From 611ac6c213557a104dce4937c291619085bdf729 Mon Sep 17 00:00:00 2001 From: hdvt Date: Wed, 2 Jul 2025 17:49:15 +0300 Subject: [PATCH] majority of bug fixes --- .gitignore | 2 +- .../hdvtdev/blockAndSeek/BlockAndSeek.java | 30 +- .../blockAndSeek/BlockAndSeekGame.java | 335 +++++++++++++----- .../hdvtdev/blockAndSeek/BlockAndSeekMap.java | 11 + .../hdvtdev/blockAndSeek/CommandListener.java | 38 +- .../java/hdvtdev/blockAndSeek/Config.java | 41 +++ src/main/java/hdvtdev/blockAndSeek/Keys.java | 8 +- .../hdvtdev/blockAndSeek/Localization.java | 98 +++-- .../{ => eventListeners}/EventListener.java | 143 +++++--- .../ForceControlEventListener.java | 75 ++++ .../blockAndSeek/managers/ConfigManager.java | 50 +-- .../blockAndSeek/managers/GamesManager.java | 115 +----- .../blockAndSeek/managers/GuiManager.java | 31 +- .../blockAndSeek/managers/ItemManager.java | 63 +++- .../blockAndSeek/managers/MapsManager.java | 7 - .../roulette/RouletteCreator.java | 98 ++++- src/main/resources/config.yml | 20 +- src/main/resources/localization.yml | 14 +- 18 files changed, 810 insertions(+), 369 deletions(-) create mode 100644 src/main/java/hdvtdev/blockAndSeek/Config.java rename src/main/java/hdvtdev/blockAndSeek/{ => eventListeners}/EventListener.java (59%) create mode 100644 src/main/java/hdvtdev/blockAndSeek/eventListeners/ForceControlEventListener.java diff --git a/.gitignore b/.gitignore index f5580ba..bf7e64e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ /.gradle/ +/build/ /gradle/ -/bin/ diff --git a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeek.java b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeek.java index 68df789..bd6eab2 100644 --- a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeek.java +++ b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeek.java @@ -1,11 +1,14 @@ package hdvtdev.blockAndSeek; +import hdvtdev.blockAndSeek.eventListeners.EventListener; +import hdvtdev.blockAndSeek.eventListeners.ForceControlEventListener; import hdvtdev.blockAndSeek.managers.ConfigManager; import me.libraryaddict.disguise.LibsDisguises; import org.bukkit.Bukkit; import org.bukkit.command.PluginCommand; import org.bukkit.configuration.serialization.ConfigurationSerialization; import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; @@ -34,10 +37,6 @@ public class BlockAndSeek extends JavaPlugin { return javaPlugin.getResource(resource); } - public static void saveResource(File file) { - saveResource(file.getAbsolutePath()); - } - public static void saveResource(String file) { javaPlugin.saveResource(file, false); } @@ -46,17 +45,13 @@ public class BlockAndSeek extends JavaPlugin { return javaPlugin.getLogger(); } - public static PluginCommand getCmd(String name) { - return javaPlugin.getCommand(name); - - } - @Override public void onEnable() { javaPlugin = this; ConfigurationSerialization.registerClass(BlockAndSeekMap.class, "BlockAndSeekMap"); + ConfigurationSerialization.registerClass(Config.class, "BlockAndSeekConfig"); LibsDisguises libsDisguises = (LibsDisguises) Bukkit.getPluginManager().getPlugin("LibsDisguises"); @@ -71,20 +66,15 @@ public class BlockAndSeek extends JavaPlugin { getLogger().severe("Failed to save some .yml configs!"); } + + getLogger().warning(ConfigManager.getConfig().toString()); + PluginCommand command = Objects.requireNonNull(getCommand("blockandseek")); command.setExecutor(new CommandListener()); - - - /* TODO - if (CommodoreProvider.isSupported()) { - CommandListener.registerCompletions(CommodoreProvider.getCommodore(this), command); - } - - */ - - - getServer().getPluginManager().registerEvents(new EventListener(), this); + PluginManager manager = getServer().getPluginManager(); + if (ConfigManager.getConfig().forceControl()) manager.registerEvents(new ForceControlEventListener(), this); + manager.registerEvents(new EventListener(), this); } diff --git a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekGame.java b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekGame.java index 4c5aa87..534a836 100644 --- a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekGame.java +++ b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekGame.java @@ -1,14 +1,23 @@ package hdvtdev.blockAndSeek; +import hdvtdev.blockAndSeek.managers.ConfigManager; import hdvtdev.blockAndSeek.managers.FreezeManager; +import hdvtdev.blockAndSeek.managers.GamesManager; +import hdvtdev.blockAndSeek.managers.ItemManager; +import hdvtdev.blockAndSeek.roulette.RouletteCreator; import me.libraryaddict.disguise.DisguiseAPI; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Location; +import org.bukkit.*; import org.bukkit.entity.Player; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; +import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; @@ -17,117 +26,255 @@ public class BlockAndSeekGame { private final ConcurrentHashMap players = new ConcurrentHashMap<>(); private final AtomicBoolean started = new AtomicBoolean(false); - private final String name; - private final int maxPlayers; + private final BlockAndSeekMap map; private final Location lobby; + private final Location spawn; + private final String name; - - public BlockAndSeekGame(String name, int maxPlayers, List lobby) { + public BlockAndSeekGame(String name, BlockAndSeekMap map) { + this.map = map; + World world = Bukkit.getWorld(name); + world.setTime(1000); + world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false); + world.setStorm(false); + world.setGameRule(GameRule.DO_WEATHER_CYCLE, false); this.name = name; - this.maxPlayers = maxPlayers; - this.lobby = new Location(Bukkit.getWorld(name), lobby.getFirst(), lobby.get(1), lobby.get(2)); - } - - public List getHiders() { - return players.entrySet().stream().filter(e -> Objects.equals(e.getValue(), PlayerType.HIDER)).map(Map.Entry::getKey).toList(); - } - - public void preEnd() { - - for (Player hider : getHiders()) { - FreezeManager.unfreezeIfFrozen(hider); - FreezeManager.removePlayerDisguise(hider); - DisguiseAPI.undisguiseToAll(hider); - hider.getInventory().clear(); - hider.setGlowing(true); - } - - for (Player player : getPlayers()) { - player.setInvulnerable(true); - player.setVisibleByDefault(true); - } - - - } - - public void end() { - - for (Player hider : getHiders()) { - FreezeManager.removePlayerDisguise(hider); - DisguiseAPI.undisguiseToAll(hider); - } - - for (Player player : players.keySet()) { - player.teleport(lobby); - player.getPersistentDataContainer().remove(Keys.PLAYER); - player.setGameMode(GameMode.SURVIVAL); - player.setInvulnerable(false); - player.setGlowing(false); - } - } - - public boolean addPlayer(Player player) { - if (started.get() || playerCount() + 1 > maxPlayers) { - return false; - } - player.getPersistentDataContainer().set(Keys.PLAYER, PersistentDataType.STRING, name); - player.teleport(lobby); - players.put(player, PlayerType.HIDER); - return true; - } - - public void removePlayer(Player player) { - players.remove(player); - } - - public void setSpectator(Player player) { - players.put(player, PlayerType.SPECTATOR); - player.setGameMode(GameMode.SPECTATOR); - } - - public Set getPlayers() { - return players.keySet(); - } - - public Player getLastHider() { - for (Map.Entry entry : players.entrySet()) { - if (entry.getValue() == PlayerType.HIDER) return entry.getKey(); - } - return null; - } - - public int seekersCount() { - return (int) players.values().stream().filter(f -> f.equals(PlayerType.SEEKER)).count(); - } - - public int hidersCount() { - return (int) players.values().stream().filter(f -> f.equals(PlayerType.HIDER)).count(); + this.lobby = map.getLobbyLocation(world); + this.spawn = map.getSpawnLocation(world); + this.startBukkitTask(); } public int playerCount() { return players.size(); } - public void start() { + public int maxPlayers() { + return map.getMaxPlayers(); + } + + public boolean addPlayer(Player player) { + if (!started.get()) { + players.put(player, PlayerType.HIDER); + player.getPersistentDataContainer().set(Keys.GAME, PersistentDataType.STRING, name); + player.teleport(lobby); + PlayerInventory inventory = player.getInventory(); + inventory.clear(); + inventory.setItem(8, Localization.translateItem(player, ItemManager.getLeaveItem())); + player.setGameMode(GameMode.SURVIVAL); + player.setInvulnerable(true); + player.setHealth(20.0); + player.setFoodLevel(20); + Localization.sendMessage( + players.keySet(), + true, + "player-join", + "{player}", player.getName(), + "{players}", players.size() + "/" + map.getMaxPlayers() + ); + return true; + } else return false; + } + + public void removePlayer(Player player) { + players.remove(player); + DisguiseAPI.undisguiseToAll(player); + player.getInventory().clear(); + player.setGameMode(GameMode.SURVIVAL); + player.getPersistentDataContainer().remove(Keys.GAME); + Config config = ConfigManager.getConfig(); + if (config.forceControl()) ItemManager.defaultInventory(player); + player.teleport(config.defaultSpawn()); + + + Localization.sendMessage( + players.keySet(), + true, + "player-leave", + "{player}", player.getName(), + "{players}", started.get() ? "" : players.size() + "/" + map.getMaxPlayers() + ); + } + + public void setSpectator(Player hider, @Nullable Player seeker) { + hider.spigot().respawn(); + hider.teleport(hider.getLastDeathLocation()); + players.put(hider, PlayerType.SPECTATOR); + hider.setGameMode(GameMode.SPECTATOR); + Localization.sendMessage( + players.keySet(), + true, + seeker == null ? "hider-died" : "hider-was-found", + "{hider}", hider.getName(), + "{seeker}", seeker == null ? "" : seeker.getName() + ); + } + + private long getHidersCount() { + return players.values().stream().filter(type -> type == PlayerType.HIDER).count(); + } + + private List getSeekers() { + return players.entrySet().stream().filter(entry -> entry.getValue() == PlayerType.SEEKER).map(Map.Entry::getKey).toList(); + } + + private List getHiders() { + return players.entrySet().stream().filter(entry -> entry.getValue() == PlayerType.HIDER).map(Map.Entry::getKey).toList(); + } + + private Player getLastHider() { + return players.keySet().iterator().next(); + } + + private void start() { started.set(true); + selectRandomSeekers((int) Math.round(players.size() * 0.25)); + List hiders = getHiders(); + for (Player hider : hiders) { + hider.getPersistentDataContainer().set(Keys.HIDER, PersistentDataType.BOOLEAN, true); + hider.teleport(spawn); + hider.setInvulnerable(false); + PlayerInventory inventory = hider.getInventory(); + inventory.clear(); + inventory.addItem(Localization.translateItem(hider, ItemManager.getFreezeItem())); + RouletteCreator.createRoulette(hider, null, true, map.getBlocks()); + } } - public boolean isStarted() { - return started.get(); + private void end(boolean force) { + GamesManager.remove(name); + if (!force) { + Location serverLobby = ConfigManager.getConfig().defaultSpawn(); + boolean defaultInventory = ConfigManager.getConfig().forceControl(); + for (Player player : players.keySet()) { + PersistentDataContainer container = player.getPersistentDataContainer(); + container.remove(Keys.HIDER); + container.remove(Keys.SEEKER); + container.remove(Keys.GAME); + DisguiseAPI.undisguiseToAll(player); + if (defaultInventory) ItemManager.defaultInventory(player); + player.setGlowing(false); + player.setInvulnerable(false); + player.setVisibleByDefault(true); + player.setGameMode(GameMode.SURVIVAL); + player.teleport(serverLobby); + + } + } } - public Player selectRandomSeeker() { - return selectRandomSeekers(1).getFirst(); + private void preEnd() { + for (Player hider : getHiders()) { + hider.getInventory().clear(); + FreezeManager.unfreezeIfFrozen(hider); + hider.setGlowing(true); + hider.setInvulnerable(true); + } } - public List selectRandomSeekers(int count) { + public void selectRandomSeekers(int count) { ArrayList playerList = new ArrayList<>(players.keySet()); Collections.shuffle(playerList); List seekers = playerList.subList(0, Math.min(count, playerList.size())); - for (Player seeker : seekers) players.put(seeker, PlayerType.SEEKER); - return seekers; + for (Player seeker : seekers) { + players.put(seeker, PlayerType.SEEKER); + ItemManager.setSeekerSet(seeker); + seeker.setInvulnerable(false); + seeker.getPersistentDataContainer().set(Keys.SEEKER, PersistentDataType.BOOLEAN, true); + } + } + private void startBukkitTask() { + new BukkitRunnable() { + + int waitTime = 30; + final int defaultWaitTime = waitTime; + int duration = map.getDuration(); + final int seekerDeploy = duration - 15; + + + @Override + public void run() { + if (waitTime != 0) { + int playerSize = players.size(); + if (playerSize >= map.getMinPlayers()) { + if (waitTime % 5 == 0 || waitTime <= 5) { + Localization.sendMessage( + players.keySet(), + true, + "wait-time-left", + "{time}", String.valueOf(waitTime) + ); + } + waitTime--; + } else if (playerSize == 0) { + end(true); + this.cancel(); + } else if (waitTime != defaultWaitTime) { + waitTime = defaultWaitTime; + } + } else { + if (!started.get()) { + start(); + } else { + + if (players.isEmpty()) end(false); + + if (duration > 0 && getHidersCount() == 0) { + Localization.sendTitle( + players.keySet(), + false, + "seekers-won" + ); + duration = -1; + } + + if (duration == seekerDeploy) { + for (Player seeker : getSeekers()) { + seeker.teleport(spawn); + } + } + + if (duration == 0) { + preEnd(); + if (getHidersCount() == 1) { + Localization.sendTitle( + players.keySet(), + false, + "hiders-solo-win", + "{hider}", getLastHider().getName() + ); + } else { + Localization.sendTitle( + players.keySet(), + false, + "hiders-won" + ); + } + duration--; // уменьшаем только один раз + } else if (duration > 0) { + Localization.sendActionBar( + players.keySet(), + false, + "game-time-left", + "{time}", String.valueOf(duration) + ); + duration--; + } else if (duration == -10) { + this.cancel(); + end(false); + } else { + duration--; + } + } + } + } + + + }.runTaskTimer(BlockAndSeek.getInstance(), 0L, 20L); + } + + private enum PlayerType { SEEKER, HIDER, diff --git a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekMap.java b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekMap.java index e00fd54..a8bbfb7 100644 --- a/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekMap.java +++ b/src/main/java/hdvtdev/blockAndSeek/BlockAndSeekMap.java @@ -1,10 +1,13 @@ package hdvtdev.blockAndSeek; +import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.*; @@ -35,6 +38,10 @@ public class BlockAndSeekMap implements ConfigurationSerializable { return spawn; } + public Location getSpawnLocation(@Nullable World world) { + return new Location(world, spawn.getFirst(), spawn.get(1), spawn.get(2)); + } + public void setSpawn(List spawn) { this.spawn = spawn; } @@ -43,6 +50,10 @@ public class BlockAndSeekMap implements ConfigurationSerializable { return lobby; } + public Location getLobbyLocation(@Nullable World world) { + return new Location(world, lobby.getFirst(), lobby.get(1), lobby.get(2)); + } + public void setLobby(List lobby) { this.lobby = lobby; } diff --git a/src/main/java/hdvtdev/blockAndSeek/CommandListener.java b/src/main/java/hdvtdev/blockAndSeek/CommandListener.java index 0cc37ff..9012737 100644 --- a/src/main/java/hdvtdev/blockAndSeek/CommandListener.java +++ b/src/main/java/hdvtdev/blockAndSeek/CommandListener.java @@ -5,12 +5,15 @@ package hdvtdev.blockAndSeek; //import com.mojang.brigadier.builder.RequiredArgumentBuilder; import hdvtdev.blockAndSeek.managers.*; +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.minimessage.MiniMessage; +import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.attribute.Attribute; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; @@ -73,9 +76,21 @@ public class CommandListener implements TabExecutor { DisguiseAPI.disguiseToAll(player, new MiscDisguise(DisguiseType.FALLING_BLOCK, new ItemStack(material))); } } - case "armor" -> { + + case "new" -> { if (sender instanceof Player player) { - player.getInventory().setArmorContents(ItemManager.getSeekerArmor()); + RouletteCreator.newCreateRoulette(player, List.of( + new BlockAndSeekMap.Block(new ItemStack(Material.STONE), 10), + new BlockAndSeekMap.Block(new ItemStack(Material.DIRT), 10), + new BlockAndSeekMap.Block(new ItemStack(Material.LANTERN), 10), + new BlockAndSeekMap.Block(new ItemStack(Material.TARGET), 10), + new BlockAndSeekMap.Block(new ItemStack(Material.SCULK_SHRIEKER), 10), + new BlockAndSeekMap.Block(new ItemStack(Material.FLOWER_POT), 10), + new BlockAndSeekMap.Block(new ItemStack(Material.AZALEA_LEAVES), 10), + new BlockAndSeekMap.Block(new ItemStack(Material.PUMPKIN), 10), + new BlockAndSeekMap.Block(new ItemStack(Material.MELON), 10), + new BlockAndSeekMap.Block(new ItemStack(Material.DIAMOND_BLOCK), 10) + )); } } case "foo" -> { @@ -88,6 +103,25 @@ public class CommandListener implements TabExecutor { player.getInventory().addItem(foo); } } + case "container" -> { + if (sender instanceof Player player) { + player.sendMessage(String.valueOf(player.getPersistentDataContainer().has(Keys.GAME))); + } + } + case "def" -> { + if (sender instanceof Player player) { + player.setVisibleByDefault(true); + player.setInvisible(false); + player.setInvulnerable(false); + player.setGameMode(GameMode.SURVIVAL); + player.setGlowing(false); + player.clearActivePotionEffects(); + player.setHealth(player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getDefaultValue()); + player.setFoodLevel(20); + DisguiseAPI.undisguiseToAll(player); + + } + } case "map" -> { if (sender.hasPermission("blockandseek.manage")) { if (argsLen > 1) { diff --git a/src/main/java/hdvtdev/blockAndSeek/Config.java b/src/main/java/hdvtdev/blockAndSeek/Config.java new file mode 100644 index 0000000..40dfd1e --- /dev/null +++ b/src/main/java/hdvtdev/blockAndSeek/Config.java @@ -0,0 +1,41 @@ +package hdvtdev.blockAndSeek; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public record Config(@NotNull Location defaultSpawn, boolean forceControl) implements ConfigurationSerializable { + + @Override + public @NotNull Map serialize() { + Map map = new HashMap<>(); + map.put("default-spawn", defaultSpawn.serialize()); + map.put("force-control", Boolean.valueOf(forceControl)); + return map; + } + + @NotNull + @SuppressWarnings("unchecked") + public static Config deserialize(@NotNull Map args) { + Map location = (Map) args.get("default-spawn"); + List cords = location == null || location.isEmpty() ? List.of() : (List) location.get("location"); + World world = location == null || location.isEmpty() ? null : Bukkit.getWorld((String) location.get("world")); + if (world == null) { + world = Bukkit.createWorld(new WorldCreator("world")); + } + if (cords.isEmpty() || cords.size() < 3) { + Location spawn = world.getSpawnLocation(); + cords = List.of((int) spawn.getX(), (int) spawn.getY(), (int) spawn.getZ()); + } + return new Config(new Location(world, cords.getFirst(), cords.get(1), cords.get(2)), (Boolean) args.get("force-control")); + } + + +} \ No newline at end of file diff --git a/src/main/java/hdvtdev/blockAndSeek/Keys.java b/src/main/java/hdvtdev/blockAndSeek/Keys.java index d1a7ce0..11aa27e 100644 --- a/src/main/java/hdvtdev/blockAndSeek/Keys.java +++ b/src/main/java/hdvtdev/blockAndSeek/Keys.java @@ -10,11 +10,15 @@ public class Keys { public static final NamespacedKey SOUND_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekSoundItem"); public static final NamespacedKey FREEZE_ITEM = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekFreezeItem"); 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 GAME_PAGE = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekGamePage"); public static final NamespacedKey FROZEN_PLAYER = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekFrozenPlayer"); - public static final NamespacedKey PLAYER = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekPlayer"); public static final NamespacedKey GAME = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekGame"); + public static final NamespacedKey HIDER = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekHider"); + public static final NamespacedKey SEEKER = new NamespacedKey(BlockAndSeek.getInstance(), "BlockAndSeekSeeker"); + public static final Team NO_COLLIDE_TEAM; static { @@ -23,5 +27,7 @@ public class Keys { if (team == null) team = scoreboard.registerNewTeam("BlockAndSeekNoCollide"); team.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER); NO_COLLIDE_TEAM = team; + + } } diff --git a/src/main/java/hdvtdev/blockAndSeek/Localization.java b/src/main/java/hdvtdev/blockAndSeek/Localization.java index 7d58076..5e3a6f3 100644 --- a/src/main/java/hdvtdev/blockAndSeek/Localization.java +++ b/src/main/java/hdvtdev/blockAndSeek/Localization.java @@ -3,53 +3,107 @@ package hdvtdev.blockAndSeek; import hdvtdev.blockAndSeek.managers.ConfigManager; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import net.kyori.adventure.title.Title; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.Map; + public class Localization { private static volatile Map> localization = Collections.unmodifiableMap(ConfigManager.getLocalization()); + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + private static final PlainTextComponentSerializer plainText = PlainTextComponentSerializer.plainText(); private static final Component prefix = miniMessage.deserialize("[BlockAndSeek] "); + private static final Component empty = Component.empty(); public static void update() { localization = Collections.unmodifiableMap(ConfigManager.getLocalization()); } - public static String get(@NotNull String key, String... replacements) { - return getLang(null, key, replacements); + public static ItemStack translateItem(@NotNull Player player, @NotNull ItemStack itemStack, @NotNull String... replacements) { + ItemStack translatedItem = itemStack.clone(); + ItemMeta itemMeta = translatedItem.getItemMeta(); + String key = plainText.serialize(itemMeta.displayName()); + itemMeta.displayName(getComponent(player.locale().toLanguageTag(), key, replacements)); + translatedItem.setItemMeta(itemMeta); + return translatedItem; } - public static String getLang(@Nullable String lang, @NotNull String key, String... replacements) { - lang = lang == null || !localization.containsKey(lang) ? "en-US" : lang; + public static void sendMessage(@NotNull Iterable players, boolean addPrefix, @NotNull String key, @NotNull String... replacements) { + for (Player player : players) { + sendMessage(player, addPrefix, key, replacements); + } + } + + public static void sendMessage(@NotNull Player player, boolean addPrefix, @NotNull String key, @NotNull String... replacements) { + Component component = getComponent(player.locale().toLanguageTag(), key, replacements); + player.sendMessage(addPrefix ? prefix.append(component) : component); + } + + public static void sendActionBar(@NotNull Iterable players, boolean addPrefix, @NotNull String key, @NotNull String... replacements) { + for (Player player : players) { + sendActionBar(player, addPrefix, key, replacements); + } + } + + @Deprecated + public static String get(String a) { + return ""; + } + + @Deprecated + public static Component getComponent(String a) { + return empty; + } + + @Deprecated + public static Component getComponentWithPrefix(String... a) { + return empty; + } - String s = localization.get(lang).get(key); + public static void sendActionBar(@NotNull Player player, boolean addPrefix, @NotNull String key, @NotNull String... replacements) { + Component component = getComponent(player.locale().toLanguageTag(), key, replacements); + player.sendActionBar(addPrefix ? prefix.append(component) : component); + } + + public static void sendTitle(@NotNull Iterable players, boolean addPrefix, @NotNull String key, @NotNull String... replacements) { + for (Player player : players) { + sendTitle(player, addPrefix, key, replacements); + } + } + + public static void sendTitle(@NotNull Player player, boolean addPrefix, @NotNull String key, @NotNull String... replacements) { + Component component = getComponent(player.locale().toLanguageTag(), key, replacements); + player.showTitle(Title.title(addPrefix ? prefix.append(component) : component, empty)); + } + + public static @NotNull Component getComponent(@NotNull Player p, @NotNull String key, @NotNull String... replacements) { + return getComponent(p.locale().toLanguageTag(), key, replacements); + } + + public static @NotNull Component getComponent(@NotNull String lang, @NotNull String key, @NotNull String... replacements) { + return miniMessage.deserialize(get(lang, key, replacements)); + } + + public static @NotNull String get(@NotNull String lang, @NotNull String key, @NotNull String... replacements) { + + String s = localization.getOrDefault(lang, localization.get("en-US")).get(key); if (s != null) { for (int i = 0; i < replacements.length; i += 2) { s = s.replace(replacements[i], replacements[i + 1]); } } else return "Unknown localization: " + key; + + return s; } - public static Component getComponent(String key, String... replacements) { - return getLangComponent(null, key, replacements); - } - - public static Component getLangComponent(String lang, String key, String... replacements) { - return miniMessage.deserialize(getLang(lang, key, replacements)); - } - - public static Component getLangComponentWithPrefix(String lang, String key, String... replacements) { - return prefix.append(getLangComponent(lang, key, replacements)); - } - - public static Component getComponentWithPrefix(String key, String... replacements) { - return prefix.append(getLangComponent(null, key, replacements)); - } - } diff --git a/src/main/java/hdvtdev/blockAndSeek/EventListener.java b/src/main/java/hdvtdev/blockAndSeek/eventListeners/EventListener.java similarity index 59% rename from src/main/java/hdvtdev/blockAndSeek/EventListener.java rename to src/main/java/hdvtdev/blockAndSeek/eventListeners/EventListener.java index f14e7a2..fa5345d 100644 --- a/src/main/java/hdvtdev/blockAndSeek/EventListener.java +++ b/src/main/java/hdvtdev/blockAndSeek/eventListeners/EventListener.java @@ -1,6 +1,8 @@ -package hdvtdev.blockAndSeek; +package hdvtdev.blockAndSeek.eventListeners; +import hdvtdev.blockAndSeek.BlockAndSeek; +import hdvtdev.blockAndSeek.Keys; import hdvtdev.blockAndSeek.managers.FreezeManager; import hdvtdev.blockAndSeek.managers.GamesManager; import hdvtdev.blockAndSeek.managers.GuiManager; @@ -17,24 +19,24 @@ import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockDamageEvent; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDismountEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.Vector; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -49,9 +51,6 @@ public class EventListener implements Listener { private static final ConcurrentHashMap tasks = new ConcurrentHashMap<>(); private static final ConcurrentHashMap soundCoolDown = new ConcurrentHashMap<>(); - - private static final Vector ZERO_VELOCITY = new Vector(0, 0, 0); - private static final ItemStack freezeItem = ItemManager.getFreezeItem(); private static final ItemStack menuItem = ItemManager.getMenuItem(); public static void createTask(Player player, BukkitTask bukkitTask) { @@ -63,28 +62,38 @@ public class EventListener implements Listener { task.cancel(); } + private static boolean playerInGame(Player player) { + return player.getPersistentDataContainer().has(Keys.GAME); + } + + private static boolean isInOneTeam(Player p1, Player p2) { + var c1 = p1.getPersistentDataContainer(); + var c2 = p2.getPersistentDataContainer(); + return (c1.has(Keys.HIDER) && c2.has(Keys.HIDER)) || (c1.has(Keys.SEEKER) && c2.has(Keys.SEEKER)); + } + @EventHandler public void onDrop(PlayerDropItemEvent event) { - event.setCancelled(true); + if (event.getPlayer().getPersistentDataContainer().has(Keys.GAME)) event.setCancelled(true); } @EventHandler public void onBlockDamage(BlockDamageEvent event) { - - if (FreezeManager.unfreeze(event.getBlock().getBlockData())) event.setCancelled(true); + if (event.getPlayer().getPersistentDataContainer().has(Keys.SEEKER)) { + if (FreezeManager.unfreeze(event.getBlock().getBlockData())) event.setCancelled(true); + } } @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); if (player.getVehicle() instanceof ArmorStand armorStand) { - armorStand.getPersistentDataContainer().remove(Keys.FROZEN_PLAYER); - armorStand.remove(); + PersistentDataContainer armorStandContainer = armorStand.getPersistentDataContainer(); + if (armorStandContainer.has(Keys.FROZEN_PLAYER)) { + armorStandContainer.remove(Keys.FROZEN_PLAYER); + armorStand.remove(); + } } - - Inventory inventory = player.getInventory(); - if (!inventory.contains(ItemManager.getMenuItem())) inventory.addItem(ItemManager.getMenuItem()); - } @EventHandler @@ -92,9 +101,8 @@ public class EventListener implements Listener { Player player = event.getPlayer(); PersistentDataContainer container = player.getPersistentDataContainer(); - String arena = container.get(Keys.PLAYER, PersistentDataType.STRING); + String arena = container.get(Keys.GAME, PersistentDataType.STRING); if (arena != null) { - container.remove(Keys.PLAYER); GamesManager.get(arena).removePlayer(player); FreezeManager.removePlayerDisguise(player); } @@ -102,7 +110,15 @@ public class EventListener implements Listener { @EventHandler public void onPlayerDeath(PlayerDeathEvent event) { - + Player player = event.getPlayer(); + String game = player.getPersistentDataContainer().get(Keys.GAME, PersistentDataType.STRING); + if (game != null) { + event.deathMessage(null); + event.setDroppedExp(0); + event.getDrops().clear(); + scheduler.runTask(BlockAndSeek.getInstance(), () -> GamesManager.get(game).setSpectator(player, player.getKiller())); + //without scheduler strange things are happening idk + } } @EventHandler @@ -113,6 +129,14 @@ public class EventListener implements Listener { } } + @EventHandler + public void onFoodLevelChange(FoodLevelChangeEvent event) { + if (event.getEntity() instanceof Player player && playerInGame(player)) { + event.setCancelled(true); + event.getEntity().setFoodLevel(20); + } + } + @EventHandler public void onRightClick(PlayerInteractEvent event) { @@ -123,59 +147,82 @@ public class EventListener implements Listener { ItemStack itemInHand = player.getInventory().getItemInMainHand(); + ItemMeta meta = itemInHand.getItemMeta(); - if (itemInHand.equals(freezeItem)) { - coolDown.add(player); - scheduler.runTaskLater(BlockAndSeek.getInstance(), () -> coolDown.remove(player), 3L); - FreezeManager.freeze(player); - event.setCancelled(true); - } else if (itemInHand.equals(menuItem)) { - GuiManager.Menu.open(player); + if (meta != null) { + PersistentDataContainer itemData = meta.getPersistentDataContainer(); + if (itemData.has(Keys.FREEZE_ITEM) && playerInGame(player)) { + coolDown.add(player); + scheduler.runTaskLater(BlockAndSeek.getInstance(), () -> coolDown.remove(player), 3L); + FreezeManager.freeze(player); + event.setCancelled(true); + } else if (itemData.has(Keys.MENU_ITEM)) { + GuiManager.Menu.open(player); + event.setCancelled(true); + } else if (itemData.has(Keys.LEAVE_ITEM)) { + String game = player.getPersistentDataContainer().get(Keys.GAME, PersistentDataType.STRING); + GamesManager.get(game).removePlayer(player); + event.setCancelled(true); + } } + + } } @EventHandler public void onBlockPlacement(BlockPlaceEvent event) { - event.setCancelled(true); + if (event.getPlayer().getPersistentDataContainer().has(Keys.GAME)) event.setCancelled(true); } @EventHandler public void onBlockBreak(BlockBreakEvent event) { - event.setCancelled(true); + if (event.getPlayer().getPersistentDataContainer().has(Keys.GAME)) event.setCancelled(true); } + @EventHandler + public void onPlayerDamage(EntityDamageByEntityEvent event) { + if (event.getDamager() instanceof Player damager && event.getEntity() instanceof Player victim) { + if (isInOneTeam(damager, victim)) { + event.setCancelled(true); + } + } + } @EventHandler public void onInventoryClick(InventoryClickEvent event) { Player player = (Player) event.getWhoClicked(); Inventory inventory = event.getClickedInventory(); + if (inventory != null) { - InventoryHolder holder = inventory.getHolder(); - switch (holder) { - case GuiManager.Menu ignored -> { - switch (event.getSlot()) { - case 13 -> { - GuiManager.Menu.Games.open(player); - } - default -> { + + ItemStack item = inventory.getItem(event.getSlot()); + + + if (item != null) { + ItemMeta meta = item.getItemMeta(); + if (meta != null) { + PersistentDataContainer itemData = meta.getPersistentDataContainer(); + + if (itemData.has(Keys.GAME_PAGE)) { + GuiManager.Menu.Games.open(player); + event.setCancelled(true); + } else if (itemData.has(Keys.GAME)) { + String game = itemData.get(Keys.GAME, PersistentDataType.STRING); + if (game != null) { + GamesManager.get(game).addPlayer(player); + event.setCancelled(true); } } - event.setCancelled(true); - } - case GuiManager.Menu.Games ignored -> { - ItemStack game = event.getCurrentItem(); - if (game != null) { - String gameName = game.getItemMeta().getPersistentDataContainer().get(Keys.GAME, PersistentDataType.STRING); - if (gameName != null) GamesManager.get(gameName).addPlayer(player); - } - event.setCancelled(true); - } - case null, default -> { } } + + } + + if (player.getPersistentDataContainer().has(Keys.GAME)) { + event.setCancelled(true); } if (player.hasMetadata("RollingMenu")) { @@ -190,8 +237,6 @@ public class EventListener implements Listener { player.closeInventory(InventoryCloseEvent.Reason.UNKNOWN); } } - } else if (event.getSlotType().equals(InventoryType.SlotType.ARMOR)) { - event.setCancelled(true); } diff --git a/src/main/java/hdvtdev/blockAndSeek/eventListeners/ForceControlEventListener.java b/src/main/java/hdvtdev/blockAndSeek/eventListeners/ForceControlEventListener.java new file mode 100644 index 0000000..8b461a6 --- /dev/null +++ b/src/main/java/hdvtdev/blockAndSeek/eventListeners/ForceControlEventListener.java @@ -0,0 +1,75 @@ +package hdvtdev.blockAndSeek.eventListeners; + +import hdvtdev.blockAndSeek.Keys; +import hdvtdev.blockAndSeek.managers.ItemManager; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.weather.WeatherChangeEvent; +import org.bukkit.event.world.TimeSkipEvent; +import org.bukkit.persistence.PersistentDataContainer; + +public class ForceControlEventListener implements Listener { + + private static boolean hasPermsToDamage(Player p1, Player p2) { + PersistentDataContainer c1 = p1.getPersistentDataContainer(); + PersistentDataContainer c2 = p2.getPersistentDataContainer(); + return (c1.has(Keys.SEEKER) || c1.has(Keys.HIDER)) && (c2.has(Keys.SEEKER) || c2.has(Keys.HIDER)); + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + ItemManager.defaultInventory(player); + } + + @EventHandler + public void onWeatherChange(WeatherChangeEvent event) { + if (event.getCause() != WeatherChangeEvent.Cause.COMMAND) event.setCancelled(true); + } + + @EventHandler + public void onTimeSkip(TimeSkipEvent event) { + if (event.getSkipReason() != TimeSkipEvent.SkipReason.COMMAND) event.setCancelled(true); + } + + @EventHandler + public void onBlockPlacement(BlockPlaceEvent event) { + event.setCancelled(true); + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + event.setCancelled(true); + } + + @EventHandler + public void onFoodLevelChange(FoodLevelChangeEvent event) { + if (event.getEntity() instanceof Player player) { + event.setCancelled(true); + player.setFoodLevel(20); + } + } + + @EventHandler + public void onDrop(PlayerDropItemEvent event) { + event.setCancelled(true); + } + + @EventHandler + public void onPlayerDamage(EntityDamageByEntityEvent event) { + if (event.getDamager() instanceof Player damager && event.getEntity() instanceof Player victim) { + if (!hasPermsToDamage(damager, victim)) { + event.setCancelled(true); + } + } + } + + +} diff --git a/src/main/java/hdvtdev/blockAndSeek/managers/ConfigManager.java b/src/main/java/hdvtdev/blockAndSeek/managers/ConfigManager.java index 46ad566..5d29775 100644 --- a/src/main/java/hdvtdev/blockAndSeek/managers/ConfigManager.java +++ b/src/main/java/hdvtdev/blockAndSeek/managers/ConfigManager.java @@ -2,6 +2,7 @@ package hdvtdev.blockAndSeek.managers; import hdvtdev.blockAndSeek.BlockAndSeek; import hdvtdev.blockAndSeek.BlockAndSeekMap; +import hdvtdev.blockAndSeek.Config; import hdvtdev.blockAndSeek.Localization; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; @@ -17,15 +18,16 @@ import java.util.concurrent.ConcurrentHashMap; public class ConfigManager { private static volatile Map> localization; - private static volatile Map config; + private static volatile Config config; private static Map maps = new ConcurrentHashMap<>(); private static final File mapsFile = new File(BlockAndSeek.getPluginDataFolder(), "maps.yml"); - public static BlockAndSeekMap getMap(String name) { - return maps.get(name); + public static Config getConfig() { + return config; } + public static Set getAllMaps() { return YamlConfiguration.loadConfiguration(mapsFile).getKeys(false); } @@ -47,14 +49,9 @@ public class ConfigManager { BlockAndSeek.saveResource(file); + /* switch (file) { - case "config.yml" -> { - Map confMap = new HashMap<>(); - for (String key : defaultConfiguration.getKeys(false)) { - confMap.put(key, defaultConfiguration.getString(key, "NULL")); - } - config = confMap; - } + case "config.yml" -> config = defaultConfiguration.getSerializable("config", Config.class); case "localization.yml" -> { Map> confMap = new HashMap<>(); Map lang = new HashMap<>(); @@ -67,36 +64,26 @@ public class ConfigManager { } } + */ - } else { - switch (file) { - case "config.yml" -> loadConfig(conf, defaultConfiguration); - case "localization.yml" -> loadLocalization(conf, defaultConfiguration); - case "maps.yml" -> MapsManager.loadMaps(); - } + + } + + switch (file) { + case "config.yml" -> loadConfig(conf, defaultConfiguration); + case "localization.yml" -> loadLocalization(conf, defaultConfiguration); + case "maps.yml" -> MapsManager.loadMaps(); } } - private static void loadConfig(File configurationFile, YamlConfiguration defaultConfiguration) throws IOException { - ConcurrentHashMap confMap = new ConcurrentHashMap<>(); + private static void loadConfig(File configurationFile, YamlConfiguration defaultConfiguration) { YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configurationFile); + configuration.setDefaults(defaultConfiguration); - for (String key : defaultConfiguration.getKeys(false)) { - if (configuration.isSet(key)) { - confMap.put(key, configuration.getString(key, defaultConfiguration.getString(key, "NULL"))); - } else { - String value = defaultConfiguration.getString(key, "NULL"); - configuration.set(key, value); - confMap.put(key, value); - } - } - - configuration.save(configurationFile); - - config = confMap; + config = configuration.getSerializable("config", Config.class); } private static void loadLocalization(File configurationFile, YamlConfiguration defaultConfiguration) throws IOException { @@ -135,6 +122,7 @@ public class ConfigManager { configuration.save(configurationFile); localization = confMap; + Localization.update(); } diff --git a/src/main/java/hdvtdev/blockAndSeek/managers/GamesManager.java b/src/main/java/hdvtdev/blockAndSeek/managers/GamesManager.java index 84f13e5..bfc4c3d 100644 --- a/src/main/java/hdvtdev/blockAndSeek/managers/GamesManager.java +++ b/src/main/java/hdvtdev/blockAndSeek/managers/GamesManager.java @@ -4,22 +4,14 @@ import hdvtdev.blockAndSeek.BlockAndSeek; import hdvtdev.blockAndSeek.BlockAndSeekGame; import hdvtdev.blockAndSeek.BlockAndSeekMap; import hdvtdev.blockAndSeek.Localization; -import hdvtdev.blockAndSeek.roulette.RouletteCreator; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.title.Title; import org.bukkit.Bukkit; -import org.bukkit.Location; import org.bukkit.WorldCreator; -import org.bukkit.entity.Player; -import org.bukkit.inventory.PlayerInventory; -import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scoreboard.Criteria; import org.bukkit.scoreboard.DisplaySlot; import org.bukkit.scoreboard.Objective; import org.bukkit.scoreboard.Scoreboard; import java.io.File; -import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -45,111 +37,16 @@ public class GamesManager { } BlockAndSeekMap map = MapsManager.getMap(name); - System.out.println(map); - BlockAndSeekGame game = new BlockAndSeekGame(name, map.getMaxPlayers(), map.getLobby()); - List spawnCords = map.getSpawn(); - List lobbyCords = map.getLobby(); + BlockAndSeekGame game = new BlockAndSeekGame(name, map); + games.put(name, game); - - new BukkitRunnable() { - - int duration = map.getDuration() + 10; - final int seekerSpawn = duration - 15; - int gameEnd = duration - 10; - int waitTime = 30; - final Location spawn = new Location(Bukkit.getWorld(name), spawnCords.getFirst(), spawnCords.get(1), spawnCords.get(2)); - Player seeker; - - @Override - public void run() { - - if (!game.isStarted()) { - int playerCount = game.playerCount(); - - for (Player player : game.getPlayers()) { - player.sendActionBar(Component.text("Игроков " + playerCount + "/12")); //TODO! - } - - if (playerCount >= map.getMinPlayers()) { - - if (waitTime == 0 || playerCount == map.getMaxPlayers()) { - game.start(); - seeker = game.selectRandomSeeker(); - - for (Player player : game.getHiders()) { - player.teleport(spawn); - PlayerInventory inventory = player.getInventory(); - inventory.clear(); - inventory.addItem(ItemManager.getFreezeItem()); - RouletteCreator.createRoulette(player, null, true, map.getBlocks()); - } - - } else { - if (waitTime < 5 || waitTime % 5 == 0) { - for (Player player : game.getPlayers()) { - player.sendMessage(Localization.getLangComponentWithPrefix(player.locale().toLanguageTag(), "wait-time-left", "{time}", String.valueOf(waitTime))); - } - } - waitTime--; - } - - } else waitTime = 10; - - } else { - - if (seekerSpawn == gameEnd) { - seeker.teleport(spawn); - PlayerInventory seekerInventory = seeker.getInventory(); - seekerInventory.setArmorContents(ItemManager.getSeekerArmor()); - } - - if (game.hidersCount() == 0) { - - for (Player player : game.getPlayers()) { - player.showTitle(Title.title(Localization.getComponent("seekers-won"), Component.text(""))); - } - - game.preEnd(); - games.remove(name); - - } - - for (Player player : game.getPlayers()) { - player.sendActionBar(Localization.getComponent("game-time-left", "{time}", String.valueOf(gameEnd))); - } - - if (gameEnd == 0) { - if (game.hidersCount() == 1) { - for (Player player : game.getPlayers()) { - player.showTitle(Title.title(Localization.getComponent("hiders-solo-win", "{player}", game.getLastHider().getName()), Component.text(""))); - } - } else { - for (Player player : game.getPlayers()) { - player.showTitle(Title.title(Localization.getComponent("hiders-won"), Component.text(""))); - } - } - - game.preEnd(); - games.remove(name); - - } else gameEnd--; - - if (duration == 0) { - this.cancel(); - } - - } - - - } - - - }.runTaskTimer(BlockAndSeek.getInstance(), 0L, 20L); - - return 0; } + public static void remove(String name) { + games.remove(name); + } + public static BlockAndSeekGame get(String name) { return games.get(name); } diff --git a/src/main/java/hdvtdev/blockAndSeek/managers/GuiManager.java b/src/main/java/hdvtdev/blockAndSeek/managers/GuiManager.java index e29108e..a6ad179 100644 --- a/src/main/java/hdvtdev/blockAndSeek/managers/GuiManager.java +++ b/src/main/java/hdvtdev/blockAndSeek/managers/GuiManager.java @@ -1,7 +1,9 @@ package hdvtdev.blockAndSeek.managers; +import hdvtdev.blockAndSeek.BlockAndSeekGame; import hdvtdev.blockAndSeek.Keys; import hdvtdev.blockAndSeek.Localization; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -12,6 +14,8 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; +import java.util.List; + public class GuiManager { private static final ItemStack filler1 = new ItemStack(Material.ORANGE_STAINED_GLASS_PANE); @@ -40,24 +44,22 @@ public class GuiManager { public static final Menu instance = new Menu(); - private static final Inventory mainMenu = Bukkit.createInventory(instance, 27, Localization.getComponent("menu-item")); - - static { - fill(mainMenu); - mainMenu.setItem(13, ItemManager.getGamesPageItem()); - } private Menu() { } public static void open(Player player) { - player.openInventory(mainMenu); + + Inventory inventory = Bukkit.createInventory(instance, 27, Localization.getComponent(player, "menu-item")); + inventory.setItem(13, Localization.translateItem(player, ItemManager.getGamesPageItem())); + + player.openInventory(inventory); } @Override public @NotNull Inventory getInventory() { - return mainMenu; + return Bukkit.createInventory(instance, 27, Component.text("raw")); } public static class Games implements InventoryHolder { @@ -69,14 +71,21 @@ public class GuiManager { public static void open(Player player) { - Inventory gamesMenu = Bukkit.createInventory(new Games(), 45, Localization.getComponent("menu-item")); + Inventory gamesMenu = Bukkit.createInventory(new Games(), 45, Localization.getComponent(player, "games-page-item")); for (String game : GamesManager.getAvailableGames()) { + BlockAndSeekGame blockAndSeekGame = GamesManager.get(game); ItemStack gameItem = defaultGameItem.clone(); ItemMeta meta = gameItem.getItemMeta(); meta.getPersistentDataContainer().set(Keys.GAME, PersistentDataType.STRING, game); - meta.displayName(Localization.getComponent("game-name", "{name}", game)); + meta.displayName(Component.text("game-name")); + meta.lore(List.of(Localization.getComponent( + player, + "game-player-count", + "{players}", String.valueOf(blockAndSeekGame.playerCount()), + "{max-players}", String.valueOf(blockAndSeekGame.maxPlayers()) + ))); gameItem.setItemMeta(meta); - gamesMenu.addItem(gameItem); + gamesMenu.addItem(Localization.translateItem(player, gameItem, "{name}", game)); } diff --git a/src/main/java/hdvtdev/blockAndSeek/managers/ItemManager.java b/src/main/java/hdvtdev/blockAndSeek/managers/ItemManager.java index 74a7b8c..99b4d79 100644 --- a/src/main/java/hdvtdev/blockAndSeek/managers/ItemManager.java +++ b/src/main/java/hdvtdev/blockAndSeek/managers/ItemManager.java @@ -2,6 +2,7 @@ package hdvtdev.blockAndSeek.managers; import hdvtdev.blockAndSeek.Keys; import hdvtdev.blockAndSeek.Localization; +import net.kyori.adventure.text.Component; import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -17,53 +18,83 @@ public class ItemManager { private static final ItemStack freezeItem = new ItemStack(Material.HEART_OF_THE_SEA); + private static final ItemStack seekerSword = new ItemStack(Material.WOODEN_SWORD); + private static final ItemStack seekerHelmet = new ItemStack(Material.LEATHER_HELMET); + private static final ItemStack seekerChestplate = new ItemStack(Material.LEATHER_CHESTPLATE); + private static final ItemStack seekerLeggings = new ItemStack(Material.LEATHER_LEGGINGS); + private static final ItemStack seekerBoots = new ItemStack(Material.LEATHER_BOOTS); + private static final ItemStack menuItem = new ItemStack(Material.COMPASS); private static final ItemStack games = new ItemStack(Material.BOOKSHELF); private static final ItemStack createGameButton = new ItemStack(Material.SLIME_BALL); + private static final ItemStack leaveItem = new ItemStack(Material.RED_DYE); - private static final ItemStack[] seekerSet; static { ItemMeta freezeMeta = freezeItem.getItemMeta(); - freezeMeta.displayName(Localization.getComponent("freeze-item")); + freezeMeta.displayName(Component.text("freeze-item")); freezeMeta.getPersistentDataContainer().set(Keys.FREEZE_ITEM, PersistentDataType.BOOLEAN, true); freezeItem.setItemMeta(freezeMeta); + ItemMeta swordMeta = seekerSword.getItemMeta(); + swordMeta.displayName(Component.text("seeker-sword")); + swordMeta.addEnchant(Enchantment.DAMAGE_ALL, 2, false); + swordMeta.setUnbreakable(true); + swordMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_ATTRIBUTES); + seekerSword.setItemMeta(swordMeta); + ItemMeta menuMeta = menuItem.getItemMeta(); - menuMeta.displayName(Localization.getComponent("menu-item")); + menuMeta.displayName(Component.text("menu-item")); 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 gamesMeta = games.getItemMeta(); - gamesMeta.displayName(Localization.getComponent("games-page-item")); + gamesMeta.displayName(Component.text("games-page-item")); + gamesMeta.getPersistentDataContainer().set(Keys.GAME_PAGE, PersistentDataType.BOOLEAN, true); games.setItemMeta(gamesMeta); + ItemMeta leaveMeta = leaveItem.getItemMeta(); + leaveMeta.displayName(Component.text("leave-item")); + leaveMeta.getPersistentDataContainer().set(Keys.LEAVE_ITEM, PersistentDataType.BOOLEAN, true); + leaveItem.setItemMeta(leaveMeta); + ItemMeta createGameButtonMeta = createGameButton.getItemMeta(); - createGameButtonMeta.displayName(Localization.getComponent("create-game-item")); + createGameButtonMeta.displayName(Component.text("create-game-item")); createGameButton.setItemMeta(createGameButtonMeta); - ItemStack seekerHelmet = new ItemStack(Material.LEATHER_HELMET); - ItemStack seekerChestplate = new ItemStack(Material.LEATHER_CHESTPLATE); - ItemStack seekerLeggings = new ItemStack(Material.LEATHER_LEGGINGS); - ItemStack seekerBoots = new ItemStack(Material.LEATHER_BOOTS); seekerHelmet.setItemMeta(color(seekerHelmet)); seekerBoots.setItemMeta(color(seekerBoots)); seekerChestplate.setItemMeta(color(seekerChestplate)); seekerLeggings.setItemMeta(color(seekerLeggings)); - seekerSet = new ItemStack[]{seekerBoots, seekerLeggings, seekerChestplate, seekerHelmet}; + } + public static void setSeekerSet(Player seeker) { + PlayerInventory inventory = seeker.getInventory(); + inventory.clear(); + inventory.addItem(Localization.translateItem(seeker, seekerSword)); + ItemStack[] armor = new ItemStack[]{ + Localization.translateItem(seeker, seekerBoots), + Localization.translateItem(seeker, seekerLeggings), + Localization.translateItem(seeker, seekerChestplate), + Localization.translateItem(seeker, seekerHelmet) + }; + inventory.setArmorContents(armor); + + } + + private static ItemMeta color(ItemStack item) { LeatherArmorMeta meta = (LeatherArmorMeta) item.getItemMeta(); meta.setColor(Color.RED); meta.setUnbreakable(true); meta.addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 10, true); - meta.displayName(Localization.getComponent("seeker-armor")); + meta.displayName(Component.text("seeker-armor")); return meta; } @@ -71,7 +102,11 @@ public class ItemManager { public static void defaultInventory(Player player) { PlayerInventory inventory = player.getInventory(); inventory.clear(); - inventory.addItem(menuItem); + inventory.addItem(Localization.translateItem(player, menuItem)); + } + + public static ItemStack getLeaveItem() { + return leaveItem; } public static ItemStack getCreateGameButton() { @@ -86,10 +121,6 @@ public class ItemManager { return menuItem; } - public static ItemStack[] getSeekerArmor() { - return seekerSet; - } - public static ItemStack getFreezeItem() { return freezeItem; } diff --git a/src/main/java/hdvtdev/blockAndSeek/managers/MapsManager.java b/src/main/java/hdvtdev/blockAndSeek/managers/MapsManager.java index 6a464cd..3c42cb5 100644 --- a/src/main/java/hdvtdev/blockAndSeek/managers/MapsManager.java +++ b/src/main/java/hdvtdev/blockAndSeek/managers/MapsManager.java @@ -21,13 +21,6 @@ public class MapsManager { return allMaps.keySet(); } - public static void test() { - System.out.println("all maps"); - allMaps.forEach((k, v) -> System.out.println(k + ": " + v)); - System.out.println("ready maps"); - readyMaps.forEach((k, v) -> System.out.println(k + ": " + v)); - } - public static BlockAndSeekMap getMap(String name) { return allMaps.get(name); } diff --git a/src/main/java/hdvtdev/blockAndSeek/roulette/RouletteCreator.java b/src/main/java/hdvtdev/blockAndSeek/roulette/RouletteCreator.java index fb81d50..123cda9 100644 --- a/src/main/java/hdvtdev/blockAndSeek/roulette/RouletteCreator.java +++ b/src/main/java/hdvtdev/blockAndSeek/roulette/RouletteCreator.java @@ -2,7 +2,7 @@ package hdvtdev.blockAndSeek.roulette; import hdvtdev.blockAndSeek.BlockAndSeek; import hdvtdev.blockAndSeek.BlockAndSeekMap; -import hdvtdev.blockAndSeek.EventListener; +import hdvtdev.blockAndSeek.eventListeners.EventListener; import me.libraryaddict.disguise.DisguiseAPI; import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.MiscDisguise; @@ -25,6 +25,102 @@ import java.util.List; public class RouletteCreator implements InventoryHolder { + public static void newCreateRoulette(Player player, List blocks) { + final Inventory gui = Bukkit.createInventory(null, 45); + new BukkitRunnable() { + + + int i = 0; + final RouletteGenerator rouletteGenerator = new RouletteGenerator(blocks); + + final List> rows = List.of( + new RouletteList<>(rouletteGenerator.getRandomRow(15)), + new RouletteList<>(rouletteGenerator.getRandomRow(15)), + new RouletteList<>(rouletteGenerator.getRandomRow(15)) + ); + + final List items = List.of( + new ItemStack[]{ + rows.getFirst().next(), + rows.getFirst().next(), + rows.getFirst().next(), + rows.getFirst().next(), + rows.getFirst().next() + }, + new ItemStack[]{ + rows.get(1).next(), + rows.get(1).next(), + rows.get(1).next(), + rows.get(1).next(), + rows.get(1).next() + + }, + new ItemStack[]{ + rows.get(2).next(), + rows.get(2).next(), + rows.get(2).next(), + rows.get(2).next(), + rows.get(2).next() + } + ); + + private volatile boolean finished = false; + private long startTime = System.currentTimeMillis(); + private long lastActionTime = startTime; + private long nextDelay = 0; + + private final long baseDelay = 30; + private final long maxDelay = 450; + private final double k = 0.2; + + @Override + public void run() { + if (finished) this.cancel(); + + + long now = System.currentTimeMillis(); + long elapsedSeconds = (now - startTime) / 1000; + if (elapsedSeconds >= 10) { + finished = true; + return; + } + + + nextDelay = (long) (baseDelay + (maxDelay - baseDelay) * (1 - Math.exp(-k * elapsedSeconds))); + + if (now - lastActionTime >= nextDelay) { + i++; + for (int j = 0; j < 5; j++) { + gui.setItem(3 + j * 9, items.getFirst()[j]); + gui.setItem(5 + j * 9, items.get(1)[j]); + gui.setItem(7 + j * 9, items.get(2)[j]); + } + + player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5f, 2f); + + for (int j = 4; j >= 1; j--) { + items.getFirst()[j] = items.getFirst()[j - 1]; + items.get(1)[j] = items.get(1)[j - 1]; + items.get(2)[j] = items.get(2)[j - 1]; + } + + items.getFirst()[0] = rows.getFirst().next(); + items.get(1)[0] = rows.get(1).next(); + items.get(2)[0] = rows.get(2).next(); + lastActionTime = now; + } + + i++; + + } + + + }.runTaskTimer(BlockAndSeek.getInstance(), 0, 4); + + player.openInventory(gui); + } + + @Deprecated public static void createRoulette(Player player, Inventory inventory, boolean openInventory, List blocks) { Inventory gui = inventory == null ? new RouletteCreator().getInventory() : inventory; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 8e3b571..0f88007 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,3 +1,19 @@ -# Selected language in localization.yml (en_US is used by default) -language: en_US +config: + ==: hdvtdev.blockAndSeek.Config # <-- DO NOT CHANGE THIS FIELD!!! + # A place to teleport players to after the game is over + # Example: + # default-spawn: + # - world: "your world" + # location: + # - 0 #x + # - 60 #y + # - 0 #z + default-spawn: { } + # If force-control set to true plugin will control typical aspects such as + # disabling breaking blocks, disabling damage in lobbies, etc. + # WARN: DO NOT USE THIS WITH OTHER PLUGINS THAT PROVIDE SIMILAR FUNCTIONALITY + force-control: false + + # planned + # auto-update: false \ No newline at end of file diff --git a/src/main/resources/localization.yml b/src/main/resources/localization.yml index f09b1dd..fd2b31b 100644 --- a/src/main/resources/localization.yml +++ b/src/main/resources/localization.yml @@ -11,14 +11,18 @@ en-US: failed-reload: "Failed to reload {config}. Error: {e}" seekers-won: "Seekers won!" - hiders-won: "Seekers won!" - hiders-solo-win: "{player} won this game!" + hiders-won: "Hiders won!" + hiders-solo-win: "{hider} won this game!" + hider-was-found: "{hider} was found by {seeker}" + hider-died: "{hider} somehow died xd" game-time-left: "Time left: {time}s" game-players-count: "{players} of {max-players}" + player-join: "{player} joined. {players}" + player-leave: "{player} leaved. {players}" game-title: "{title}" - wait-time-left: "Game starts in: {time}s" + wait-time-left: "Game starts in: {time}s" #items freeze-item: "Freeze" @@ -26,5 +30,9 @@ en-US: menu-item: "BlockAndSeek Menu" games-page-item: "Games" + create-game-item: "Create new game" game-name: "{name}" + game-player-count: "{players} of {max-players} players" + leave-item: "Leave game" +