PropManager fix. Added abstract BlockAndSeekItem. Created LazyLocation. Added many items for seeker/hider
This commit is contained in:
@@ -1,40 +1,43 @@
|
||||
package hdvtdev.blockandseek;
|
||||
|
||||
|
||||
import hdvtdev.blockandseek.eventListeners.RequiredEventListener;
|
||||
import hdvtdev.blockandseek.eventListeners.EventListener;
|
||||
import hdvtdev.blockandseek.eventListeners.ForceControlEventListener;
|
||||
import hdvtdev.blockandseek.eventListeners.RequiredEventListener;
|
||||
import hdvtdev.blockandseek.items.Pistol;
|
||||
import hdvtdev.blockandseek.managers.*;
|
||||
import hdvtdev.blockandseek.objects.*;
|
||||
import hdvtdev.blockandseek.roulette.RouletteCreator;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import me.libraryaddict.disguise.LibsDisguises;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.incendo.cloud.bukkit.CloudBukkitCapabilities;
|
||||
import org.incendo.cloud.bukkit.parser.location.LocationParser;
|
||||
import org.incendo.cloud.execution.ExecutionCoordinator;
|
||||
import org.incendo.cloud.paper.LegacyPaperCommandManager;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BlockAndSeek extends JavaPlugin {
|
||||
|
||||
private static JavaPlugin javaPlugin;
|
||||
@@ -61,32 +64,41 @@ public class BlockAndSeek extends JavaPlugin {
|
||||
return javaPlugin.getLogger();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
javaPlugin = this;
|
||||
|
||||
LibsDisguises libsDisguises = (LibsDisguises) Bukkit.getPluginManager().getPlugin("LibsDisguises");
|
||||
LibsDisguises libsDisguises =
|
||||
(LibsDisguises) Bukkit.getPluginManager().getPlugin(
|
||||
"LibsDisguises"
|
||||
);
|
||||
if (libsDisguises == null) {
|
||||
getLogger().severe("LibsDisguises not found! It's required for the plugin to work!");
|
||||
getLogger().severe(
|
||||
"LibsDisguises not found! It's required for the plugin to work!"
|
||||
);
|
||||
super.onDisable();
|
||||
}
|
||||
|
||||
this.init();
|
||||
|
||||
PluginCommand command = Objects.requireNonNull(getCommand("blockandseek"));
|
||||
PluginCommand command = Objects.requireNonNull(
|
||||
getCommand("blockandseek")
|
||||
);
|
||||
|
||||
PluginManager manager = getServer().getPluginManager();
|
||||
boolean forceControl = Config.forceControl();
|
||||
if (forceControl) getLogger().info("Using force control");
|
||||
manager.registerEvents(forceControl ? new ForceControlEventListener() : new EventListener(), this);
|
||||
manager.registerEvents(
|
||||
forceControl
|
||||
? new ForceControlEventListener()
|
||||
: new EventListener(),
|
||||
this
|
||||
);
|
||||
manager.registerEvents(new RequiredEventListener(), this);
|
||||
}
|
||||
|
||||
|
||||
private void init() {
|
||||
try {
|
||||
|
||||
File dataFolder = getDataFolder();
|
||||
|
||||
if (!dataFolder.exists()) {
|
||||
@@ -109,105 +121,224 @@ public class BlockAndSeek extends JavaPlugin {
|
||||
saveResource("languages/en_US.yml", false);
|
||||
}
|
||||
|
||||
MapsManager.loadMaps();
|
||||
|
||||
TranslationManager.loadLanguages();
|
||||
MapsManager.loadMaps();
|
||||
|
||||
commandManager = LegacyPaperCommandManager.createNative(
|
||||
this,
|
||||
ExecutionCoordinator.simpleCoordinator()
|
||||
this,
|
||||
ExecutionCoordinator.simpleCoordinator()
|
||||
);
|
||||
|
||||
|
||||
if (commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
|
||||
if (
|
||||
commandManager.hasCapability(
|
||||
CloudBukkitCapabilities.NATIVE_BRIGADIER
|
||||
)
|
||||
) {
|
||||
try {
|
||||
commandManager.registerBrigadier();
|
||||
} catch (IllegalStateException ignored) {
|
||||
|
||||
}
|
||||
} catch (IllegalStateException ignored) {}
|
||||
}
|
||||
|
||||
this.registerCommands();
|
||||
|
||||
} catch (Exception e) {
|
||||
getLogger().severe("Cloud err: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private final PropManager propManager = new PropManager();
|
||||
private static final UUID ZOOM_UUID = UUID.randomUUID();
|
||||
|
||||
private void registerCommands() {
|
||||
|
||||
var root = commandManager.commandBuilder("blockandseek");
|
||||
|
||||
var editBase = root
|
||||
.literal("editMap")
|
||||
.required("map_name", StringParser.stringParser(), MapsManager.mapSuggestions);
|
||||
.literal("editMap")
|
||||
.required(
|
||||
"map_name",
|
||||
StringParser.stringParser(),
|
||||
MapsManager.mapSuggestions
|
||||
);
|
||||
|
||||
//edit commands
|
||||
|
||||
|
||||
commandManager.command(
|
||||
editBase.literal("setLobby") // Это наш <parameter> как литерал
|
||||
.required("location", LocationParser.locationParser())
|
||||
.handler(ctx -> {
|
||||
|
||||
})
|
||||
editBase
|
||||
.literal("setLobby")
|
||||
.required("location", LocationParser.locationParser())
|
||||
.handler(ctx -> {})
|
||||
);
|
||||
|
||||
commandManager.command(
|
||||
editBase.literal("setLocation")
|
||||
.required("location", LocationParser.locationParser()) // Это <value>
|
||||
.handler(ctx -> {
|
||||
String configName = ctx.get("config_name");
|
||||
Location location = ctx.get("location");
|
||||
|
||||
ctx.sender().sendMessage("В конфиге " + configName + " точка установлена: " + location.toString());
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(root
|
||||
.literal("maps")
|
||||
editBase
|
||||
.literal("setLocation")
|
||||
.required("location", LocationParser.locationParser())
|
||||
.handler(ctx -> {
|
||||
ctx.sender().sendMessage(MapsManager.getMaps().stream().map(BlockAndSeekMap::getWorld).collect(Collectors.joining(", ")));
|
||||
String configName = ctx.get("config_name");
|
||||
Location location = ctx.get("location");
|
||||
|
||||
ctx
|
||||
.sender()
|
||||
.sendMessage(
|
||||
"В конфиге " +
|
||||
configName +
|
||||
" точка установлена: " +
|
||||
location.toString()
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(root
|
||||
|
||||
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("testMessage")
|
||||
.handler(ctx -> {
|
||||
ctx.sender().sendMessage(MiniMessage.miniMessage().deserialize(" <gradient:#FFAA00:#FFD700><bold>System</bold></gradient> <dark_gray>»</dark_gray> <yellow>Ваш игровой режим изменен.</yellow>\n"));
|
||||
ctx
|
||||
.sender()
|
||||
.sendMessage(
|
||||
MiniMessage.miniMessage().deserialize(
|
||||
" <gradient:#FFAA00:#FFD700><bold>System</bold></gradient> <dark_gray>»</dark_gray> <yellow>Ваш игровой режим изменен.</yellow>\n"
|
||||
)
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(root
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("testGlow")
|
||||
.handler(ctx -> {
|
||||
if (ctx.sender() instanceof Player player) {
|
||||
RayTraceResult result = player.rayTraceBlocks(128);
|
||||
if (result != null) {
|
||||
Block block = result.getHitBlock();
|
||||
if (block != null) {
|
||||
GlowUtil.highlightBlock(player, block.getLocation().toBlockLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("menuTest")
|
||||
.handler(ctx -> {
|
||||
if (ctx.sender() instanceof Player player) {
|
||||
player.getInventory().addItem(ItemManager.getMenuItem());
|
||||
player
|
||||
.getInventory()
|
||||
.addItem(ItemManager.getItem(Items.MENU).getTranslated(player));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("morphItem")
|
||||
.handler(ctx -> {
|
||||
if (ctx.sender() instanceof Player player) {
|
||||
player
|
||||
.getInventory()
|
||||
.addItem(ItemManager.getItem(Items.MORPH).getTranslated(player));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(root
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("pistolGet")
|
||||
.handler(ctx -> {
|
||||
if (ctx.sender() instanceof Player player) {
|
||||
player
|
||||
.getInventory()
|
||||
.addItem(ItemManager.getItem(Items.PISTOL).getTranslated(player));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("clear")
|
||||
.handler(ctx -> {
|
||||
if (ctx.sender() instanceof Player player) {
|
||||
AttributeInstance attribute = player.getAttribute(
|
||||
Attribute.GENERIC_MOVEMENT_SPEED
|
||||
);
|
||||
|
||||
if (
|
||||
attribute != null &&
|
||||
attribute.getModifier(ZOOM_UUID) != null
|
||||
) {
|
||||
attribute.removeModifier(ZOOM_UUID);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("pistolTest")
|
||||
.handler(ctx -> {
|
||||
if (ctx.sender() instanceof Player player) {
|
||||
player.getInventory().addItem(ItemManager.getItem(Items.MORPH).getTranslated(player));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("grenadeTest")
|
||||
.handler(ctx -> {
|
||||
if (ctx.sender() instanceof Player player) {
|
||||
player.getInventory().addItem(ItemManager.getItem(Items.GRENADE).getTranslated(player));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("reload")
|
||||
.handler(ctx -> {
|
||||
var sender = ctx.sender();
|
||||
if (Config.loadConfig()) {
|
||||
MapsManager.loadMaps();
|
||||
TranslationManager.loadLanguages();
|
||||
sender.sendMessage("Configs were reloaded!");
|
||||
} else sender.sendMessage("Failed to reload configs! Check server logs.");
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("configTest")
|
||||
.handler(ctx -> ctx.sender().sendMessage(Config.toStaticString()))
|
||||
);
|
||||
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("localeTest")
|
||||
.handler(ctx -> {
|
||||
if (ctx.sender() instanceof Player player) {
|
||||
player.sendMessage("Locale is: " + player.locale());
|
||||
player.sendMessage(TranslationManager.get(player, TranslationKey.FREEZE_ITEM));
|
||||
player.sendMessage(
|
||||
TranslationManager.get(
|
||||
player,
|
||||
TranslationKey.FREEZE_ITEM
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
commandManager.command(root
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("createGame")
|
||||
.permission(perm)
|
||||
.required("map_name", StringParser.stringParser(), MapsManager.mapSuggestions)
|
||||
.required(
|
||||
"map_name",
|
||||
StringParser.stringParser(),
|
||||
MapsManager.mapSuggestions
|
||||
)
|
||||
.handler(context -> {
|
||||
String name = context.get("map_name");
|
||||
GamesManager.createGame(name);
|
||||
@@ -217,18 +348,11 @@ public class BlockAndSeek extends JavaPlugin {
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(root
|
||||
.literal("createMap")
|
||||
.permission(perm)
|
||||
.required("map_name", StringParser.stringParser(), MapsManager.worldSuggestions)
|
||||
.handler(context -> {
|
||||
String name = context.get("map_name");
|
||||
MapsManager.createMap(name);
|
||||
context.sender().sendMessage("Map probably created");
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(root
|
||||
|
||||
|
||||
commandManager.command(
|
||||
root
|
||||
.literal("joinGame")
|
||||
.permission(perm)
|
||||
.required("name", StringParser.stringParser())
|
||||
@@ -241,93 +365,10 @@ public class BlockAndSeek extends JavaPlugin {
|
||||
})
|
||||
);
|
||||
|
||||
commandManager.command(
|
||||
editBase.literal("generateBlocks")
|
||||
.handler(ctx -> {
|
||||
if (ctx.sender() instanceof Player player) {
|
||||
|
||||
String mapName = ctx.get("map_name");
|
||||
BlockAndSeekMap map = MapsManager.getMap(mapName);
|
||||
|
||||
var cached = BlocksGenerator.get(map.getSpawn().getWorld().getName());
|
||||
|
||||
if (cached != null) {
|
||||
new RouletteCreator(player, cached);
|
||||
} else {
|
||||
BlocksGenerator.getSortedBlockStats(player.getLocation(), 32, (var list) -> {
|
||||
|
||||
List<Map.Entry<Material, Long>> selectedBlocks = new ArrayList<>(list);
|
||||
|
||||
// 2. Перемешиваем и берем 30 случайных (или меньше, если всего блоков меньше 30)
|
||||
Collections.shuffle(selectedBlocks);
|
||||
if (selectedBlocks.size() > 30) {
|
||||
selectedBlocks = selectedBlocks.subList(0, 30);
|
||||
}
|
||||
|
||||
selectedBlocks.sort((a, b) -> Long.compare(b.getValue(), a.getValue()));
|
||||
|
||||
List<Map.Entry<Material, Rarity>> result = new ArrayList<>();
|
||||
|
||||
// 4. Считаем общий вес редкостей (100 + 50 + 25 + ...) = 189
|
||||
int totalWeight = Arrays.stream(Rarity.values()).mapToInt(Rarity::getChance).sum();
|
||||
|
||||
// Шаг веса на один блок.
|
||||
// Представь длинную полоску длиной 189 единиц. Мы режем её на 30 равных частей.
|
||||
// Куда попадает разрез — такая и редкость.
|
||||
double weightStep = (double) totalWeight / selectedBlocks.size();
|
||||
|
||||
double currentWeightPosition = 0; // Текущая позиция на шкале весов
|
||||
|
||||
// Идем по отсортированному списку (от самых частых к самым редким)
|
||||
for (Map.Entry<Material, Long> entry : selectedBlocks) {
|
||||
|
||||
// Определяем, в какой диапазон редкости попадает текущий блок
|
||||
Rarity assignedRarity = Rarity.COMMON; // Дефолт
|
||||
|
||||
int weightCursor = 0;
|
||||
for (Rarity r : Rarity.values()) {
|
||||
weightCursor += r.getChance();
|
||||
// Если текущая позиция веса меньше границы этой редкости — мы нашли её
|
||||
// (Добавляем половину шага, чтобы брать "центр" диапазона блока для точности)
|
||||
if ((currentWeightPosition + weightStep / 2) <= weightCursor) {
|
||||
assignedRarity = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.add(new AbstractMap.SimpleEntry<>(entry.getKey(), assignedRarity));
|
||||
|
||||
// Сдвигаемся дальше по шкале
|
||||
currentWeightPosition += weightStep;
|
||||
}
|
||||
|
||||
|
||||
var r = result.stream().map(e -> new PropBlock(new ItemStack(e.getKey()), e.getValue())).toList();
|
||||
map.setBlocks(r);
|
||||
|
||||
map.save();
|
||||
BlocksGenerator.addCache(player.getLocation().getWorld().getName(), r);
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void spawnSmokeCloud(Location center) {
|
||||
|
||||
new BukkitRunnable() {
|
||||
int ticksPassed = 0;
|
||||
|
||||
@@ -343,20 +384,35 @@ public class BlockAndSeek extends JavaPlugin {
|
||||
World world = center.getWorld();
|
||||
if (world == null) return;
|
||||
|
||||
world.spawnParticle(
|
||||
Particle.EXPLOSION,
|
||||
center,
|
||||
15,
|
||||
1.2,
|
||||
1.2,
|
||||
1.2,
|
||||
0.05
|
||||
);
|
||||
|
||||
world.spawnParticle(Particle.EXPLOSION_HUGE, center, 15, 1.2, 1.2, 1.2, 0.05);
|
||||
|
||||
|
||||
|
||||
for (var entity : world.getNearbyEntities(center, 2.5, 2.5, 2.5)) {
|
||||
if (entity instanceof Player player && player.getLocation().distanceSquared(center) <= 9) {
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 40, 1));
|
||||
for (var entity : world.getNearbyEntities(
|
||||
center,
|
||||
2.5,
|
||||
2.5,
|
||||
2.5
|
||||
)) {
|
||||
if (
|
||||
entity instanceof Player player &&
|
||||
player.getLocation().distanceSquared(center) <= 9
|
||||
) {
|
||||
player.addPotionEffect(
|
||||
new PotionEffect(PotionEffectType.BLINDNESS, 40, 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ticksPassed++;
|
||||
}
|
||||
}.runTaskTimer(this, 0L, 5L);
|
||||
}
|
||||
.runTaskTimer(this, 0L, 5L);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,26 +4,39 @@ import eu.okaeri.configs.ConfigManager;
|
||||
import eu.okaeri.configs.OkaeriConfig;
|
||||
import eu.okaeri.configs.annotation.Comment;
|
||||
import eu.okaeri.configs.annotation.Exclude;
|
||||
import eu.okaeri.configs.exception.OkaeriException;
|
||||
import eu.okaeri.configs.serdes.commons.SerdesCommons;
|
||||
import eu.okaeri.configs.yaml.bukkit.YamlBukkitConfigurer;
|
||||
import eu.okaeri.configs.yaml.bukkit.serdes.SerdesBukkit;
|
||||
|
||||
import hdvtdev.blockandseek.objects.LazyLocation;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.WorldCreator;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Config extends OkaeriConfig {
|
||||
|
||||
static {
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
@Exclude
|
||||
private static Config config;
|
||||
|
||||
static {
|
||||
@Comment("Server options.")
|
||||
private ServerSettings serverSettings = new ServerSettings();
|
||||
@Comment("Spawn location. Useless if the Server.forceControl is false.")
|
||||
private LazyLocation spawn = new LazyLocation("world");
|
||||
@Comment("Show hidden BlockAndSeek commands.")
|
||||
private boolean enableDebugCommands = false;
|
||||
|
||||
public static boolean loadConfig() {
|
||||
try {
|
||||
File configFile = new File(BlockAndSeek.getPluginDataFolder(), "config.yml");
|
||||
if (!configFile.exists()) configFile.createNewFile();
|
||||
config = ConfigManager.create(Config.class, (it) -> {
|
||||
it.withConfigurer(
|
||||
new YamlBukkitConfigurer(),
|
||||
@@ -33,23 +46,16 @@ public class Config extends OkaeriConfig {
|
||||
it.withBindFile(configFile);
|
||||
it.withLogger(BlockAndSeek.getPluginLogger());
|
||||
it.saveDefaults();
|
||||
it.load(true);
|
||||
});
|
||||
|
||||
config.load();
|
||||
config.save();
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
} catch (OkaeriException e) {
|
||||
BlockAndSeek.getPluginLogger().severe("Failed to load config.yml: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Comment("Server options.")
|
||||
private ServerSettings serverSettings = new ServerSettings();
|
||||
@Comment("Spawn location. Useless if the Server.forceControl is false.")
|
||||
private Location spawn = Objects.requireNonNull(Bukkit.createWorld(new WorldCreator("world"))).getSpawnLocation();
|
||||
@Comment("Show hidden BlockAndSeek commands.")
|
||||
private boolean enableDebugCommands = false;
|
||||
|
||||
|
||||
public static boolean debugEnabled() {
|
||||
return config.enableDebugCommands;
|
||||
@@ -60,7 +66,7 @@ public class Config extends OkaeriConfig {
|
||||
}
|
||||
|
||||
public static Location spawn() {
|
||||
return config.spawn;
|
||||
return config.spawn.getLocation();
|
||||
}
|
||||
|
||||
public static String toStaticString() {
|
||||
|
||||
83
src/main/java/hdvtdev/blockandseek/GlowUtil.java
Normal file
83
src/main/java/hdvtdev/blockandseek/GlowUtil.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package hdvtdev.blockandseek;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class GlowUtil {
|
||||
|
||||
public static int highlightBlock(Player viewer, Location blockLoc) {
|
||||
int entityId = -ThreadLocalRandom.current().nextInt(10000, Integer.MAX_VALUE);
|
||||
UUID uuid = UUID.randomUUID();
|
||||
|
||||
Vector3d position = new Vector3d(
|
||||
blockLoc.getX(),
|
||||
blockLoc.getY(),
|
||||
blockLoc.getZ()
|
||||
);
|
||||
|
||||
WrapperPlayServerSpawnEntity spawnPacket = new WrapperPlayServerSpawnEntity(
|
||||
entityId,
|
||||
Optional.of(uuid),
|
||||
EntityTypes.INTERACTION,
|
||||
position,
|
||||
0f, 0f, 0f,
|
||||
0,
|
||||
Optional.empty()
|
||||
);
|
||||
|
||||
List<EntityData<?>> metaDataList = new ArrayList<>();
|
||||
|
||||
byte flags = (byte) 0x40;
|
||||
metaDataList.add(new EntityData<>(0, EntityDataTypes.BYTE, flags));
|
||||
metaDataList.add(new EntityData<>(8, EntityDataTypes.FLOAT, 1.0f));
|
||||
metaDataList.add(new EntityData<>(9, EntityDataTypes.FLOAT, 1.0f));
|
||||
|
||||
WrapperPlayServerEntityMetadata metadataPacket = new WrapperPlayServerEntityMetadata(entityId, metaDataList);
|
||||
|
||||
PacketEvents.getAPI().getPlayerManager().sendPacket(viewer, spawnPacket);
|
||||
PacketEvents.getAPI().getPlayerManager().sendPacket(viewer, metadataPacket);
|
||||
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public static void removeGlow(Player viewer, int entityId) {
|
||||
WrapperPlayServerDestroyEntities destroyPacket = new WrapperPlayServerDestroyEntities(new int[]{entityId});
|
||||
PacketEvents.getAPI().getPlayerManager().sendPacket(viewer, destroyPacket);
|
||||
}
|
||||
|
||||
public static void setPlayerGlowing(Player viewer, Player target, boolean glowing) {
|
||||
List<EntityData<?>> metaDataList = new ArrayList<>();
|
||||
|
||||
byte flags = 0;
|
||||
if (target.getFireTicks() > 0) flags |= 0x01;
|
||||
if (target.isSneaking()) flags |= 0x02;
|
||||
if (target.isSprinting()) flags |= 0x08;
|
||||
if (target.isSwimming()) flags |= 0x10;
|
||||
if (target.isInvisible()) flags |= 0x20;
|
||||
|
||||
if (glowing) {
|
||||
flags |= 0x40;
|
||||
} else {
|
||||
if (target.isGlowing()) flags |= 0x40;
|
||||
}
|
||||
|
||||
if (target.isGliding()) flags |= (byte) 0x80;
|
||||
|
||||
metaDataList.add(new EntityData<>(0, EntityDataTypes.BYTE, flags));
|
||||
|
||||
WrapperPlayServerEntityMetadata metadataPacket = new WrapperPlayServerEntityMetadata(target.getEntityId(), metaDataList);
|
||||
PacketEvents.getAPI().getPlayerManager().sendPacket(viewer, metadataPacket);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ public class Keys {
|
||||
public static final NamespacedKey FACE_CHANGING_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekFaceChangingItem");
|
||||
public static final NamespacedKey MENU_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekMenuItem");
|
||||
public static final NamespacedKey LEAVE_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekLeaveItem");
|
||||
public static final NamespacedKey PISTOL = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekPistol");
|
||||
|
||||
public static final Team NO_COLLIDE_TEAM;
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package hdvtdev.blockandseek;
|
||||
|
||||
|
||||
import hdvtdev.blockandseek.managers.PropManager;
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
|
||||
public final class Utils {
|
||||
|
||||
@@ -18,6 +18,20 @@ public final class Utils {
|
||||
p.setExp(0.9998f * ((float) level / 100));
|
||||
}
|
||||
|
||||
public static void damageSeeker(Player seeker, int damage) {
|
||||
seeker.damage(damage);
|
||||
setLevelWithBar(seeker, (int) (seeker.getHealth() * 5));
|
||||
}
|
||||
|
||||
public static void healSeeker(Player player, double heal) {
|
||||
double currentHealth = player.getHealth();
|
||||
if (currentHealth < 20) {
|
||||
double newHealth = Math.min(currentHealth + heal, 20);
|
||||
player.setHealth(newHealth);
|
||||
setLevelWithBar(player, (int) Math.round(player.getHealth() * 5));
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearPlayer(Player player) {
|
||||
|
||||
DisguiseAPI.undisguiseToAll(player);
|
||||
@@ -25,7 +39,7 @@ public final class Utils {
|
||||
player.getInventory().clear();
|
||||
player.getInventory().setArmorContents(null);
|
||||
player.getInventory().setExtraContents(null);
|
||||
|
||||
PropManager.removePlayer(player);
|
||||
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
|
||||
@@ -38,6 +52,8 @@ public final class Utils {
|
||||
player.setSaturation(5.0f);
|
||||
player.setExhaustion(0f);
|
||||
player.setInvulnerable(false);
|
||||
player.setInvisible(false);
|
||||
player.setVisibleByDefault(true);
|
||||
player.setLevel(0);
|
||||
player.setExp(0f);
|
||||
player.setFireTicks(0);
|
||||
|
||||
@@ -7,12 +7,15 @@ import hdvtdev.blockandseek.GuiHolder;
|
||||
import hdvtdev.blockandseek.managers.PropManager;
|
||||
|
||||
import hdvtdev.blockandseek.menus.GamesMenu;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDismountEvent;
|
||||
@@ -29,6 +32,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -40,7 +44,11 @@ public class RequiredEventListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if (!Keys.NO_COLLIDE_TEAM.hasPlayer(player)) {
|
||||
Keys.NO_COLLIDE_TEAM.addPlayer(player);
|
||||
}
|
||||
//player.setResourcePack("https://gitea.hdvtdev.tech/hdvt/idk/raw/branch/main/pack.zip", "f32bf084b01b57601d7ae3711e5c88e31ce637a3", true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -48,28 +56,12 @@ public class RequiredEventListener implements Listener {
|
||||
|
||||
}
|
||||
|
||||
//todo remove
|
||||
private final PropManager propManager = new PropManager();
|
||||
private final Set<UUID> coolDown = new HashSet<>();
|
||||
|
||||
@EventHandler
|
||||
public void onRightClick(PlayerInteractEvent event) {
|
||||
if (event.getHand() != EquipmentSlot.HAND) return;
|
||||
if (event.getAction().isLeftClick()) return;
|
||||
public void onPlayerClick(PlayerInteractEvent event) {
|
||||
|
||||
Player player = event.getPlayer();
|
||||
ItemStack item = event.getItem();
|
||||
BlockAndSeekItem item = BlockAndSeekItem.tryCast(event.getItem());
|
||||
if (item != null) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (meta != null) {
|
||||
PersistentDataContainer dataContainer = meta.getPersistentDataContainer();
|
||||
if (dataContainer.has(Keys.MENU_ITEM)) {
|
||||
new GamesMenu(player);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
item.onRawInteract(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
57
src/main/java/hdvtdev/blockandseek/items/DashItem.java
Normal file
57
src/main/java/hdvtdev/blockandseek/items/DashItem.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package hdvtdev.blockandseek.items;
|
||||
|
||||
import hdvtdev.blockandseek.Keys;
|
||||
import hdvtdev.blockandseek.managers.PropManager;
|
||||
import hdvtdev.blockandseek.managers.TranslationManager;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import hdvtdev.blockandseek.objects.Items;
|
||||
import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public class DashItem extends BlockAndSeekItem {
|
||||
|
||||
|
||||
public DashItem() {
|
||||
super(Items.DASH, Duration.ofSeconds(75), ClickAction.RIGHT_CLICK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInteract(@NotNull PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Location location = player.getLocation();
|
||||
player.playSound(location, Sound.ENTITY_BAT_TAKEOFF, 1f, 1f);
|
||||
Vector direction = location.getDirection();
|
||||
//direction.setY(0).normalize();
|
||||
direction.multiply(2.0);
|
||||
direction.setY(0.4);
|
||||
player.setVelocity(direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack buildRawItem() {
|
||||
ItemStack itemStack = new ItemStack(Material.LAPIS_LAZULI);
|
||||
itemStack.editMeta(itemMeta -> {
|
||||
itemMeta.addEnchant(Enchantment.INFINITY, 1, true);
|
||||
itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
});
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getTranslated(Player player) {
|
||||
return TranslationManager.translateItem(player, getCloned(), TranslationKey.DASH_ITEM);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package hdvtdev.blockandseek.items;
|
||||
|
||||
import hdvtdev.blockandseek.Keys;
|
||||
import hdvtdev.blockandseek.managers.PropManager;
|
||||
import hdvtdev.blockandseek.managers.TranslationManager;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import hdvtdev.blockandseek.objects.Items;
|
||||
import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public class FaceChangingItem extends BlockAndSeekItem {
|
||||
public FaceChangingItem() {
|
||||
super(Items.FACE_CHANGING, Duration.ZERO, ClickAction.RIGHT_CLICK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInteract(@NotNull PlayerInteractEvent event) {
|
||||
PropManager.changePropDirection(event.getPlayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack buildRawItem() {
|
||||
return new ItemStack(Material.NETHER_STAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getTranslated(Player player) {
|
||||
return TranslationManager.translateItem(player, getCloned(), TranslationKey.FACE_CHANGING_ITEM);
|
||||
}
|
||||
}
|
||||
40
src/main/java/hdvtdev/blockandseek/items/FreezeItem.java
Normal file
40
src/main/java/hdvtdev/blockandseek/items/FreezeItem.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package hdvtdev.blockandseek.items;
|
||||
|
||||
import hdvtdev.blockandseek.managers.PropManager;
|
||||
import hdvtdev.blockandseek.managers.TranslationManager;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import hdvtdev.blockandseek.objects.Items;
|
||||
import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public class FreezeItem extends BlockAndSeekItem {
|
||||
public FreezeItem() {
|
||||
super(Items.FREEZE, Duration.ofMillis(100), ClickAction.RIGHT_CLICK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInteract(@NotNull PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
player.sendActionBar(Component.text(PropManager.freezeOrUnfreeze(player).toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack buildRawItem() {
|
||||
ItemStack itemStack = new ItemStack(Material.HEART_OF_THE_SEA);
|
||||
itemStack.editMeta(itemMeta -> itemMeta.addEnchant(Enchantment.INFINITY, 1, true));
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getTranslated(Player player) {
|
||||
return TranslationManager.translateItem(player, getCloned(), TranslationKey.FREEZE_ITEM);
|
||||
}
|
||||
}
|
||||
148
src/main/java/hdvtdev/blockandseek/items/Grenade.java
Normal file
148
src/main/java/hdvtdev/blockandseek/items/Grenade.java
Normal file
@@ -0,0 +1,148 @@
|
||||
package hdvtdev.blockandseek.items;
|
||||
|
||||
import hdvtdev.blockandseek.BlockAndSeek;
|
||||
import hdvtdev.blockandseek.Utils;
|
||||
import hdvtdev.blockandseek.managers.PropManager;
|
||||
import hdvtdev.blockandseek.managers.TranslationManager;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import hdvtdev.blockandseek.objects.Items;
|
||||
import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Grenade extends BlockAndSeekItem {
|
||||
|
||||
public Grenade() {
|
||||
super(Items.GRENADE, Duration.ofSeconds(10), ClickAction.RIGHT_CLICK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInteract(@NotNull PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
final Location location = player.getEyeLocation();
|
||||
final Vector velocity = location.getDirection().multiply(1.5);
|
||||
location.getWorld().playSound(location, Sound.BLOCK_CHAIN_STEP, 1f, 1f);
|
||||
|
||||
final ArmorStand tntVisual = location.getWorld().spawn(location, ArmorStand.class, entity -> {
|
||||
entity.setVisible(false);
|
||||
entity.setGravity(false);
|
||||
entity.setMarker(true);
|
||||
entity.setSmall(true);
|
||||
entity.getEquipment().setHelmet(new ItemStack(Material.TNT));
|
||||
});
|
||||
|
||||
new BukkitRunnable() {
|
||||
|
||||
final double gravity = 0.05;
|
||||
final double drag = 0.99;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
location.getWorld().spawnParticle(Particle.CAMPFIRE_COSY_SMOKE, location, 1, 0, 0, 0, 0);
|
||||
|
||||
Vector move = velocity.clone();
|
||||
RayTraceResult hit = location.getWorld().rayTraceBlocks(location, move, move.length());
|
||||
|
||||
if (hit != null && hit.getHitBlock() != null) {
|
||||
|
||||
tntVisual.remove();
|
||||
|
||||
|
||||
Location hitLoc = hit.getHitPosition().toLocation(location.getWorld());
|
||||
|
||||
int radius = 4;
|
||||
List<UUID> props = hitLoc.getNearbyEntities(radius, radius, radius).stream().filter(entity -> entity instanceof Player p && !p.equals(player))
|
||||
.map(Entity::getUniqueId).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
|
||||
location.getWorld().playSound(hitLoc, Sound.ENTITY_GENERIC_EXPLODE, 1f, 1f);
|
||||
location.getWorld().spawnParticle(Particle.EXPLOSION, hitLoc, 1);
|
||||
|
||||
List<Block> affectedBlocks = new ArrayList<>();
|
||||
|
||||
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int z = -radius; z <= radius; z++) {
|
||||
Block b = hitLoc.getBlock().getRelative(x, y, z);
|
||||
|
||||
if (hitLoc.distance(b.getLocation().add(0.5, 0.5, 0.5)) <= radius) {
|
||||
if (!b.getType().isAir()) {
|
||||
affectedBlocks.add(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (Block b : affectedBlocks) {
|
||||
Location blockLocation = b.getLocation();
|
||||
UUID maybeProp = PropManager.getProp(blockLocation);
|
||||
if (maybeProp != null) {
|
||||
PropManager.forceUnfreeze(maybeProp);
|
||||
props.add(maybeProp);
|
||||
}
|
||||
}
|
||||
|
||||
if (!props.isEmpty()) {
|
||||
player.playSound(player, Sound.ENTITY_ARROW_HIT_PLAYER, 1f, 1f);
|
||||
for (UUID uuid : props) {
|
||||
Player hider = Bukkit.getPlayer(uuid);
|
||||
if (hider != null) {
|
||||
hider.damage(13.5);
|
||||
Utils.healSeeker(player, 13.5);
|
||||
}
|
||||
}
|
||||
} else Utils.damageSeeker(player, 25);
|
||||
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
location.add(move);
|
||||
tntVisual.teleport(location.clone().subtract(0, 0.7, 0));
|
||||
|
||||
velocity.multiply(drag);
|
||||
velocity.setY(velocity.getY() - gravity);
|
||||
|
||||
if (location.getY() < location.getWorld().getMinHeight() || !location.getWorld().isChunkLoaded(location.getBlockX() >> 4, location.getBlockZ() >> 4)) {
|
||||
tntVisual.remove();
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(BlockAndSeek.getInstance(), 0L, 1L);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack buildRawItem() {
|
||||
ItemStack itemStack = new ItemStack(Material.FIREWORK_STAR);
|
||||
itemStack.editMeta(itemMeta -> itemMeta.addEnchant(Enchantment.INFINITY, 1, true));
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getTranslated(Player player) {
|
||||
return TranslationManager.translateItem(player, getCloned(), TranslationKey.GRENADE);
|
||||
}
|
||||
}
|
||||
4
src/main/java/hdvtdev/blockandseek/items/LeaveItem.java
Normal file
4
src/main/java/hdvtdev/blockandseek/items/LeaveItem.java
Normal file
@@ -0,0 +1,4 @@
|
||||
package hdvtdev.blockandseek.items;
|
||||
|
||||
public class LeaveItem {
|
||||
}
|
||||
38
src/main/java/hdvtdev/blockandseek/items/MenuItem.java
Normal file
38
src/main/java/hdvtdev/blockandseek/items/MenuItem.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package hdvtdev.blockandseek.items;
|
||||
|
||||
import hdvtdev.blockandseek.managers.TranslationManager;
|
||||
import hdvtdev.blockandseek.menus.GamesMenu;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import hdvtdev.blockandseek.objects.Items;
|
||||
import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class MenuItem extends BlockAndSeekItem {
|
||||
public MenuItem() {
|
||||
super(Items.MENU, ClickAction.RIGHT_CLICK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInteract(@NotNull PlayerInteractEvent event) {
|
||||
new GamesMenu(event.getPlayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack buildRawItem() {
|
||||
ItemStack itemStack = new ItemStack(Material.COMPASS);
|
||||
itemStack.editMeta(itemMeta -> itemMeta.addEnchant(Enchantment.INFINITY, 1, true));
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getTranslated(Player player) {
|
||||
return TranslationManager.translateItem(player, getCloned(), TranslationKey.MENU);
|
||||
}
|
||||
}
|
||||
51
src/main/java/hdvtdev/blockandseek/items/MorphItem.java
Normal file
51
src/main/java/hdvtdev/blockandseek/items/MorphItem.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package hdvtdev.blockandseek.items;
|
||||
|
||||
import hdvtdev.blockandseek.managers.TranslationManager;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import hdvtdev.blockandseek.objects.Items;
|
||||
import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
import me.libraryaddict.disguise.disguisetypes.MiscDisguise;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class MorphItem extends BlockAndSeekItem {
|
||||
|
||||
public MorphItem() {
|
||||
super(Items.MORPH, ClickAction.RIGHT_CLICK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInteract(@NotNull PlayerInteractEvent event) {
|
||||
Block block = event.getClickedBlock();
|
||||
Player player = event.getPlayer();
|
||||
if (block == null) {
|
||||
RayTraceResult result = player.rayTraceBlocks(128);
|
||||
if (result != null) {
|
||||
block = result.getHitBlock();
|
||||
} else return;
|
||||
}
|
||||
|
||||
if (block == null) return;
|
||||
DisguiseAPI.disguiseToAll(player, new MiscDisguise(DisguiseType.FALLING_BLOCK, new ItemStack(block.getType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack buildRawItem() {
|
||||
ItemStack itemStack = new ItemStack(Material.PHANTOM_MEMBRANE);
|
||||
itemStack.editMeta(itemMeta -> itemMeta.addEnchant(Enchantment.INFINITY, 1, true));
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getTranslated(Player player) {
|
||||
return TranslationManager.translateItem(player, getCloned(), TranslationKey.MORPH_ITEM);
|
||||
}
|
||||
}
|
||||
112
src/main/java/hdvtdev/blockandseek/items/Pistol.java
Normal file
112
src/main/java/hdvtdev/blockandseek/items/Pistol.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package hdvtdev.blockandseek.items;
|
||||
|
||||
import hdvtdev.blockandseek.Utils;
|
||||
import hdvtdev.blockandseek.managers.PropManager;
|
||||
import hdvtdev.blockandseek.managers.TranslationManager;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import hdvtdev.blockandseek.objects.Items;
|
||||
import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
public class Pistol extends BlockAndSeekItem {
|
||||
|
||||
public Pistol() {
|
||||
super(Items.PISTOL, Duration.ofMillis(750), ClickAction.RIGHT_CLICK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInteract(@NotNull PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
player.playSound(player, Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, 1.0f, 1.0f);
|
||||
|
||||
Location startLoc = player.getEyeLocation();
|
||||
Vector direction = startLoc.getDirection();
|
||||
|
||||
RayTraceResult result = player.getWorld().rayTrace(
|
||||
startLoc,
|
||||
direction,
|
||||
50,
|
||||
FluidCollisionMode.NEVER,
|
||||
true,
|
||||
0.5,
|
||||
entity -> {
|
||||
if (entity.equals(player)) return false;
|
||||
|
||||
if (entity instanceof ArmorStand) return false;
|
||||
|
||||
if (entity instanceof Player maybeProp) {
|
||||
return !PropManager.isProped(maybeProp.getUniqueId());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
Vector endPosition = result == null ? startLoc.toVector().add(direction.clone().multiply(64)) : result.getHitPosition();
|
||||
|
||||
double distance = startLoc.toVector().distance(endPosition);
|
||||
double step = 0.5;
|
||||
|
||||
for (double d = 0; d < distance; d += step) {
|
||||
Location particleLoc = startLoc.clone().add(direction.clone().multiply(d));
|
||||
player.getWorld().spawnParticle(Particle.SMOKE, particleLoc, 1, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
Entity hitEntity = result.getHitEntity();
|
||||
if (hitEntity instanceof Player target) {
|
||||
target.damage(5);
|
||||
double strength = 0.1;
|
||||
double x = -target.getLocation().getDirection().getX();
|
||||
double z = -target.getLocation().getDirection().getZ();
|
||||
target.knockback(strength, x, z);
|
||||
player.playSound(player, Sound.ENTITY_ARROW_HIT_PLAYER, 1f, 1f);
|
||||
Utils.healSeeker(player, 5);
|
||||
} else {
|
||||
Block hitBlock = result.getHitBlock();
|
||||
if (hitBlock != null) {
|
||||
UUID uuid = PropManager.getProp(hitBlock.getLocation());
|
||||
if (uuid != null) {
|
||||
Player hider = Bukkit.getPlayer(uuid);
|
||||
if (hider != null) {
|
||||
PropManager.forceUnfreeze(hider);
|
||||
player.playSound(player, Sound.ENTITY_ARROW_HIT_PLAYER, 1f, 1f);
|
||||
hider.damage(5);
|
||||
Utils.healSeeker(player, 5);
|
||||
}
|
||||
} else {
|
||||
Utils.damageSeeker(player, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack buildRawItem() {
|
||||
return new ItemStack(Material.BLACK_DYE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getTranslated(Player player) {
|
||||
return TranslationManager.translateItem(player, getCloned(), TranslationKey.PISTOL);
|
||||
}
|
||||
}
|
||||
73
src/main/java/hdvtdev/blockandseek/items/SoundMaker.java
Normal file
73
src/main/java/hdvtdev/blockandseek/items/SoundMaker.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package hdvtdev.blockandseek.items;
|
||||
|
||||
import hdvtdev.blockandseek.Keys;
|
||||
import hdvtdev.blockandseek.managers.TranslationManager;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import hdvtdev.blockandseek.objects.Items;
|
||||
import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
|
||||
public class SoundMaker extends BlockAndSeekItem {
|
||||
|
||||
private static final List<Sound> SHORT_SOUNDS = List.of(
|
||||
Sound.ENTITY_CHICKEN_AMBIENT,
|
||||
Sound.BLOCK_GLASS_BREAK,
|
||||
Sound.ENTITY_PLAYER_SPLASH,
|
||||
Sound.ENTITY_SHULKER_AMBIENT,
|
||||
Sound.ENTITY_WITCH_AMBIENT,
|
||||
Sound.BLOCK_BELL_USE,
|
||||
Sound.ENTITY_VILLAGER_AMBIENT,
|
||||
Sound.ENTITY_SNIFFER_HAPPY,
|
||||
Sound.ENTITY_PIG_DEATH,
|
||||
Sound.ENTITY_PIG_AMBIENT,
|
||||
Sound.ENTITY_GOAT_SCREAMING_PREPARE_RAM,
|
||||
Sound.ENTITY_GOAT_SCREAMING_DEATH,
|
||||
Sound.ENTITY_LLAMA_SPIT,
|
||||
Sound.ENTITY_CAT_PURREOW,
|
||||
Sound.ENTITY_SHEEP_AMBIENT
|
||||
);
|
||||
|
||||
|
||||
public SoundMaker() {
|
||||
super(Items.SOUND_MAKER, Duration.ofMillis(1750), ClickAction.RIGHT_CLICK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInteract(@NotNull PlayerInteractEvent event) {
|
||||
Sound sound = SHORT_SOUNDS.get(ThreadLocalRandom.current().nextInt(0, SHORT_SOUNDS.size()));
|
||||
Player player = event.getPlayer();
|
||||
player.getWorld().playSound(player.getLocation(), sound, 1.75f, 1.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack buildRawItem() {
|
||||
ItemStack itemStack = new ItemStack(Material.BROWN_DYE);
|
||||
itemStack.editMeta(soundMeta -> {
|
||||
soundMeta.getPersistentDataContainer().set(Keys.SOUND_ITEM, PersistentDataType.BOOLEAN, true);
|
||||
soundMeta.addEnchant(Enchantment.INFINITY, 1, true);
|
||||
soundMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
});
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getTranslated(Player player) {
|
||||
return TranslationManager.translateItem(player, getCloned(), TranslationKey.SOUND_ITEM);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package hdvtdev.blockandseek.managers;
|
||||
|
||||
import hdvtdev.blockandseek.roulette.RouletteList;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FrecamManager {
|
||||
|
||||
private final RouletteList<UUID> hiders;
|
||||
private static final HashMap<UUID, Location> playerLocations = new HashMap<>();
|
||||
|
||||
public FrecamManager(List<UUID> hiders) {
|
||||
this.hiders = new RouletteList<>(hiders);
|
||||
}
|
||||
|
||||
public void teleportToNext(@NotNull Player player) {
|
||||
Player target = Bukkit.getPlayer(hiders.next());
|
||||
if (target != null) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
Location location = target.getLocation();
|
||||
if (!playerLocations.containsKey(uuid)) {
|
||||
playerLocations.put(uuid, player.getLocation());
|
||||
}
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -27,16 +27,12 @@ public class GamesManager {
|
||||
return games.keySet();
|
||||
}
|
||||
|
||||
public static @Nullable BlockAndSeekGame createGame(String name) {
|
||||
public static BlockAndSeekGame createGame(String name) {
|
||||
|
||||
BlockAndSeekMap map = MapsManager.getMap(name);
|
||||
if (map != null) {
|
||||
BlockAndSeekGame game = new BlockAndSeekGame(name, map);
|
||||
games.put(name, game);
|
||||
return game;
|
||||
}
|
||||
|
||||
return null;
|
||||
BlockAndSeekGame game = new BlockAndSeekGame(name, map);
|
||||
games.put(name, game);
|
||||
return game;
|
||||
}
|
||||
|
||||
public static void remove(String name) {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package hdvtdev.blockandseek.managers;
|
||||
|
||||
import hdvtdev.blockandseek.Keys;
|
||||
import hdvtdev.blockandseek.items.*;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import hdvtdev.blockandseek.objects.Items;
|
||||
import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
import lombok.Getter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
@@ -15,19 +18,32 @@ import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static hdvtdev.blockandseek.objects.TranslationKey.*;
|
||||
|
||||
public class ItemManager {
|
||||
|
||||
@Getter
|
||||
private static final ItemStack freezeItem = new ItemStack(Material.HEART_OF_THE_SEA);
|
||||
@Getter
|
||||
private static final ItemStack faceChangingItem = new ItemStack(Material.NETHER_STAR);
|
||||
@Getter
|
||||
private static final ItemStack dashItem = new ItemStack(Material.LAPIS_LAZULI);
|
||||
@Getter
|
||||
private static final ItemStack soundItem = new ItemStack(Material.BROWN_DYE);
|
||||
|
||||
private static final Map<Items, BlockAndSeekItem> items = new EnumMap<>(Items.class);
|
||||
|
||||
static {
|
||||
items.put(Items.MORPH, new MorphItem());
|
||||
items.put(Items.MENU, new MenuItem());
|
||||
items.put(Items.DASH, new DashItem());
|
||||
items.put(Items.SOUND_MAKER, new SoundMaker());
|
||||
items.put(Items.FACE_CHANGING, new FaceChangingItem());
|
||||
items.put(Items.PISTOL, new Pistol());
|
||||
items.put(Items.GRENADE, new Grenade());
|
||||
items.put(Items.FREEZE, new FreezeItem());
|
||||
|
||||
}
|
||||
|
||||
public static BlockAndSeekItem getItem(Items item) {
|
||||
return items.get(item);
|
||||
}
|
||||
|
||||
private static final ItemStack seekerSword = new ItemStack(Material.WOODEN_SWORD);
|
||||
private static final ItemStack seekerHelmet = new ItemStack(Material.LEATHER_HELMET);
|
||||
@@ -35,57 +51,26 @@ public class ItemManager {
|
||||
private static final ItemStack seekerLeggings = new ItemStack(Material.LEATHER_LEGGINGS);
|
||||
private static final ItemStack seekerBoots = new ItemStack(Material.LEATHER_BOOTS);
|
||||
|
||||
@Getter
|
||||
private static final ItemStack menuItem = new ItemStack(Material.COMPASS);
|
||||
@Getter
|
||||
private static final ItemStack games = new ItemStack(Material.BOOKSHELF);
|
||||
@Getter
|
||||
private static final ItemStack createGameButton = new ItemStack(Material.SLIME_BALL);
|
||||
@Getter
|
||||
private static final ItemStack leaveItem = new ItemStack(Material.RED_DYE);
|
||||
|
||||
|
||||
static {
|
||||
|
||||
ItemMeta freezeMeta = freezeItem.getItemMeta();
|
||||
freezeMeta.getPersistentDataContainer().set(Keys.FREEZE_ITEM, PersistentDataType.BOOLEAN, true);
|
||||
freezeItem.setItemMeta(freezeMeta);
|
||||
|
||||
ItemMeta faceChangingMeta = faceChangingItem.getItemMeta();
|
||||
faceChangingMeta.getPersistentDataContainer().set(Keys.FACE_CHANGING_ITEM, PersistentDataType.BOOLEAN, true);
|
||||
faceChangingItem.setItemMeta(faceChangingMeta);
|
||||
|
||||
ItemMeta swordMeta = seekerSword.getItemMeta();
|
||||
swordMeta.addEnchant(Enchantment.DAMAGE_ALL, 2, false);
|
||||
swordMeta.addEnchant(Enchantment.SHARPNESS, 2, false);
|
||||
swordMeta.setUnbreakable(true);
|
||||
swordMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES);
|
||||
seekerSword.setItemMeta(swordMeta);
|
||||
|
||||
ItemMeta menuMeta = menuItem.getItemMeta();
|
||||
menuMeta.getPersistentDataContainer().set(Keys.MENU_ITEM, PersistentDataType.BOOLEAN, true);
|
||||
menuMeta.addEnchant(Enchantment.ARROW_INFINITE, 1, true);
|
||||
menuMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
menuItem.setItemMeta(menuMeta);
|
||||
|
||||
ItemMeta dashMeta = dashItem.getItemMeta();
|
||||
dashMeta.getPersistentDataContainer().set(Keys.DASH_ITEM, PersistentDataType.BOOLEAN, true);
|
||||
dashMeta.addEnchant(Enchantment.ARROW_INFINITE, 1, true);
|
||||
dashMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
dashItem.setItemMeta(dashMeta);
|
||||
|
||||
ItemMeta soundMeta = soundItem.getItemMeta();
|
||||
soundMeta.getPersistentDataContainer().set(Keys.SOUND_ITEM, PersistentDataType.BOOLEAN, true);
|
||||
soundMeta.addEnchant(Enchantment.ARROW_INFINITE, 1, true);
|
||||
soundMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
soundItem.setItemMeta(soundMeta);
|
||||
|
||||
ItemMeta gamesMeta = games.getItemMeta();
|
||||
games.setItemMeta(gamesMeta);
|
||||
|
||||
ItemMeta leaveMeta = leaveItem.getItemMeta();
|
||||
leaveMeta.getPersistentDataContainer().set(Keys.LEAVE_ITEM, PersistentDataType.BOOLEAN, true);
|
||||
leaveItem.setItemMeta(leaveMeta);
|
||||
|
||||
ItemMeta createGameButtonMeta = createGameButton.getItemMeta();
|
||||
createGameButton.setItemMeta(createGameButtonMeta);
|
||||
|
||||
@@ -100,7 +85,11 @@ public class ItemManager {
|
||||
public static void setSeekerSet(Player seeker) {
|
||||
PlayerInventory inventory = seeker.getInventory();
|
||||
inventory.clear();
|
||||
inventory.addItem(TranslationManager.translateItem(seeker, seekerSword, TranslationKey.SEEKER_TEMPLATE));
|
||||
inventory.addItem(TranslationManager.translateItem(seeker, seekerSword, TranslationKey.SEEKER_TEMPLATE),
|
||||
getItem(Items.DASH).getTranslated(seeker),
|
||||
getItem(Items.PISTOL).getTranslated(seeker),
|
||||
getItem(Items.GRENADE).getTranslated(seeker)
|
||||
);
|
||||
ItemStack[] armor = new ItemStack[]{
|
||||
TranslationManager.translateItem(seeker, seekerBoots, TranslationKey.SEEKER_TEMPLATE),
|
||||
TranslationManager.translateItem(seeker, seekerLeggings, TranslationKey.SEEKER_TEMPLATE),
|
||||
@@ -117,7 +106,7 @@ public class ItemManager {
|
||||
LeatherArmorMeta meta = (LeatherArmorMeta) item.getItemMeta();
|
||||
meta.setColor(Color.RED);
|
||||
meta.setUnbreakable(true);
|
||||
meta.addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 10, true);
|
||||
meta.addEnchant(Enchantment.PROTECTION, 10, true);
|
||||
meta.addEnchant(Enchantment.THORNS, 3, true);
|
||||
|
||||
return meta;
|
||||
@@ -126,25 +115,18 @@ public class ItemManager {
|
||||
public static void defaultInventory(Player player) {
|
||||
PlayerInventory inventory = player.getInventory();
|
||||
inventory.clear();
|
||||
inventory.addItem(TranslationManager.translateItem(player, menuItem, TranslationKey.MENU));
|
||||
inventory.addItem(getItem(Items.MENU).getTranslated(player));
|
||||
}
|
||||
|
||||
public static void hiderInventory(Player player) {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
playerInventory.clear();
|
||||
playerInventory.addItem(
|
||||
TranslationManager.translateItem(player, freezeItem, FREEZE_ITEM),
|
||||
TranslationManager.translateItem(player, faceChangingItem, FACE_CHANGING_ITEM),
|
||||
TranslationManager.translateItem(player, soundItem, SOUND_ITEM),
|
||||
TranslationManager.translateItem(player, dashItem, DASH_ITEM)
|
||||
getItem(Items.FREEZE).getTranslated(player),
|
||||
getItem(Items.FACE_CHANGING).getTranslated(player),
|
||||
getItem(Items.SOUND_MAKER).getTranslated(player),
|
||||
getItem(Items.DASH).getTranslated(player)
|
||||
);
|
||||
}
|
||||
|
||||
public static void giveFaceChangingItem(Player player) {
|
||||
player.getInventory().addItem(TranslationManager.translateItem(player, faceChangingItem, TranslationKey.SEEKER_TEMPLATE));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,15 +4,16 @@ import eu.okaeri.configs.ConfigManager;
|
||||
import eu.okaeri.configs.serdes.commons.SerdesCommons;
|
||||
import eu.okaeri.configs.yaml.bukkit.YamlBukkitConfigurer;
|
||||
import eu.okaeri.configs.yaml.bukkit.serdes.SerdesBukkit;
|
||||
|
||||
import hdvtdev.blockandseek.BlockAndSeek;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
import org.intellij.lang.annotations.Flow;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
@@ -26,94 +27,49 @@ public final class MapsManager {
|
||||
|
||||
private MapsManager() {}
|
||||
|
||||
public static void loadMaps() {
|
||||
if (!MAPS_DIR.exists()) {
|
||||
MAPS_DIR.mkdirs();
|
||||
}
|
||||
public static List<String> getAllMaps() {
|
||||
return new ArrayList<>(maps.keySet());
|
||||
}
|
||||
|
||||
File[] files = MAPS_DIR.listFiles((dir, name) -> name.endsWith(".yml"));
|
||||
if (files == null) return;
|
||||
|
||||
for (File file : files) {
|
||||
String name = file.getName().replace(".yml", "");
|
||||
try {
|
||||
BlockAndSeekMap map = loadConfig(file);
|
||||
maps.put(name, map);
|
||||
} catch (Exception e) {
|
||||
BlockAndSeek.getPluginLogger().severe("Error loading map " + name + ": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
BlockAndSeek.getPluginLogger().info("Loaded " + maps.size() + " maps.");
|
||||
public static boolean hasMap(String name) {
|
||||
return maps.containsKey(name);
|
||||
}
|
||||
|
||||
public static BlockAndSeekMap getMap(String name) {
|
||||
return maps.get(name);
|
||||
}
|
||||
|
||||
public static Collection<BlockAndSeekMap> getMaps() {
|
||||
return maps.values();
|
||||
}
|
||||
public static void loadMaps() {
|
||||
|
||||
public static void createMap(String name) {
|
||||
File mapFile = new File(MAPS_DIR, name + ".yml");
|
||||
if (mapFile.exists()) {
|
||||
throw new IllegalArgumentException("Map already exists!");
|
||||
}
|
||||
File[] mapsFile = MAPS_DIR.listFiles();
|
||||
|
||||
BlockAndSeekMap map = loadConfig(mapFile);
|
||||
|
||||
map.setWorld(name);
|
||||
|
||||
if (Bukkit.getWorld(name) != null) {
|
||||
Location spawn = Bukkit.getWorld(name).getSpawnLocation();
|
||||
map.setLobby(spawn);
|
||||
map.setSpawn(spawn);
|
||||
}
|
||||
|
||||
map.save();
|
||||
maps.put(name, map);
|
||||
}
|
||||
|
||||
private static BlockAndSeekMap loadConfig(File file) {
|
||||
var map = ConfigManager.create(BlockAndSeekMap.class, (it) -> {
|
||||
it.withConfigurer(
|
||||
new YamlBukkitConfigurer(),
|
||||
new SerdesBukkit(),
|
||||
new SerdesCommons()
|
||||
);
|
||||
it.withBindFile(file);
|
||||
it.withLogger(BlockAndSeek.getPluginLogger());
|
||||
it.load(true);
|
||||
});
|
||||
|
||||
String worldName = map.getWorld();
|
||||
if (worldName == null) {
|
||||
BlockAndSeek.getPluginLogger().warning("Map " + file.getName() + " has no world defined!");
|
||||
return map;
|
||||
}
|
||||
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
|
||||
if (world == null) {
|
||||
File worldFolder = new File(Bukkit.getWorldContainer(), worldName);
|
||||
if (worldFolder.exists() && worldFolder.isDirectory()) {
|
||||
BlockAndSeek.getPluginLogger().info("World '" + worldName + "' is not loaded. Loading now...");
|
||||
world = Bukkit.createWorld(new WorldCreator(worldName));
|
||||
if (mapsFile != null) {
|
||||
for (File mapFile : mapsFile) {
|
||||
BlockAndSeekMap blockAndSeekMap = ConfigManager.create(BlockAndSeekMap.class, (it) -> {
|
||||
it.withConfigurer(new YamlBukkitConfigurer(), new SerdesCommons(), new SerdesBukkit());
|
||||
it.withBindFile(mapFile);
|
||||
it.saveDefaults();
|
||||
it.load(true);
|
||||
});
|
||||
maps.put(mapFile.getName().replace(".yml", ""), blockAndSeekMap);
|
||||
}
|
||||
}
|
||||
|
||||
map.getLobby().setWorld(world);
|
||||
map.getSpawn().setWorld(world);
|
||||
}
|
||||
|
||||
map.save();
|
||||
|
||||
return map;
|
||||
public static void addMap(String name) {
|
||||
BlockAndSeekMap blockAndSeekMap = ConfigManager.create(BlockAndSeekMap.class, (it) -> {
|
||||
it.withConfigurer(new YamlBukkitConfigurer(), new SerdesCommons(), new SerdesBukkit());
|
||||
it.withBindFile(new File(MAPS_DIR, name + ".yml"));
|
||||
it.saveDefaults();
|
||||
it.load(true);
|
||||
});
|
||||
maps.put(name, blockAndSeekMap);
|
||||
}
|
||||
|
||||
// --- Suggestions ---
|
||||
|
||||
public static SuggestionProvider<CommandSender> worldSuggestions = (context, input) ->
|
||||
public static final SuggestionProvider<CommandSender> worldSuggestions = (context, input) ->
|
||||
CompletableFuture.supplyAsync(() -> {
|
||||
// Лучше брать загруженные миры Bukkit, если карта должна быть в активном мире
|
||||
// Если нужны папки миров:
|
||||
@@ -128,7 +84,7 @@ public final class MapsManager {
|
||||
.collect(Collectors.toList());
|
||||
});
|
||||
|
||||
public static SuggestionProvider<CommandSender> mapSuggestions = (context, input) ->
|
||||
public static final SuggestionProvider<CommandSender> mapSuggestions = (context, input) ->
|
||||
CompletableFuture.supplyAsync(() -> maps.keySet().stream()
|
||||
.map(Suggestion::suggestion)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
@@ -1,110 +1,112 @@
|
||||
package hdvtdev.blockandseek.managers;
|
||||
|
||||
import hdvtdev.blockandseek.BlockAndSeek;
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.disguisetypes.Disguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
import me.libraryaddict.disguise.disguisetypes.MiscDisguise;
|
||||
import me.libraryaddict.disguise.disguisetypes.watchers.FallingBlockWatcher;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Openable;
|
||||
import org.bukkit.block.data.Directional;
|
||||
import org.bukkit.block.data.Orientable;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public final class PropManager {
|
||||
public class PropManager {
|
||||
|
||||
private final Map<UUID, PropData> players = new HashMap<>();
|
||||
private final Map<Location, UUID> props = new HashMap<>();
|
||||
private static final Map<UUID, PropData> players = new ConcurrentHashMap<>();
|
||||
private static final Map<Location, UUID> props = new ConcurrentHashMap<>();
|
||||
|
||||
public void removePlayer(Player player) {
|
||||
private PropManager() {}
|
||||
|
||||
public static void removePlayer(Player player) {
|
||||
PropData propData = players.remove(player.getUniqueId());
|
||||
if (propData != null) {
|
||||
props.remove(propData.propLocation);
|
||||
propData.armorStand.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isProped(UUID uuid) {
|
||||
return props.containsValue(uuid);
|
||||
public static boolean isProped(UUID uuid) {
|
||||
return players.containsKey(uuid);
|
||||
}
|
||||
|
||||
public void forceUnfreeze(Player player) {
|
||||
public static void forceUnfreeze(Player player) {
|
||||
if (players.containsKey(player.getUniqueId())) {
|
||||
freezeOrUnfreeze(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void forceUnfreeze(UUID uuid) {
|
||||
public static void forceUnfreeze(UUID uuid) {
|
||||
if (players.containsKey(uuid)) {
|
||||
freezeOrUnfreeze(Bukkit.getPlayer(uuid));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public UUID getProp(Location location) {
|
||||
return props.remove(location);
|
||||
public static UUID getProp(Location location) {
|
||||
return props.get(location);
|
||||
}
|
||||
|
||||
|
||||
//fixme: replace body with freezeOrUnfreeze(Player player) body
|
||||
/*
|
||||
public PropState freezeOrUnfreeze(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null) {
|
||||
return freezeOrUnfreeze(player);
|
||||
}
|
||||
return PropState.FAILED;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//i dont know how dis works xd
|
||||
public PropState freezeOrUnfreeze(Player player) {
|
||||
public static PropState freezeOrUnfreeze(Player player) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
PropData propData = players.remove(uuid);
|
||||
Location location = player.getLocation().toCenterLocation();
|
||||
|
||||
if (propData != null) {
|
||||
ArmorStand armorStand = propData.armorStand;
|
||||
location.getWorld().setBlockData(location, propData.blockData);
|
||||
location.setY(Math.floor(location.getY()));
|
||||
player.setInvulnerable(false);
|
||||
armorStand.removePassenger(player);
|
||||
armorStand.remove();
|
||||
Location propLocation = propData.propLocation;
|
||||
|
||||
props.remove(propLocation);
|
||||
propLocation.getBlock().setBlockData(propData.blockData);
|
||||
|
||||
propLocation.setYaw(player.getYaw());
|
||||
propLocation.setPitch(player.getPitch());
|
||||
|
||||
player.teleport(propLocation.toCenterLocation());
|
||||
player.setInvulnerable(false);
|
||||
player.setVisibleByDefault(true);
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
|
||||
propData.armorStand.removePassenger(player);
|
||||
propData.armorStand.remove();
|
||||
|
||||
return PropState.UNFROZEN;
|
||||
} else {
|
||||
|
||||
Location location = player.getLocation();
|
||||
Block block = location.getBlock();
|
||||
BlockData blockData = block.getBlockData();
|
||||
|
||||
Location blockLocation = block.getLocation();
|
||||
|
||||
if (props.containsKey(blockLocation)) {
|
||||
return PropState.FAILED;
|
||||
}
|
||||
|
||||
Location centerLocation = blockLocation.toCenterLocation();
|
||||
Location upperBlockLocation = centerLocation.clone();
|
||||
upperBlockLocation.setY(upperBlockLocation.getY() + 1);
|
||||
Location upperBlockLocation = centerLocation.clone().add(0, 1, 0);
|
||||
|
||||
if (!upperBlockLocation.getBlock().isSolid() && !blockLocation.getBlock().isSolid()) {
|
||||
props.put(blockLocation, uuid);
|
||||
if (!upperBlockLocation.getBlock().isSolid() && !block.getType().isSolid()) {
|
||||
|
||||
BlockData originalBlockData = block.getBlockData();
|
||||
BlockData disguiseBlockData = getPlayerDisguiseData(player);
|
||||
location.getWorld().setBlockData(blockLocation, disguiseBlockData == null ? Material.TARGET.createBlockData() : disguiseBlockData);
|
||||
|
||||
block.setBlockData(disguiseBlockData == null ? Material.TARGET.createBlockData() : disguiseBlockData);
|
||||
|
||||
centerLocation.setY(centerLocation.getY() - 0.85);
|
||||
|
||||
player.setInvulnerable(true);
|
||||
player.setVisibleByDefault(false);
|
||||
player.setFreezeTicks(40);
|
||||
|
||||
ArmorStand armorStand = location.getWorld().spawn(centerLocation, ArmorStand.class, stand -> {
|
||||
stand.setVisible(false);
|
||||
stand.setVisible(false);
|
||||
stand.setCollidable(false);
|
||||
stand.setGravity(true);
|
||||
@@ -114,21 +116,60 @@ public final class PropManager {
|
||||
stand.setInvulnerable(true);
|
||||
});
|
||||
|
||||
players.put(uuid, new PropData(armorStand, blockData));
|
||||
players.put(uuid, new PropData(armorStand, originalBlockData, blockLocation));
|
||||
props.put(blockLocation, uuid);
|
||||
|
||||
return PropState.FROZEN;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return PropState.FAILED;
|
||||
}
|
||||
|
||||
private static final BlockFace[] rotationOrder = {
|
||||
BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST,
|
||||
BlockFace.UP, BlockFace.DOWN
|
||||
};
|
||||
|
||||
public static void changePropDirection(Player player) {
|
||||
if (players.containsKey(player.getUniqueId())) {
|
||||
Block block = player.getLocation().getBlock();
|
||||
BlockData blockData = block.getBlockData();
|
||||
|
||||
if (blockData instanceof Orientable orientable) {
|
||||
Axis nextAxis = switch (orientable.getAxis()) {
|
||||
case X -> Axis.Y;
|
||||
case Y -> Axis.Z;
|
||||
case Z -> Axis.X;
|
||||
};
|
||||
orientable.setAxis(nextAxis);
|
||||
block.setBlockData(orientable);
|
||||
}
|
||||
|
||||
else if (blockData instanceof Directional directional) {
|
||||
BlockFace currentFace = directional.getFacing();
|
||||
BlockFace nextFace = null;
|
||||
|
||||
for (int i = 0; i < rotationOrder.length; i++) {
|
||||
if (rotationOrder[i] == currentFace) {
|
||||
for (int j = 1; j <= rotationOrder.length; j++) {
|
||||
BlockFace potentialFace = rotationOrder[(i + j) % rotationOrder.length];
|
||||
if (directional.getFaces().contains(potentialFace)) {
|
||||
nextFace = potentialFace;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextFace != null) {
|
||||
directional.setFacing(nextFace);
|
||||
block.setBlockData(directional);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static BlockData getPlayerDisguiseData(Player player) {
|
||||
Disguise disguise = DisguiseAPI.getDisguise(player);
|
||||
@@ -141,14 +182,9 @@ public final class PropManager {
|
||||
|
||||
|
||||
public enum PropState {
|
||||
FROZEN,
|
||||
UNFROZEN,
|
||||
FAILED
|
||||
FROZEN, UNFROZEN, FAILED
|
||||
}
|
||||
|
||||
private record PropData(ArmorStand armorStand, BlockData blockData) {
|
||||
|
||||
private record PropData(ArmorStand armorStand, BlockData blockData, Location propLocation) {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import eu.okaeri.configs.annotation.Exclude;
|
||||
import eu.okaeri.configs.serdes.commons.SerdesCommons;
|
||||
import eu.okaeri.configs.yaml.bukkit.YamlBukkitConfigurer;
|
||||
import hdvtdev.blockandseek.BlockAndSeek;
|
||||
import hdvtdev.blockandseek.objects.BlockAndSeekItem;
|
||||
import hdvtdev.blockandseek.objects.Translation;
|
||||
import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
import lombok.Getter;
|
||||
@@ -37,6 +38,7 @@ public final class TranslationManager {
|
||||
public static final String bracedPrefix = "<gradient:#FFAA00:#FFD700><bold>[BlockAndSeek]</bold></gradient>";
|
||||
|
||||
private static final Map<String, EnumMap<TranslationKey, String>> translations = new HashMap<>();
|
||||
private static final Map<String, BlockAndSeekItem> itemTranslations = new HashMap<>();
|
||||
|
||||
public static Component get(Player player, TranslationKey key, String... placeholders) {
|
||||
return get(player.locale().toString(), key, placeholders);
|
||||
|
||||
@@ -27,65 +27,35 @@ public final class WorldManager {
|
||||
|
||||
private static final AsyncScheduler asyncScheduler = Bukkit.getAsyncScheduler();
|
||||
|
||||
private static final ConcurrentHashMap<String, WorldManager> worldManagers = new ConcurrentHashMap<>();
|
||||
|
||||
static {
|
||||
//TODO
|
||||
}
|
||||
|
||||
|
||||
private final File originalWorld;
|
||||
|
||||
private final ConcurrentLinkedQueue<World> freeCopies = new ConcurrentLinkedQueue<>();
|
||||
private final AtomicInteger copyIndex = new AtomicInteger(1);
|
||||
private final int reservedCopies;
|
||||
private final int reservedCopies = 1;
|
||||
|
||||
private WorldManager(String worldName, int reservedCopies) {
|
||||
public WorldManager(String worldName) {
|
||||
this.originalWorld = new File(serverFolder, worldName + "_copy");
|
||||
this.reservedCopies = reservedCopies;
|
||||
|
||||
new BukkitRunnable() {
|
||||
|
||||
boolean unloading = false;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!Bukkit.isTickingWorlds() && !unloading) {
|
||||
unloading = true;
|
||||
Bukkit.unloadWorld(worldName, true);
|
||||
asyncScheduler.runNow(BlockAndSeek.getInstance(), task -> {
|
||||
try {
|
||||
FileUtils.copyDirectoryStructure(new File(serverFolder, worldName), originalWorld);
|
||||
createCopy();
|
||||
} catch (IOException e) {
|
||||
BlockAndSeek.getPluginLogger().severe("Failed to copy world \"" + worldName + "\": " + e.getMessage());
|
||||
this.cancel();
|
||||
}
|
||||
});
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(BlockAndSeek.getInstance(), 0, 1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static void createWorldManager(String existingWorld, int reservedCopies) {
|
||||
worldManagers.put(existingWorld, new WorldManager(existingWorld, reservedCopies));
|
||||
}
|
||||
|
||||
public static @Nullable WorldManager get(String worldName) {
|
||||
return worldManagers.get(worldName);
|
||||
private void createCopies() {
|
||||
for (int i = 0; i < reservedCopies; i++) {
|
||||
createCopy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return {@link World} if a free copy is available or a new one has been created.
|
||||
* Returns {@code null} if there are currently no free copies and a new copy is still being created.
|
||||
*/
|
||||
public @Nullable World acquire() {
|
||||
if (freeCopies.size() <= 1) {
|
||||
createCopy(); //TODO
|
||||
createCopies(); //TODO
|
||||
}
|
||||
return freeCopies.poll();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static hdvtdev.blockandseek.objects.TranslationKey.UNKNOWN_MAP;
|
||||
@@ -26,37 +27,39 @@ public class MapsMenu implements GuiHolder {
|
||||
private final Inventory inventory;
|
||||
|
||||
public MapsMenu(Player player) {
|
||||
Component title = TranslationManager.get(player, TranslationKey.GAMES_MENU);
|
||||
Component title = TranslationManager.get(player, TranslationKey.MAPS_MENU);
|
||||
this.inventory = Bukkit.createInventory(this, 54, title);
|
||||
init();
|
||||
this.init();
|
||||
showInventory(player);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
for (BlockAndSeekMap map : MapsManager.getMaps()) {
|
||||
for (String name : MapsManager.getAllMaps()) {
|
||||
ItemStack gameItem = new ItemStack(Material.MAP);
|
||||
ItemMeta itemMeta = gameItem.getItemMeta();
|
||||
itemMeta.displayName(TranslationManager.get(TranslationManager.defaultLanguage, TranslationKey.MAP, "%name%", map.getWorld()));
|
||||
gameItem.setItemMeta(itemMeta);
|
||||
gameItem.editMeta(itemMeta ->
|
||||
itemMeta.displayName(TranslationManager.get(TranslationManager.defaultLanguage, TranslationKey.MAP, "%name%", name)));
|
||||
inventory.addItem(gameItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(InventoryClickEvent event) {
|
||||
|
||||
ItemStack item = event.getCurrentItem();
|
||||
event.setCancelled(true);
|
||||
if (item != null) {
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
String mapName = TranslationManager.plaintText.serialize(item.displayName()).replaceAll("[\\[\\]]", "");
|
||||
var map = MapsManager.getMap(mapName);
|
||||
if (map != null) {
|
||||
if (MapsManager.hasMap(mapName)) {
|
||||
GamesManager.createGame(mapName).addPlayer(player);
|
||||
} else {
|
||||
player.sendMessage(TranslationManager.get(player, UNKNOWN_MAP, "%map%", mapName, "%maps%", MapsManager.getMaps().stream().map(BlockAndSeekMap::getWorld).collect(Collectors.joining(", "))));
|
||||
player.sendMessage(UNKNOWN_MAP.translate(player, "%map%", mapName, "%maps%", String.join(", ", MapsManager.getAllMaps())));
|
||||
}
|
||||
player.closeInventory();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package hdvtdev.blockandseek.objects;
|
||||
|
||||
import hdvtdev.blockandseek.BlockAndSeek;
|
||||
import hdvtdev.blockandseek.managers.ItemManager;
|
||||
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class BlockAndSeekButton {
|
||||
|
||||
private static final NamespacedKey namespacedKey = new NamespacedKey(BlockAndSeek.getInstance(), "item_id");
|
||||
private final ItemStack button;
|
||||
|
||||
public BlockAndSeekButton(@NotNull Items id) {
|
||||
this.button = asItemStack(id);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ItemStack asItemStack(@NotNull Items val) {
|
||||
ItemStack itemStack = buildRawItem();
|
||||
itemStack.editMeta(meta -> meta.getPersistentDataContainer().set(namespacedKey, Items.TYPE, val));
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract ItemStack buildRawItem();
|
||||
|
||||
@NotNull
|
||||
public abstract ItemStack getTranslated(Player player);
|
||||
|
||||
@NotNull
|
||||
protected final ItemStack getCloned() {
|
||||
return button.clone();
|
||||
}
|
||||
}
|
||||
@@ -9,17 +9,18 @@ import hdvtdev.blockandseek.managers.GamesManager;
|
||||
import hdvtdev.blockandseek.managers.ItemManager;
|
||||
import hdvtdev.blockandseek.managers.PropManager;
|
||||
import hdvtdev.blockandseek.managers.StateManager;
|
||||
|
||||
import hdvtdev.blockandseek.menus.GamesMenu;
|
||||
import hdvtdev.blockandseek.roulette.RouletteCreator;
|
||||
|
||||
import me.libraryaddict.disguise.DisguiseAPI;
|
||||
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
|
||||
import me.libraryaddict.disguise.disguisetypes.MiscDisguise;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.title.Title;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -40,6 +41,8 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.*;
|
||||
@@ -48,7 +51,6 @@ public class BlockAndSeekGame {
|
||||
|
||||
private final BlockAndSeekMap map;
|
||||
private final StateManager stateManager = new StateManager();
|
||||
private final PropManager propManager = new PropManager();
|
||||
private final String name;
|
||||
|
||||
private GamePhase phase;
|
||||
@@ -62,7 +64,7 @@ public class BlockAndSeekGame {
|
||||
public boolean addPlayer(Player player) {
|
||||
if (phase instanceof LobbyPhase && stateManager.playerCount() < map.getMaxPlayers()) {
|
||||
stateManager.setPlayerState(player.getUniqueId(), PlayerType.NONE);
|
||||
player.teleport(map.getLobby());
|
||||
map.getLobby().teleport(player);
|
||||
player.setInvulnerable(true);
|
||||
return true;
|
||||
}
|
||||
@@ -128,7 +130,7 @@ public class BlockAndSeekGame {
|
||||
//fixme: player leave event: count == 0 -> phase = null -> delete game
|
||||
private class LobbyPhase extends GamePhase {
|
||||
|
||||
private static final int WAIT_TIME = 30;
|
||||
private static final int WAIT_TIME = 31;
|
||||
|
||||
@Override
|
||||
public void onTick() {
|
||||
@@ -166,6 +168,7 @@ public class BlockAndSeekGame {
|
||||
private class StartedGamePhase extends GamePhase implements Listener {
|
||||
|
||||
private long gameDuration = map.getGameDuration().toSeconds();
|
||||
private final long midGame = gameDuration / 2;
|
||||
|
||||
@Override
|
||||
public void onTick() {
|
||||
@@ -182,6 +185,14 @@ public class BlockAndSeekGame {
|
||||
broadcastToAll(TranslationKey.SEEKERS_WIN);
|
||||
this.onDisable();
|
||||
} else {
|
||||
if (gameDuration == midGame) {
|
||||
for (UUID uuid : stateManager.getPlayersInState(PlayerType.PROP)) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null) {
|
||||
new RouletteCreator(player, map.getBlocks());
|
||||
}
|
||||
}
|
||||
}
|
||||
actionBarToAll(TranslationKey.TIME_LEFT, "%time%", String.valueOf(gameDuration));
|
||||
}
|
||||
gameDuration--;
|
||||
@@ -197,7 +208,7 @@ public class BlockAndSeekGame {
|
||||
if (player != null) {
|
||||
stateManager.setPlayerState(uuid, PlayerType.PROP);
|
||||
ItemManager.hiderInventory(player);
|
||||
player.teleport(map.getSpawn());
|
||||
map.getSpawn().teleport(player);
|
||||
new RouletteCreator(player, map.getBlocks());
|
||||
player.setInvulnerable(false);
|
||||
} else BlockAndSeek.getPluginLogger().warning("Player is null. ");
|
||||
@@ -213,12 +224,15 @@ public class BlockAndSeekGame {
|
||||
Collections.shuffle(rawSeekers);
|
||||
|
||||
var seekers = rawSeekers.subList(0, Math.min(count, playerSet.size()));
|
||||
long spawnDelay = map.getSeekerSpawnDelay().toSeconds() * 20;
|
||||
|
||||
for (UUID seeker : seekers) {
|
||||
Player player = Bukkit.getPlayer(seeker);
|
||||
if (player != null) {
|
||||
stateManager.setPlayerState(seeker, PlayerType.SEEKER);
|
||||
player.setWalkSpeed(0.22f);
|
||||
player.setWalkSpeed(0.27f);
|
||||
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, (int) spawnDelay, 2));
|
||||
ItemManager.setSeekerSet(player);
|
||||
Utils.setLevelWithBar(player, 100);
|
||||
GamesManager.addSeekerImmune(player);
|
||||
@@ -231,12 +245,12 @@ public class BlockAndSeekGame {
|
||||
for (UUID seeker : seekers) {
|
||||
Player player = Bukkit.getPlayer(seeker);
|
||||
if (player != null) {
|
||||
player.teleport(map.getSpawn());
|
||||
map.getSpawn().teleport(player);
|
||||
player.setInvulnerable(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.runTaskLater(BlockAndSeek.getInstance(), map.getSeekerSpawnDelay().toSeconds() * 20);
|
||||
}.runTaskLater(BlockAndSeek.getInstance(), spawnDelay);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -281,6 +295,7 @@ public class BlockAndSeekGame {
|
||||
if (stateManager.hasPlayer(uuid)) {
|
||||
stateManager.setPlayerState(uuid, PlayerType.SPECTATOR);
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
PropManager.removePlayer(player);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@@ -302,7 +317,7 @@ public class BlockAndSeekGame {
|
||||
if (playerType == PlayerType.SEEKER) {
|
||||
event.setCancelled(true);
|
||||
} else if (playerType == PlayerType.PROP) {
|
||||
if (!propManager.isProped(uuid)) {
|
||||
if (!PropManager.isProped(uuid)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@@ -313,7 +328,7 @@ public class BlockAndSeekGame {
|
||||
public void onEntityDismount(EntityDismountEvent event) {
|
||||
if (event.getEntity() instanceof Player player && event.getDismounted() instanceof ArmorStand) {
|
||||
if (stateManager.hasPlayer(player.getUniqueId())) {
|
||||
propManager.forceUnfreeze(player);
|
||||
PropManager.forceUnfreeze(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -363,11 +378,15 @@ public class BlockAndSeekGame {
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
if (PlayerType.SEEKER.equals(stateManager.getState(uuid))) {
|
||||
UUID prop = propManager.getProp(event.getBlock().getLocation());
|
||||
UUID prop = PropManager.getProp(event.getBlock().getLocation());
|
||||
if (prop != null) {
|
||||
propManager.forceUnfreeze(prop);
|
||||
PropManager.forceUnfreeze(prop);
|
||||
Utils.healSeeker(player, 5);
|
||||
player.playSound(player, Sound.ENTITY_ARROW_HIT_PLAYER, 1f, 1f);
|
||||
Player hider = Bukkit.getPlayer(prop);
|
||||
if (hider != null) hider.damage(4); //todo calculate damage fix
|
||||
} else {
|
||||
player.damage(2);
|
||||
player.damage(1);
|
||||
Utils.setLevelWithBar(player, (int) Math.round(player.getHealth() * 5));
|
||||
}
|
||||
}
|
||||
@@ -389,39 +408,6 @@ public class BlockAndSeekGame {
|
||||
}
|
||||
}
|
||||
|
||||
private final Set<UUID> coolDown = new HashSet<>();
|
||||
|
||||
@EventHandler
|
||||
public void onRightClick(PlayerInteractEvent event) {
|
||||
if (event.getHand() != EquipmentSlot.HAND) return;
|
||||
if (event.getAction().isLeftClick()) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
|
||||
ItemStack item = event.getItem();
|
||||
if (item != null) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (meta != null) {
|
||||
PersistentDataContainer dataContainer = meta.getPersistentDataContainer();
|
||||
if (dataContainer.has(Keys.FREEZE_ITEM)) {
|
||||
if (!coolDown.contains(uuid)) {
|
||||
player.sendActionBar(Component.text(propManager.freezeOrUnfreeze(event.getPlayer()).toString()));
|
||||
coolDown.add(uuid);
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
coolDown.remove(uuid);
|
||||
}
|
||||
}.runTaskLater(BlockAndSeek.getInstance(), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private class EndedGamePhase extends GamePhase {
|
||||
@@ -440,7 +426,7 @@ public class BlockAndSeekGame {
|
||||
for (UUID uuid : stateManager.getPlayers()) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null) {
|
||||
propManager.forceUnfreeze(player);
|
||||
PropManager.forceUnfreeze(player);
|
||||
player.setInvulnerable(true);
|
||||
player.setGlowing(true);
|
||||
}
|
||||
|
||||
112
src/main/java/hdvtdev/blockandseek/objects/BlockAndSeekItem.java
Normal file
112
src/main/java/hdvtdev/blockandseek/objects/BlockAndSeekItem.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package hdvtdev.blockandseek.objects;
|
||||
|
||||
import hdvtdev.blockandseek.BlockAndSeek;
|
||||
import hdvtdev.blockandseek.managers.ItemManager;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class BlockAndSeekItem {
|
||||
|
||||
private static final NamespacedKey namespacedKey = new NamespacedKey(BlockAndSeek.getInstance(), "item_id");
|
||||
|
||||
private final long cooldown;
|
||||
private final ItemStack rawItem;
|
||||
private final Set<Action> actions;
|
||||
|
||||
private static final Set<Action> rightClickOnly = EnumSet.of(Action.RIGHT_CLICK_BLOCK, Action.RIGHT_CLICK_AIR);
|
||||
private static final Set<Action> leftClickOnly = EnumSet.of(Action.LEFT_CLICK_BLOCK, Action.LEFT_CLICK_AIR);
|
||||
private static final Set<Action> anyClick = EnumSet.of(
|
||||
Action.RIGHT_CLICK_BLOCK, Action.RIGHT_CLICK_AIR,
|
||||
Action.LEFT_CLICK_BLOCK, Action.LEFT_CLICK_AIR
|
||||
);
|
||||
|
||||
public BlockAndSeekItem(@NotNull Items id, @NotNull Duration cooldown, @NotNull ClickAction clickAction) {
|
||||
this.actions = switch (clickAction) {
|
||||
case RIGHT_CLICK -> rightClickOnly;
|
||||
case LEFT_CLICK -> leftClickOnly;
|
||||
case ANY -> anyClick;
|
||||
};
|
||||
this.cooldown = cooldown.toMillis() / 50;
|
||||
this.rawItem = asItemStack(id);
|
||||
}
|
||||
|
||||
public BlockAndSeekItem(@NotNull Items id) {
|
||||
this(id, Duration.ZERO, ClickAction.ANY);
|
||||
}
|
||||
|
||||
public BlockAndSeekItem(@NotNull Items id, @NotNull ClickAction action) {
|
||||
this(id, Duration.ZERO, action);
|
||||
}
|
||||
|
||||
public BlockAndSeekItem(@NotNull Items id, @NotNull Duration cooldown) {
|
||||
this(id, cooldown, ClickAction.ANY);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ItemStack asItemStack(@NotNull Items val) {
|
||||
ItemStack itemStack = buildRawItem();
|
||||
itemStack.editMeta(meta -> meta.getPersistentDataContainer().set(namespacedKey, Items.TYPE, val));
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
public final boolean onRawInteract(@NotNull PlayerInteractEvent event) {
|
||||
if (this.actions.contains(event.getAction())) {
|
||||
if (cooldown != 0) {
|
||||
Player player = event.getPlayer();
|
||||
Material material = event.getMaterial();
|
||||
if (!player.hasCooldown(material)) {
|
||||
player.setCooldown(material, (int) cooldown);
|
||||
onInteract(event);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
onInteract(event);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract void onInteract(@NotNull PlayerInteractEvent event);
|
||||
|
||||
@NotNull
|
||||
protected abstract ItemStack buildRawItem();
|
||||
|
||||
@NotNull
|
||||
public abstract ItemStack getTranslated(Player player);
|
||||
|
||||
@NotNull
|
||||
protected final ItemStack getCloned() {
|
||||
return rawItem.clone();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BlockAndSeekItem tryCast(@Nullable ItemStack itemStack) {
|
||||
if (itemStack != null) {
|
||||
Items items = itemStack.getItemMeta().getPersistentDataContainer().get(namespacedKey, Items.TYPE);
|
||||
if (items != null) {
|
||||
return ItemManager.getItem(items);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public enum ClickAction {
|
||||
RIGHT_CLICK,
|
||||
LEFT_CLICK,
|
||||
ANY
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import eu.okaeri.validator.annotation.Min;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@@ -20,14 +19,11 @@ import java.util.List;
|
||||
@Setter
|
||||
public class BlockAndSeekMap extends OkaeriConfig {
|
||||
|
||||
@Comment("The name of the world where the game takes place")
|
||||
private String world;
|
||||
|
||||
@Comment("The main spawn point inside the arena")
|
||||
private Location spawn;
|
||||
private LazyLocation spawn;
|
||||
|
||||
@Comment("The waiting lobby location where players join before the match")
|
||||
private Location lobby;
|
||||
private LazyLocation lobby;
|
||||
|
||||
@Comment("Minimum number of players required to start the game")
|
||||
@Min(2)
|
||||
@@ -42,7 +38,7 @@ public class BlockAndSeekMap extends OkaeriConfig {
|
||||
@CustomKey("game-duration")
|
||||
private Duration gameDuration = Duration.ofMinutes(10);
|
||||
|
||||
@Comment("How long seekers must wait before they are released")
|
||||
@Comment("How long seekers must wait before they are released. Format examples: 10m, 300s, 1h")
|
||||
@CustomKey("seeker-spawn-delay")
|
||||
private Duration seekerSpawnDelay = Duration.ofSeconds(30);
|
||||
|
||||
@@ -51,9 +47,20 @@ public class BlockAndSeekMap extends OkaeriConfig {
|
||||
@CustomKey("delay-before-game-end")
|
||||
private Duration delayBeforeGameEnd = Duration.ofSeconds(10);
|
||||
|
||||
@Comment("Available blocks for hiders")
|
||||
@Comment("Create blocks roulette for all hiders to select a new prop")
|
||||
private boolean midGameBlockSwap = true;
|
||||
|
||||
@Comment("Grants seeker infinite health, speed, and jump boost for the specified time before the game ends.")
|
||||
@Comment("Format examples: 10m, 300s, 1h. If duration is zero, sudden death will be disabled")
|
||||
@CustomKey("sudden-death")
|
||||
private Duration suddenDeath = Duration.ofSeconds(30);
|
||||
|
||||
@Comment("Available prop blocks for hiders")
|
||||
private List<PropBlock> blocks = new ArrayList<>(List.of(new PropBlock(new ItemStack(Material.TARGET), Rarity.LEGENDARY)));
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
46
src/main/java/hdvtdev/blockandseek/objects/Items.java
Normal file
46
src/main/java/hdvtdev/blockandseek/objects/Items.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package hdvtdev.blockandseek.objects;
|
||||
|
||||
import hdvtdev.blockandseek.managers.ItemManager;
|
||||
|
||||
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public enum Items implements PersistentDataType<String, Items> {
|
||||
PISTOL,
|
||||
FREEZE,
|
||||
FACE_CHANGING,
|
||||
LEAVE,
|
||||
MENU,
|
||||
SOUND_MAKER,
|
||||
DASH,
|
||||
MORPH, GRENADE;
|
||||
|
||||
public static final PersistentDataType<String, Items> TYPE = PISTOL;
|
||||
|
||||
@Override
|
||||
public @NotNull Class<String> getPrimitiveType() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Class<Items> getComplexType() {
|
||||
return Items.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String toPrimitive(@NotNull Items complex, @NotNull PersistentDataAdapterContext context) {
|
||||
return complex.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Items fromPrimitive(@NotNull String primitive, @NotNull PersistentDataAdapterContext context) {
|
||||
return Items.valueOf(primitive);
|
||||
}
|
||||
|
||||
public @NotNull BlockAndSeekItem getItem() {
|
||||
return ItemManager.getItem(this);
|
||||
}
|
||||
|
||||
}
|
||||
69
src/main/java/hdvtdev/blockandseek/objects/LazyLocation.java
Normal file
69
src/main/java/hdvtdev/blockandseek/objects/LazyLocation.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package hdvtdev.blockandseek.objects;
|
||||
|
||||
import eu.okaeri.configs.OkaeriConfig;
|
||||
import eu.okaeri.configs.annotation.Comment;
|
||||
import eu.okaeri.configs.annotation.CustomKey;
|
||||
import eu.okaeri.configs.annotation.Exclude;
|
||||
|
||||
import hdvtdev.blockandseek.BlockAndSeek;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class LazyLocation extends OkaeriConfig {
|
||||
|
||||
public LazyLocation(String worldName) {
|
||||
this.worldName = worldName;
|
||||
}
|
||||
|
||||
@Comment("Name of the world. World will be automatically loaded.")
|
||||
@CustomKey("world-name")
|
||||
private String worldName;
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
|
||||
@Exclude
|
||||
private Location location;
|
||||
|
||||
private void loadLocation() {
|
||||
BlockAndSeek.getPluginLogger().info("Loading world \"" + worldName + "\"");
|
||||
World world = Bukkit.createWorld(new WorldCreator(worldName));
|
||||
this.location = new Location(world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
if (location == null) loadLocation();
|
||||
return location;
|
||||
}
|
||||
|
||||
public void teleport(Player player) {
|
||||
player.teleport(this.getLocation());
|
||||
}
|
||||
|
||||
public static LazyLocation from(Location loc) {
|
||||
LazyLocation ll = new LazyLocation();
|
||||
if (loc.getWorld() != null) {
|
||||
ll.worldName = loc.getWorld().getName();
|
||||
} else {
|
||||
BlockAndSeek.getPluginLogger().severe("World in location is null! Using default placeholder BlockAndSeekWorld!");
|
||||
ll.worldName = "BlockAndSeekWorld";
|
||||
}
|
||||
ll.x = loc.getX();
|
||||
ll.y = loc.getY();
|
||||
ll.z = loc.getZ();
|
||||
ll.yaw = loc.getYaw();
|
||||
ll.pitch = loc.getPitch();
|
||||
return ll;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package hdvtdev.blockandseek.objects;
|
||||
|
||||
import hdvtdev.blockandseek.managers.TranslationManager;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public enum TranslationKey {
|
||||
// Misc
|
||||
UNKNOWN_COMMAND,
|
||||
@@ -36,5 +40,11 @@ public enum TranslationKey {
|
||||
FACE_CHANGING_ITEM,
|
||||
SOUND_ITEM,
|
||||
LEAVE_ITEM,
|
||||
DASH_ITEM;
|
||||
DASH_ITEM, MORPH_ITEM, PISTOL, GRENADE;
|
||||
|
||||
public Component translate(Player player, String... placeholders) {
|
||||
return TranslationManager.get(player, this, placeholders);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import hdvtdev.blockandseek.objects.TranslationKey;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -135,6 +136,17 @@ public final class RouletteCreator implements InventoryHolder {
|
||||
}
|
||||
|
||||
}.runTaskTimer(BlockAndSeek.getInstance(), 0L, 1L);
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (player.getOpenInventory().getTopInventory().equals(gui)) {
|
||||
player.closeInventory(InventoryCloseEvent.Reason.PLAYER);
|
||||
}
|
||||
}
|
||||
}.runTaskLater(BlockAndSeek.getInstance(), 15 * 20);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,16 +5,20 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.jetbrains.annotations.NotNull; // Или другой пакет аннотаций
|
||||
|
||||
public class RouletteList<T> {
|
||||
private final List<T> items;
|
||||
private int currentIndex;
|
||||
|
||||
public RouletteList(@NotNull List<T> items) {
|
||||
this.items = Objects.requireNonNull(items);
|
||||
this.currentIndex = 0;
|
||||
if (items.isEmpty()) {
|
||||
throw new IllegalArgumentException("List must not be empty");
|
||||
}
|
||||
this.items = List.copyOf(items);
|
||||
this.currentIndex = 0;
|
||||
}
|
||||
|
||||
public T next() {
|
||||
@@ -22,4 +26,14 @@ public class RouletteList<T> {
|
||||
currentIndex = (currentIndex + 1) % items.size();
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
public T previous() {
|
||||
T item = items.get(currentIndex);
|
||||
currentIndex = (currentIndex - 1 + items.size()) % items.size();
|
||||
return item;
|
||||
}
|
||||
|
||||
public T current() {
|
||||
return items.get(currentIndex);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user