From eb4a670e9c1d5525850bca05c8a9b79764bc8c6a Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Sun, 14 Jun 2026 17:49:28 +0200 Subject: [PATCH 01/10] =?UTF-8?q?fix:=20=D0=BF=D0=BE=D0=B7=D0=B8=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B3=D0=BE=D0=BB=D0=BE=D0=B3=D1=80=D0=B0=D0=BC?= =?UTF-8?q?=D0=BC=20(getBlock.Location)=20+=20=D0=B7=D0=BE=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=B2=D0=BE=D1=80=D0=BE=D1=82=20(corner1/corner2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/dev/loki/chest/ChestHologram.java | 6 +- .../java/dev/loki/command/SetupCommand.java | 1 + .../java/dev/loki/config/LocationsConfig.java | 23 +++++- src/main/java/dev/loki/gate/ExitGate.java | 82 ++++++++++++++++++- src/main/java/dev/loki/gate/GateManager.java | 14 +++- src/main/java/dev/loki/hook/HookHologram.java | 4 +- .../dev/loki/objective/GeneratorHologram.java | 4 +- .../java/dev/loki/phase/GameplayPhase.java | 3 +- 8 files changed, 124 insertions(+), 13 deletions(-) diff --git a/src/main/java/dev/loki/chest/ChestHologram.java b/src/main/java/dev/loki/chest/ChestHologram.java index d61a787..5a1c0d2 100644 --- a/src/main/java/dev/loki/chest/ChestHologram.java +++ b/src/main/java/dev/loki/chest/ChestHologram.java @@ -73,7 +73,7 @@ public class ChestHologram { continue; } - Location holoLoc = loc.clone().add(0.5, 2.0 + heightOffset, 0.5); + Location holoLoc = loc.getBlock().getLocation().add(0.5, 2.0 + heightOffset, 0.5); try { if (useTextDisplay) { TextDisplay display = loc.getWorld().spawn(holoLoc, TextDisplay.class, d -> { @@ -139,11 +139,11 @@ public class ChestHologram { if (display instanceof TextDisplay td) { td.text(TextUtil.color(text)); - Location base = chest.getLocation().clone().add(0.5, 2.0 + heightOffset, 0.5); + Location base = chest.getLocation().getBlock().getLocation().add(0.5, 2.0 + heightOffset, 0.5); td.teleport(base); } else if (display instanceof ArmorStand as) { as.setCustomName(text); - Location base = chest.getLocation().clone().add(0.5, 2.0 + heightOffset, 0.5); + Location base = chest.getLocation().getBlock().getLocation().add(0.5, 2.0 + heightOffset, 0.5); as.teleport(base); } } diff --git a/src/main/java/dev/loki/command/SetupCommand.java b/src/main/java/dev/loki/command/SetupCommand.java index 5e8d218..c9be15c 100644 --- a/src/main/java/dev/loki/command/SetupCommand.java +++ b/src/main/java/dev/loki/command/SetupCommand.java @@ -201,6 +201,7 @@ public class SetupCommand implements TabExecutor { var locations = plugin.getConfigManager().getLocations(); locations.setGate(gateId, center); + locations.setGateZone(gateId, p1, p2); plugin.getConfigManager().saveConfig("locations.yml", locations.getConfig()); player.sendMessage(messages().get("setup.gate-placed", gateId, formatLoc(center))); diff --git a/src/main/java/dev/loki/config/LocationsConfig.java b/src/main/java/dev/loki/config/LocationsConfig.java index 054d24c..463ea4a 100644 --- a/src/main/java/dev/loki/config/LocationsConfig.java +++ b/src/main/java/dev/loki/config/LocationsConfig.java @@ -225,12 +225,24 @@ public class LocationsConfig { config.set(path, list); } - /** Устанавливает ворота A или B (хранятся как gate-a / gate-b). */ + /** Устанавливает ворота A или B с зоной (хранятся как gate-a / gate-b + corner1/corner2). */ public void setGate(String id, Location loc) { String key = "gate-" + id.toLowerCase(); config.set(key, locationToString(loc)); } + public void setGateZone(String id, Location corner1, Location corner2) { + String prefix = "gate-" + id.toLowerCase(); + config.set(prefix + "-corner1", locationToString(corner1)); + config.set(prefix + "-corner2", locationToString(corner2)); + } + + public Location getGateCorner(String id, int num) { + String key = "gate-" + id.toLowerCase() + "-corner" + num; + String str = config.getString(key); + return str != null ? parseLocation(str) : null; + } + public Location getGate(String id) { String key = "gate-" + id.toLowerCase(); String str = config.getString(key); @@ -251,6 +263,15 @@ public class LocationsConfig { return gates; } + /** Get all gate IDs that exist in config. */ + public List getGateIds() { + List ids = new ArrayList<>(); + for (String id : List.of("a", "b")) { + if (getGate(id) != null) ids.add(id); + } + return ids; + } + private String locationToString(Location loc) { // Use | as separator instead of , to avoid issues with negative coordinates in YAML return String.format(Locale.US, "%s|%.2f|%.2f|%.2f|%.1f|%.1f", diff --git a/src/main/java/dev/loki/gate/ExitGate.java b/src/main/java/dev/loki/gate/ExitGate.java index 14f143c..7d7989b 100644 --- a/src/main/java/dev/loki/gate/ExitGate.java +++ b/src/main/java/dev/loki/gate/ExitGate.java @@ -11,6 +11,10 @@ public class ExitGate { private double savedProgress; // сохраняется при уходе игрока private boolean powered; + private int zoneMinX, zoneMinY, zoneMinZ; + private int zoneMaxX, zoneMaxY, zoneMaxZ; + private boolean hasZone; + public enum GateState { CLOSED, OPENING, @@ -23,6 +27,22 @@ public class ExitGate { this.progress = 0.0; this.savedProgress = 0.0; this.powered = false; + this.hasZone = false; + } + + /** Set the gate zone from two corner locations. */ + public void setZone(Location corner1, Location corner2) { + zoneMinX = Math.min(corner1.getBlockX(), corner2.getBlockX()); + zoneMinY = Math.min(corner1.getBlockY(), corner2.getBlockY()); + zoneMinZ = Math.min(corner1.getBlockZ(), corner2.getBlockZ()); + zoneMaxX = Math.max(corner1.getBlockX(), corner2.getBlockX()); + zoneMaxY = Math.max(corner1.getBlockY(), corner2.getBlockY()); + zoneMaxZ = Math.max(corner1.getBlockZ(), corner2.getBlockZ()); + hasZone = true; + } + + private boolean hasZone() { + return hasZone; } public Location getLocation() { @@ -35,12 +55,71 @@ public class ExitGate { location.getBlock().setType(org.bukkit.Material.HOPPER, false); } + /** Build the gate structure fills the entire designated zone. */ + public void spawnGateStructure() { + World world = location.getWorld(); + if (world == null) return; + + if (hasZone) { + for (int x = zoneMinX; x <= zoneMaxX; x++) { + for (int y = zoneMinY; y <= zoneMaxY; y++) { + for (int z = zoneMinZ; z <= zoneMaxZ; z++) { + world.getBlockAt(x, y, z).setType(org.bukkit.Material.IRON_BARS, false); + } + } + } + } else { + // Fallback: 3x3x3 zone around gate location + int cx = location.getBlockX(), cy = location.getBlockY(), cz = location.getBlockZ(); + for (int x = cx - 1; x <= cx + 1; x++) { + for (int y = cy; y <= cy + 2; y++) { + for (int z = cz - 1; z <= cz + 1; z++) { + world.getBlockAt(x, y, z).setType(org.bukkit.Material.IRON_BARS, false); + } + } + } + } + + // Button at gate center + (1, 1, 1) + world.getBlockAt(location.clone().add(1, 1, 1)).setType(org.bukkit.Material.STONE_BUTTON, false); + } + /** Remove the interaction block (e.g. when gate opens or on cleanup). */ public void removeGateBlock() { if (location.getWorld() == null) return; location.getBlock().setType(org.bukkit.Material.AIR, false); } + /** Remove the entire gate zone + interaction block. */ + public void removeGateStructure() { + World world = location.getWorld(); + if (world == null) return; + + if (hasZone) { + for (int x = zoneMinX; x <= zoneMaxX; x++) { + for (int y = zoneMinY; y <= zoneMaxY; y++) { + for (int z = zoneMinZ; z <= zoneMaxZ; z++) { + world.getBlockAt(x, y, z).setType(org.bukkit.Material.AIR, false); + } + } + } + } else { + int cx = location.getBlockX(), cy = location.getBlockY(), cz = location.getBlockZ(); + for (int x = cx - 1; x <= cx + 1; x++) { + for (int y = cy; y <= cy + 2; y++) { + for (int z = cz - 1; z <= cz + 1; z++) { + world.getBlockAt(x, y, z).setType(org.bukkit.Material.AIR, false); + } + } + } + } + + // Remove button at (1, 1, 1) + world.getBlockAt(location.clone().add(1, 1, 1)).setType(org.bukkit.Material.AIR, false); + + removeGateBlock(); + } + public GateState getState() { return state; } @@ -102,7 +181,8 @@ public class ExitGate { if (progress >= 1.0) { progress = 1.0; state = GateState.OPEN; - removeGateBlock(); + removeGateStructure(); + spawnOpenParticles(); playOpenedSound(); } } diff --git a/src/main/java/dev/loki/gate/GateManager.java b/src/main/java/dev/loki/gate/GateManager.java index 074604e..bf28d40 100644 --- a/src/main/java/dev/loki/gate/GateManager.java +++ b/src/main/java/dev/loki/gate/GateManager.java @@ -19,9 +19,17 @@ public class GateManager { } private void loadGates(LocationsConfig locations) { - List gateLocations = locations.getExitGates(); - for (int i = 0; i < Math.min(gateLocations.size(), GATE_COUNT); i++) { - gates.add(new ExitGate(gateLocations.get(i))); + for (String id : locations.getGateIds()) { + Location center = locations.getGate(id); + if (center == null) continue; + ExitGate gate = new ExitGate(center); + Location c1 = locations.getGateCorner(id, 1); + Location c2 = locations.getGateCorner(id, 2); + if (c1 != null && c2 != null) { + gate.setZone(c1, c2); + } + gates.add(gate); + if (gates.size() >= GATE_COUNT) break; } } diff --git a/src/main/java/dev/loki/hook/HookHologram.java b/src/main/java/dev/loki/hook/HookHologram.java index 9691a17..7bb2879 100644 --- a/src/main/java/dev/loki/hook/HookHologram.java +++ b/src/main/java/dev/loki/hook/HookHologram.java @@ -72,7 +72,7 @@ public class HookHologram { continue; } - Location holoLoc = loc.clone().add(0.5, 2.0 + heightOffset, 0.5); + Location holoLoc = loc.getBlock().getLocation().add(0.5, 2.0 + heightOffset, 0.5); try { if (useTextDisplay) { TextDisplay display = loc.getWorld().spawn(holoLoc, TextDisplay.class, d -> { @@ -128,7 +128,7 @@ public class HookHologram { String text = "§c⚓ Крюк §f#" + visibleIndex + "/" + total + "\n§7" + status; double heightOffset = plugin.getConfigManager().getGame().getHookHologramHeightOffset(); - Location base = hook.getLocation().clone().add(0.5, 2.0 + heightOffset, 0.5); + Location base = hook.getLocation().getBlock().getLocation().add(0.5, 2.0 + heightOffset, 0.5); if (display instanceof TextDisplay td) { td.text(TextUtil.color(text)); diff --git a/src/main/java/dev/loki/objective/GeneratorHologram.java b/src/main/java/dev/loki/objective/GeneratorHologram.java index 1ea0a91..b0c56ae 100644 --- a/src/main/java/dev/loki/objective/GeneratorHologram.java +++ b/src/main/java/dev/loki/objective/GeneratorHologram.java @@ -67,7 +67,7 @@ public class GeneratorHologram { Location loc = gen.getLocation(); if (loc.getWorld() == null) continue; - Location holoLoc = loc.clone().add(0.5, 2.0 + heightOffset, 0.5); + Location holoLoc = loc.getBlock().getLocation().add(0.5, 2.0 + heightOffset, 0.5); try { if (useTextDisplay) { TextDisplay display = loc.getWorld().spawn(holoLoc, TextDisplay.class, d -> { @@ -118,7 +118,7 @@ public class GeneratorHologram { text = "§6⚙ Генератор §f#" + (gen.getId() + 1) + "/" + total + "\n§e" + bar + " §f" + pct + "%"; } - Location base = gen.getLocation().clone().add(0.5, 2.0 + heightOffset, 0.5); + Location base = gen.getLocation().getBlock().getLocation().add(0.5, 2.0 + heightOffset, 0.5); if (display instanceof TextDisplay td) { td.text(TextUtil.color(text)); diff --git a/src/main/java/dev/loki/phase/GameplayPhase.java b/src/main/java/dev/loki/phase/GameplayPhase.java index f46f335..c185496 100644 --- a/src/main/java/dev/loki/phase/GameplayPhase.java +++ b/src/main/java/dev/loki/phase/GameplayPhase.java @@ -321,8 +321,9 @@ public class GameplayPhase implements Phase { } plugin.getLogger().info("[GameplayPhase] Spawned blocks for " + hookManager.getAllHooks().size() + " hooks"); - // Спавн блоков на местах ворот (Hopper — для открытия через ПКМ) + // Спавн структуры ворот (рамка + кнопка + Hopper для взаимодействия) for (ExitGate gate : gateManager.getAllGates()) { + gate.spawnGateStructure(); gate.spawnGateBlock(); } plugin.getLogger().info("[GameplayPhase] Spawned blocks for " + gateManager.getAllGates().size() + " gates"); From b666f1b0fa5b6b8eb62c389ba92cf08a3c95434e Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Sun, 14 Jun 2026 19:18:30 +0200 Subject: [PATCH 02/10] =?UTF-8?q?feat:=20/dbdadmin=20repairgens=20?= =?UTF-8?q?=E2=80=94=20=D0=BC=D0=B3=D0=BD=D0=BE=D0=B2=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D0=BE=20=D1=87=D0=B8=D0=BD=D0=B8=D1=82=20=D0=B2=D1=81=D0=B5=20?= =?UTF-8?q?=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=82=D0=BE=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dev/loki/command/DBDAdminCommand.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/java/dev/loki/command/DBDAdminCommand.java b/src/main/java/dev/loki/command/DBDAdminCommand.java index 516f0c4..194cd61 100644 --- a/src/main/java/dev/loki/command/DBDAdminCommand.java +++ b/src/main/java/dev/loki/command/DBDAdminCommand.java @@ -43,6 +43,7 @@ public class DBDAdminCommand implements TabExecutor { return switch (args[0].toLowerCase()) { case "list" -> handleList(player, args); case "world" -> handleWorld(player, args); + case "repairgens" -> handleRepairGens(player); default -> { sendUsage(sender); yield true; @@ -124,12 +125,41 @@ public class DBDAdminCommand implements TabExecutor { return true; } + private boolean handleRepairGens(Player player) { + var gameManager = plugin.getGameManager(); + var session = gameManager.getCurrentSession(); + if (session == null) { + player.sendMessage("§cНет активной игры."); + return true; + } + + var genManager = session.getGeneratorManager(); + if (genManager == null) { + player.sendMessage("§cGeneratorManager не найден."); + return true; + } + + int count = 0; + for (var gen : genManager.getIncompleteGenerators()) { + gen.setProgress(100.0); + genManager.onGeneratorCompleted(gen); + count++; + } + + player.sendMessage("§aПочинено генераторов: §e" + count); + if (count > 0 && genManager.areAllRequiredCompleted()) { + player.sendMessage("§a✔ Все необходимые генераторы починены — ворота открываются!"); + } + return true; + } + private void sendUsage(CommandSender sender) { var messages = plugin.getConfigManager().getMessages(); sender.sendMessage(messages.get("usage.admin-list-header")); sender.sendMessage(messages.get("usage.admin-list-list")); sender.sendMessage(messages.get("usage.admin-list-type")); sender.sendMessage(messages.get("usage.admin-world")); + sender.sendMessage("§7/dbdadmin repairgens §8— §fПочинить все генераторы"); } @Override @@ -138,7 +168,7 @@ public class DBDAdminCommand implements TabExecutor { if (!sender.hasPermission("mdbd.admin")) return List.of(); if (args.length == 1) { - return Arrays.asList("list", "world").stream() + return Arrays.asList("list", "world", "repairgens").stream() .filter(s -> s.startsWith(args[0].toLowerCase())) .toList(); } From d2b174b94c77d8b122523cbffc2e2f6a427b2d62 Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Mon, 15 Jun 2026 10:22:02 +0200 Subject: [PATCH 03/10] =?UTF-8?q?fix:=2010=20bug=20fixes=20=E2=80=94=20hea?= =?UTF-8?q?ling=20dead=20players,=20kick=20bypass,=20gate=20race,=20swimmi?= =?UTF-8?q?ng=20ghost,=20regression=20config,=20dead=20code=20cleanup,=20g?= =?UTF-8?q?ate=20zone=20detection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/dev/loki/chest/Chest.java | 19 ++ .../java/dev/loki/chest/ChestHologram.java | 10 +- .../java/dev/loki/chest/ChestManager.java | 35 +-- .../java/dev/loki/chest/ChestOpening.java | 14 +- .../java/dev/loki/command/SetupCommand.java | 157 ++++++++++- src/main/java/dev/loki/config/GameConfig.java | 6 + .../java/dev/loki/config/LocationsConfig.java | 15 ++ src/main/java/dev/loki/core/GameSession.java | 3 +- src/main/java/dev/loki/gate/ExitGate.java | 22 +- src/main/java/dev/loki/gate/GateManager.java | 6 + src/main/java/dev/loki/gate/GateOpening.java | 22 +- src/main/java/dev/loki/hook/Hook.java | 2 + src/main/java/dev/loki/hook/HookManager.java | 5 +- src/main/java/dev/loki/item/ItemMedkit.java | 6 +- src/main/java/dev/loki/item/ItemType.java | 4 +- .../java/dev/loki/killer/GeneratorKick.java | 10 +- .../loki/listener/PlayerInteractListener.java | 38 +-- .../dev/loki/objective/GeneratorManager.java | 11 +- .../loki/objective/GeneratorRegression.java | 52 ---- .../dev/loki/objective/GeneratorRepair.java | 16 +- .../java/dev/loki/objective/SkillCheck.java | 142 ---------- .../loki/objective/SkillCheckInventory.java | 245 ------------------ .../java/dev/loki/objective/SkillCheckUI.java | 120 --------- .../java/dev/loki/phase/EndgamePhase.java | 14 +- .../dev/loki/phase/GameplayDamageSystem.java | 40 ++- .../dev/loki/phase/GameplayHookHandler.java | 52 +++- .../dev/loki/phase/GameplayInteraction.java | 37 +-- .../java/dev/loki/phase/GameplayPhase.java | 144 +++++++--- .../dev/loki/survivor/SurvivorHealing.java | 8 +- .../dev/loki/survivor/SurvivorMovement.java | 2 +- src/main/java/dev/loki/ui/ActionBar.java | 33 +-- src/main/java/dev/loki/ui/Sidebar.java | 18 +- src/main/java/dev/loki/ui/TitleUI.java | 20 +- src/main/resources/game.yml | 9 + src/main/resources/messages.yml | 23 +- 35 files changed, 587 insertions(+), 773 deletions(-) delete mode 100644 src/main/java/dev/loki/objective/GeneratorRegression.java delete mode 100644 src/main/java/dev/loki/objective/SkillCheck.java delete mode 100644 src/main/java/dev/loki/objective/SkillCheckInventory.java delete mode 100644 src/main/java/dev/loki/objective/SkillCheckUI.java diff --git a/src/main/java/dev/loki/chest/Chest.java b/src/main/java/dev/loki/chest/Chest.java index 9e15fad..69de308 100644 --- a/src/main/java/dev/loki/chest/Chest.java +++ b/src/main/java/dev/loki/chest/Chest.java @@ -15,6 +15,9 @@ public class Chest { private boolean opened; private boolean empty; private ItemStack loot; + private long lastEmptiedTime; + + private static final long COOLDOWN_MILLIS = 3 * 60 * 1000; // 3 minutes public Chest(Location location) { this.id = UUID.randomUUID(); @@ -22,6 +25,7 @@ public class Chest { this.opened = false; this.empty = false; this.loot = null; + this.lastEmptiedTime = 0; } public UUID getId() { @@ -52,6 +56,21 @@ public class Chest { return !opened && !empty && hasLoot(); } + public void onLooted() { + this.empty = true; + this.lastEmptiedTime = System.currentTimeMillis(); + } + + public long getSecondsUntilReset() { + long elapsed = (System.currentTimeMillis() - lastEmptiedTime) / 1000; + long remaining = (COOLDOWN_MILLIS / 1000) - elapsed; + return Math.max(0, remaining); + } + + public boolean isOnCooldown() { + return getSecondsUntilReset() > 0; + } + public ItemStack getLoot() { return loot; } diff --git a/src/main/java/dev/loki/chest/ChestHologram.java b/src/main/java/dev/loki/chest/ChestHologram.java index 5a1c0d2..a0975ba 100644 --- a/src/main/java/dev/loki/chest/ChestHologram.java +++ b/src/main/java/dev/loki/chest/ChestHologram.java @@ -118,14 +118,8 @@ public class ChestHologram { String status; if (chest.isEmpty()) { - long secs = manager.getSecondsUntilNextReset(); - if (secs > 60) { - status = "§7Пуст §8(" + (secs / 60) + "м)"; - } else if (secs > 0) { - status = "§7Пуст §8(" + secs + "с)"; - } else { - status = "§7Пуст"; - } + long secs = chest.getSecondsUntilReset(); + status = secs > 0 ? "§7Пусто §8(" + secs + "с)" : "§7Пусто"; } else if (chest.isOpened()) { status = "§6Открывается..."; } else if (chest.hasLoot()) { diff --git a/src/main/java/dev/loki/chest/ChestManager.java b/src/main/java/dev/loki/chest/ChestManager.java index f38b4e7..ec8866d 100644 --- a/src/main/java/dev/loki/chest/ChestManager.java +++ b/src/main/java/dev/loki/chest/ChestManager.java @@ -21,7 +21,6 @@ public class ChestManager { private final GameConfig gameConfig; private ChestLoot chestLoot; private BukkitTask lootResetTask; - private long lastResetTime = System.currentTimeMillis(); public ChestManager(JavaPlugin plugin, LocationsConfig locationsConfig, GameConfig gameConfig) { this.plugin = plugin; @@ -36,7 +35,6 @@ public class ChestManager { List locations = locationsConfig.getChests(); for (Location loc : locations) { Chest chest = new Chest(loc); - // Populate loot immediately so it's available chest.setLoot(chestLoot.rollLoot()); chests.put(chest.getId(), chest); } @@ -44,14 +42,12 @@ public class ChestManager { } /** - * Start periodic loot reset timer. - * Every N minutes (from config), all empty chests get new loot. + * Start per-chest cooldown timer. Each chest refills individually 3 min after being looted. */ public void startLootResetTimer() { if (lootResetTask != null) lootResetTask.cancel(); - long intervalTicks = (long) (gameConfig.getChestLootResetMinutes() * 60 * 20); - lootResetTask = plugin.getServer().getScheduler().runTaskTimer(plugin, this::resetLoot, intervalTicks, intervalTicks); - plugin.getLogger().info("Chest loot reset timer started (every " + gameConfig.getChestLootResetMinutes() + " min)"); + lootResetTask = plugin.getServer().getScheduler().runTaskTimer(plugin, this::tickCooldowns, 20L, 20L); + plugin.getLogger().info("Per-chest cooldown timer started (3 min per chest)"); } public void stopLootResetTimer() { @@ -62,20 +58,16 @@ public class ChestManager { } /** - * Reset loot: refill ALL chests with new random loot. + * Every second, check each chest — if its cooldown expired, refill it. */ - private void resetLoot() { - int refilled = 0; + private void tickCooldowns() { for (Chest chest : chests.values()) { - // Skip chests currently being opened to avoid race condition if (chest.isOpened()) continue; - chest.setLoot(chestLoot.rollLoot()); - chest.setOpened(false); - chest.setEmpty(false); - refilled++; + if (chest.isEmpty() && !chest.isOnCooldown()) { + chest.setLoot(chestLoot.rollLoot()); + chest.setEmpty(false); + } } - this.lastResetTime = System.currentTimeMillis(); - plugin.getLogger().info("[Chest] Loot reset — " + refilled + " chests refilled"); } public Chest getChest(UUID id) { @@ -117,7 +109,6 @@ public class ChestManager { chest.setEmpty(false); chest.setLoot(chestLoot.rollLoot()); } - this.lastResetTime = System.currentTimeMillis(); plugin.getLogger().info("Reset all chests"); } @@ -140,13 +131,7 @@ public class ChestManager { return (int) chests.values().stream().filter(Chest::isAvailable).count(); } - /** Seconds until the next automatic loot reset. */ - public long getSecondsUntilNextReset() { - long elapsed = (System.currentTimeMillis() - lastResetTime) / 1000; - long total = (long) (gameConfig.getChestLootResetMinutes() * 60); - long remaining = total - elapsed; - return Math.max(0, remaining); - } + public ChestLoot getChestLoot() { return chestLoot; diff --git a/src/main/java/dev/loki/chest/ChestOpening.java b/src/main/java/dev/loki/chest/ChestOpening.java index 32a4122..1618e92 100644 --- a/src/main/java/dev/loki/chest/ChestOpening.java +++ b/src/main/java/dev/loki/chest/ChestOpening.java @@ -47,15 +47,9 @@ public class ChestOpening { return false; } - // Ensure chest has loot; roll if missing - if (!chest.hasLoot()) { - ItemStack rolled = chestLoot.rollLoot(); - if (rolled == null) { - player.sendMessage(messages().get("chest.empty")); - return false; - } - chest.setLoot(rolled); - chest.setEmpty(false); + if (!chest.hasLoot() || chest.isEmpty()) { + player.sendMessage(messages().get("chest.empty")); + return false; } if (!chest.isAvailable()) { @@ -152,7 +146,7 @@ public class ChestOpening { } } chest.setOpened(false); - chest.setEmpty(true); + chest.onLooted(); chest.setLoot(null); // Clear loot after giving chest.closeVisual(); diff --git a/src/main/java/dev/loki/command/SetupCommand.java b/src/main/java/dev/loki/command/SetupCommand.java index c9be15c..92c09dc 100644 --- a/src/main/java/dev/loki/command/SetupCommand.java +++ b/src/main/java/dev/loki/command/SetupCommand.java @@ -3,6 +3,7 @@ package dev.loki.command; import dev.loki.mdbd; import dev.loki.util.SpawnUtil; import dev.loki.util.TextUtil; +import dev.loki.config.LocationsConfig; import dev.loki.config.MessagesConfig; import org.bukkit.Location; import org.bukkit.Material; @@ -70,7 +71,8 @@ public class SetupCommand implements TabExecutor { return switch (args[0].toLowerCase()) { case "wand" -> giveWand(player); case "set" -> handleSet(player, args); - case "clear" -> clearMap(player); + case "clear" -> handleClear(player, args); + case "delete" -> handleDelete(player, args); case "clear-spawns" -> clearSpawns(player); case "lobby" -> setLobby(player); default -> { sendUsage(sender); yield true; } @@ -331,6 +333,147 @@ public class SetupCommand implements TabExecutor { return true; } + // ── Clear ──────────────────────────────────────────────────────── + + private boolean handleClear(Player player, String[] args) { + var locations = plugin.getConfigManager().getLocations(); + + if (args.length >= 2) { + String type = args[1].toLowerCase(); + return clearObjectsByType(player, locations, type); + } + + // Clear ALL object data from config (no block destruction) + locations.clearLocationList("generators"); + locations.clearLocationList("hooks"); + locations.clearLocationList("chests"); + locations.clearLocationList("killer-spawn"); + for (String id : List.of("a", "b")) { + locations.getConfig().set("gate-" + id, null); + locations.getConfig().set("gate-" + id + "-corner1", null); + locations.getConfig().set("gate-" + id + "-corner2", null); + } + locations.clearSurvivorSpawns(); + plugin.getGeneratorData().clearGenerators(); + plugin.getConfigManager().saveConfig("locations.yml", locations.getConfig()); + player.sendMessage(messages().get("setup.cleared")); + return true; + } + + private boolean clearObjectsByType(Player player, LocationsConfig locations, String type) { + String path = switch (type) { + case "generator" -> "generators"; + case "hook" -> "hooks"; + case "chest" -> "chests"; + case "gate" -> null; + case "killer-spawn" -> "killer-spawn"; + case "survivor-spawn" -> null; + default -> { player.sendMessage(messages().get("setup.unknown-type", type)); yield null; } + }; + if (path == null) { + if (type.equals("gate")) { + for (String id : List.of("a", "b")) { + locations.getConfig().set("gate-" + id, null); + locations.getConfig().set("gate-" + id + "-corner1", null); + locations.getConfig().set("gate-" + id + "-corner2", null); + } + } else if (type.equals("survivor-spawn")) { + locations.clearSurvivorSpawns(); + } else { + return true; + } + } else { + locations.clearLocationList(path); + if (type.equals("generator")) { + plugin.getGeneratorData().clearGenerators(); + } + } + plugin.getConfigManager().saveConfig("locations.yml", locations.getConfig()); + player.sendMessage(messages().get("setup.cleared-type", type)); + return true; + } + + // ── Delete ─────────────────────────────────────────────────────── + + private boolean handleDelete(Player player, String[] args) { + if (args.length < 3) { + player.sendMessage(messages().get("setup.delete-usage")); + return true; + } + + String type = args[1].toLowerCase(); + int index; + try { + index = Integer.parseInt(args[2]); + } catch (NumberFormatException e) { + player.sendMessage(messages().get("setup.invalid-number", args[2])); + return true; + } + + var locations = plugin.getConfigManager().getLocations(); + + switch (type) { + case "generator" -> { + var gens = locations.getGenerators(); + if (index < 0 || index >= gens.size()) { + player.sendMessage(messages().get("setup.out-of-range", index)); + return true; + } + locations.removeLocationAtIndex("generators", index); + plugin.getGeneratorData().removeGenerator(index); + player.sendMessage(messages().get("setup.deleted", "generator #" + index)); + } + case "hook" -> { + var hooks = locations.getHooks(); + if (index < 0 || index >= hooks.size()) { + player.sendMessage(messages().get("setup.out-of-range", index)); + return true; + } + locations.removeLocationAtIndex("hooks", index); + player.sendMessage(messages().get("setup.deleted", "hook #" + index)); + } + case "chest" -> { + var chests = locations.getChests(); + if (index < 0 || index >= chests.size()) { + player.sendMessage(messages().get("setup.out-of-range", index)); + return true; + } + locations.removeLocationAtIndex("chests", index); + player.sendMessage(messages().get("setup.deleted", "chest #" + index)); + } + case "killer-spawn" -> { + locations.clearLocationList("killer-spawn"); + player.sendMessage(messages().get("setup.deleted", "killer-spawn")); + } + case "survivor-spawn" -> { + if (index < 1 || index > 4) { + player.sendMessage(messages().get("setup.out-of-range", index)); + return true; + } + locations.clearSurvivorSpawn(index); + player.sendMessage(messages().get("setup.deleted", "survivor-spawn #" + index)); + } + case "gate" -> { + String id = index == 1 ? "a" : index == 2 ? "b" : null; + if (id == null) { + player.sendMessage(messages().get("setup.out-of-range", index)); + return true; + } + locations.getConfig().set("gate-" + id, null); + locations.getConfig().set("gate-" + id + "-corner1", null); + locations.getConfig().set("gate-" + id + "-corner2", null); + player.sendMessage(messages().get("setup.deleted", "gate-" + id)); + } + default -> { + player.sendMessage(messages().get("setup.unknown-type", type)); + return true; + } + } + + plugin.getConfigManager().saveConfig("locations.yml", locations.getConfig()); + return true; + } + private boolean clearSpawns(Player player) { var locations = plugin.getConfigManager().getLocations(); locations.clearLocationList("killer-spawn"); @@ -359,6 +502,8 @@ public class SetupCommand implements TabExecutor { sender.sendMessage(messages().get("usage.setup-killer-spawn")); sender.sendMessage(messages().get("usage.setup-survivor-spawn")); sender.sendMessage(messages().get("usage.setup-gate")); + sender.sendMessage(messages().get("usage.setup-clear")); + sender.sendMessage(messages().get("usage.setup-delete")); sender.sendMessage(messages().get("usage.setup-clear-spawns")); sender.sendMessage(messages().get("usage.setup-lobby")); } @@ -373,12 +518,14 @@ public class SetupCommand implements TabExecutor { @NotNull String label, @NotNull String[] args) { if (!sender.hasPermission("mdbd.admin")) return List.of(); if (args.length == 1) { - return List.of("wand", "set", "clear", "clear-spawns", "lobby").stream() + return List.of("wand", "set", "clear", "delete", "clear-spawns", "lobby").stream() .filter(s -> s.startsWith(args[0].toLowerCase())).toList(); } - if (args.length == 2 && args[0].equalsIgnoreCase("set")) { - return List.of("hook", "chest", "generator", "killer-spawn", "survivor-spawn", "gate").stream() - .filter(s -> s.startsWith(args[1].toLowerCase())).toList(); + if (args.length == 2) { + if (args[0].equalsIgnoreCase("set") || args[0].equalsIgnoreCase("clear") || args[0].equalsIgnoreCase("delete")) { + return List.of("generator", "hook", "chest", "killer-spawn", "survivor-spawn", "gate").stream() + .filter(s -> s.startsWith(args[1].toLowerCase())).toList(); + } } return List.of(); } diff --git a/src/main/java/dev/loki/config/GameConfig.java b/src/main/java/dev/loki/config/GameConfig.java index 9187ba4..3fa6634 100644 --- a/src/main/java/dev/loki/config/GameConfig.java +++ b/src/main/java/dev/loki/config/GameConfig.java @@ -84,8 +84,11 @@ public class GameConfig { // Endgame setDefault("endgame.gate-open-seconds", 20); + setDefault("endgame.pregame-seconds", 30); + setDefault("endgame.postgame-seconds", 60); setDefault("endgame.chest-open-seconds", 3); setDefault("endgame.gate-interaction-range", 3.0); + setDefault("endgame.escape-range", 2.0); // Killer notification setDefault("killer-notification.compass-duration-seconds", 5); @@ -263,8 +266,11 @@ public class GameConfig { // Endgame // ------------------------------------------------------------------------- public int getGateOpenSeconds() { return config.getInt("endgame.gate-open-seconds", 20); } + public int getPregameSeconds() { return config.getInt("endgame.pregame-seconds", 30); } + public int getPostgameSeconds() { return config.getInt("endgame.postgame-seconds", 60); } public int getChestOpenSeconds() { return config.getInt("endgame.chest-open-seconds", 3); } public double getGateInteractionRange() { return config.getDouble("endgame.gate-interaction-range", 3.0); } + public double getEscapeRange() { return config.getDouble("endgame.escape-range", 2.0); } // ------------------------------------------------------------------------- // Killer notification diff --git a/src/main/java/dev/loki/config/LocationsConfig.java b/src/main/java/dev/loki/config/LocationsConfig.java index 463ea4a..6cc3176 100644 --- a/src/main/java/dev/loki/config/LocationsConfig.java +++ b/src/main/java/dev/loki/config/LocationsConfig.java @@ -130,6 +130,12 @@ public class LocationsConfig { return -1; } + /** Clear a specific survivor spawn slot (index 1-4). */ + public void clearSurvivorSpawn(int index) { + if (index < 1 || index > 4) throw new IllegalArgumentException("Index must be 1-4"); + config.set("survivor-spawn-" + index, null); + } + /** Clear all survivor spawn slots. */ public void clearSurvivorSpawns() { for (int i = 1; i <= 4; i++) { @@ -219,6 +225,15 @@ public class LocationsConfig { public void clearLocationList(String path) { config.set(path, new ArrayList<>()); } + /** Remove a location at a specific index from a list. */ + public void removeLocationAtIndex(String path, int index) { + List list = safeGetStringList(path); + if (index >= 0 && index < list.size()) { + list.remove(index); + config.set(path, list); + } + } + public void setSingleLocation(String path, Location loc) { List list = new ArrayList<>(); list.add(locationToString(loc)); diff --git a/src/main/java/dev/loki/core/GameSession.java b/src/main/java/dev/loki/core/GameSession.java index 4a2b524..dfaed5c 100644 --- a/src/main/java/dev/loki/core/GameSession.java +++ b/src/main/java/dev/loki/core/GameSession.java @@ -42,7 +42,8 @@ public class GameSession { this.ticksElapsed = 0; this.roleAssigner = new RoleAssigner(plugin.getConfigManager().getLocations()); this.generatorManager = new GeneratorManager( - plugin.getGeneratorData(), plugin.getConfigManager().getGame().getGeneratorRequired()); + plugin.getGeneratorData(), plugin.getConfigManager().getGame().getGeneratorRequired(), + plugin.getConfigManager().getGame()); } public void start() { diff --git a/src/main/java/dev/loki/gate/ExitGate.java b/src/main/java/dev/loki/gate/ExitGate.java index 7d7989b..9df9e1e 100644 --- a/src/main/java/dev/loki/gate/ExitGate.java +++ b/src/main/java/dev/loki/gate/ExitGate.java @@ -150,9 +150,7 @@ public class ExitGate { public void setPowered(boolean powered) { this.powered = powered; - if (powered && state == GateState.CLOSED) { - state = GateState.OPENING; - } + // НЕ меняем статус на OPENING — ворота открываются только через взаимодействие игрока } public void startOpening() { @@ -174,6 +172,16 @@ public class ExitGate { } } + /** Принудительно открыть ворота (вызывается после таймера эндгейма). */ + public void forceOpen() { + this.state = GateState.OPEN; + this.progress = 1.0; + this.savedProgress = 1.0; + removeGateStructure(); + spawnOpenParticles(); + playOpenedSound(); + } + /** Прямая установка прогресса (для линейного расчёта в GateOpening). */ public void setProgressDirect(double value) { if (state != GateState.OPENING) return; @@ -204,6 +212,14 @@ public class ExitGate { } public boolean isInRange(Location playerLoc, double radius) { + if (hasZone) { + int px = playerLoc.getBlockX(), py = playerLoc.getBlockY(), pz = playerLoc.getBlockZ(); + int closestX = Math.max(zoneMinX, Math.min(px, zoneMaxX)); + int closestY = Math.max(zoneMinY, Math.min(py, zoneMaxY)); + int closestZ = Math.max(zoneMinZ, Math.min(pz, zoneMaxZ)); + double dx = px - closestX, dy = py - closestY, dz = pz - closestZ; + return Math.sqrt(dx * dx + dy * dy + dz * dz) <= radius; + } return location.distance(playerLoc) <= radius; } diff --git a/src/main/java/dev/loki/gate/GateManager.java b/src/main/java/dev/loki/gate/GateManager.java index bf28d40..69f3671 100644 --- a/src/main/java/dev/loki/gate/GateManager.java +++ b/src/main/java/dev/loki/gate/GateManager.java @@ -110,6 +110,12 @@ public class GateManager { return (int) gates.stream().filter(ExitGate::isOpen).count(); } + public void openAllGates() { + for (ExitGate gate : gates) { + gate.forceOpen(); + } + } + public void resetAll() { endgameActive = false; for (ExitGate gate : gates) { diff --git a/src/main/java/dev/loki/gate/GateOpening.java b/src/main/java/dev/loki/gate/GateOpening.java index 5e2da93..673969d 100644 --- a/src/main/java/dev/loki/gate/GateOpening.java +++ b/src/main/java/dev/loki/gate/GateOpening.java @@ -38,17 +38,22 @@ public class GateOpening { ExitGate gate = gateManager.getGateAt(player.getLocation(), INTERACTION_RADIUS); if (gate == null) { - player.sendMessage(messages.get("chest.door-nearby")); + player.sendMessage(messages.get("gate.door-nearby")); return false; } if (!gate.isPowered()) { - player.sendMessage(messages.get("chest.door-no-power")); + player.sendMessage(messages.get("gate.door-no-power")); return false; } - if (!gate.isClosed() && !gate.isOpening()) { - player.sendMessage(messages.get("chest.door-already")); + if (gate.isOpening()) { + player.sendMessage(messages.get("gate.door-already")); + return false; + } + + if (gate.isOpen()) { + player.sendMessage(messages.get("gate.door-already")); return false; } @@ -61,7 +66,7 @@ public class GateOpening { if (progress != null) { Player player = survivor.getPlayer(); if (player != null) { - player.sendMessage(messages.get("chest.door-interrupted")); + player.sendMessage(messages.get("gate.door-interrupted")); } } } @@ -74,11 +79,14 @@ public class GateOpening { Player player = survivor.getPlayer(); if (player == null) return; + // Перевести ворота в режим открытия + gate.startOpening(); + // Восстановить сохранённый прогресс gate.restoreProgress(); openingPlayers.put(survivor.getUuid(), new OpeningProgress(gate, 0)); - player.sendMessage(messages.get("chest.door-open")); + player.sendMessage(messages.get("gate.door-open")); new OpeningTask(survivor, gate, plugin).runTaskTimer(plugin, 0L, 1L); } @@ -89,7 +97,7 @@ public class GateOpening { World world = loc.getWorld(); if (player != null) { - player.sendMessage(messages.get("chest.door-opened")); + player.sendMessage(messages.get("gate.door-opened")); if (world != null) { world.playSound(loc, Sound.BLOCK_IRON_DOOR_OPEN, 1.0f, 1.0f); // Big particle burst when opened diff --git a/src/main/java/dev/loki/hook/Hook.java b/src/main/java/dev/loki/hook/Hook.java index 7c60d85..d3f40a0 100644 --- a/src/main/java/dev/loki/hook/Hook.java +++ b/src/main/java/dev/loki/hook/Hook.java @@ -76,4 +76,6 @@ public class Hook { public boolean isBasement() { return basement; } public boolean isDisabled() { return disabled; } public void setDisabled(boolean disabled) { this.disabled = disabled; } + public int getStageProgress() { return stageProgress; } + public void addStageProgress(int delta) { stageProgress = Math.max(0, stageProgress + delta); } } diff --git a/src/main/java/dev/loki/hook/HookManager.java b/src/main/java/dev/loki/hook/HookManager.java index 2da3ff5..21828b5 100644 --- a/src/main/java/dev/loki/hook/HookManager.java +++ b/src/main/java/dev/loki/hook/HookManager.java @@ -111,10 +111,7 @@ public class HookManager { return true; // "повешен" = завершён } - Hook nearest = findNearestUnoccupiedHook(killerLoc, 5.0); - if (nearest == null) { - nearest = findAvailableHook().orElse(null); - } + Hook nearest = findNearestUnoccupiedHook(killerLoc, 4.0); if (nearest != null) { nearest.hookSurvivor(survivor); survivor.setState(PlayerState.HOOKED); // Set state to HOOKED diff --git a/src/main/java/dev/loki/item/ItemMedkit.java b/src/main/java/dev/loki/item/ItemMedkit.java index 46ad11d..fefe9be 100644 --- a/src/main/java/dev/loki/item/ItemMedkit.java +++ b/src/main/java/dev/loki/item/ItemMedkit.java @@ -39,8 +39,8 @@ public class ItemMedkit implements BaseItem { meta.setDisplayName("§a" + getType().getDisplayName()); meta.setLore(Arrays.asList( "§7" + getType().getDescription(), - "§eCharges: §f" + charges + "/" + getType().getDefaultCharges(), - "§7Right-click to heal" + "§eЗаряды: §f" + charges + "/" + getType().getDefaultCharges(), + "§7ПКМ — лечиться" )); PersistentDataContainer pdc = meta.getPersistentDataContainer(); @@ -60,7 +60,7 @@ public class ItemMedkit implements BaseItem { @Override public void onUse(Player player) { if (charges > 0) { - player.sendMessage("§aYou start healing..."); + player.sendMessage(mdbd.getInstance().getConfigManager().getMessages().get("survivor.medkit.start")); } } diff --git a/src/main/java/dev/loki/item/ItemType.java b/src/main/java/dev/loki/item/ItemType.java index dd8ed48..1257c47 100644 --- a/src/main/java/dev/loki/item/ItemType.java +++ b/src/main/java/dev/loki/item/ItemType.java @@ -1,8 +1,8 @@ package dev.loki.item; public enum ItemType { - MEDKIT("Medkit", "Heals one health state", 16), - HOOK_CUTTER("Hook Cutter", "Cuts a survivor off a hook", 1); + MEDKIT("Медкит", "Лечит одно состояние здоровья", 16), + HOOK_CUTTER("Крюкорез", "Срезает выжившего с крюка", 1); private final String displayName; private final String description; diff --git a/src/main/java/dev/loki/killer/GeneratorKick.java b/src/main/java/dev/loki/killer/GeneratorKick.java index 110bf7c..82adc53 100644 --- a/src/main/java/dev/loki/killer/GeneratorKick.java +++ b/src/main/java/dev/loki/killer/GeneratorKick.java @@ -14,7 +14,9 @@ import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -39,6 +41,9 @@ public class GeneratorKick { private int globalCooldownTicks = 0; private BukkitTask cooldownTask; + /** Pending unblock tasks — cancelled on shutdown to avoid ghost tasks */ + private final List pendingUnblockTasks = new ArrayList<>(); + public GeneratorKick(Plugin plugin, GameConfig config, GeneratorManager generatorManager) { this.plugin = plugin; this.config = config; @@ -135,6 +140,8 @@ public class GeneratorKick { for (BukkitTask t : chargingTasks.values()) t.cancel(); chargingTasks.clear(); if (cooldownTask != null) { cooldownTask.cancel(); cooldownTask = null; } + for (BukkitTask t : pendingUnblockTasks) t.cancel(); + pendingUnblockTasks.clear(); } // ------------------------------------------------------------------------- @@ -164,9 +171,10 @@ public class GeneratorKick { // Unblock generator after kick-duration (separate from global cooldown) int unblockTicks = config.getKickDuration() * 20; - plugin.getServer().getScheduler().runTaskLater(plugin, () -> { + BukkitTask unblockTask = plugin.getServer().getScheduler().runTaskLater(plugin, () -> { gen.setBlocked(false); }, unblockTicks); + pendingUnblockTasks.add(unblockTask); // Start global kick cooldown startGlobalCooldown(); diff --git a/src/main/java/dev/loki/listener/PlayerInteractListener.java b/src/main/java/dev/loki/listener/PlayerInteractListener.java index 5b3b1ec..27f81b0 100644 --- a/src/main/java/dev/loki/listener/PlayerInteractListener.java +++ b/src/main/java/dev/loki/listener/PlayerInteractListener.java @@ -228,10 +228,32 @@ public class PlayerInteractListener implements Listener { // #13: Запрет входа в печки для всех (и маньяка тоже) — MUST be FIRST before any other checks if (event.getClickedBlock() != null) { String type = event.getClickedBlock().getType().toString(); + if (type.contains("FURNACE") || type.contains("SMOKER") || type.contains("BLAST_FURNACE")) { event.setCancelled(true); return; } + + // Chest interaction - cancel vanilla GUI for ALL players (including killer) + if (type.contains("CHEST")) { + event.setCancelled(true); + if (onChestInteract != null && !bp.isKiller()) { + onChestInteract.accept(player, true); + } + return; + } + } + + // Gate opening — проверяем ДО генератора, чтобы ворота можно было открыть рядом с геной + if (!bp.isKiller() && onHatchInteract != null) { + var s = gameManager.getPlayerSession(player.getUniqueId()); + if (s != null && s.getGateManager() != null) { + var gate = s.getGateManager().getGateAt(player.getLocation(), 3.0); + if (gate != null && !gate.isOpen()) { + onHatchInteract.accept(player, true); + return; + } + } } if (!bp.isKiller() && tryGeneratorInteract(player)) return; @@ -242,29 +264,15 @@ public class PlayerInteractListener implements Listener { return; } - // Gate opening via proximity for survivors — works on air clicks too - if (!bp.isKiller() && onHatchInteract != null) { - onHatchInteract.accept(player, true); - } - if (event.getClickedBlock() == null) return; String type = event.getClickedBlock().getType().toString(); - // Chest interaction - cancel vanilla GUI and use plugin chest system - if (type.contains("CHEST")) { - event.setCancelled(true); - if (onChestInteract != null && !bp.isKiller()) { - onChestInteract.accept(player, true); - } - return; - } // Hook rescue: if survivor clicks on a hook block, attempt rescue + // Hook rescue / block protection if (!bp.isKiller() && onRescueAttempt != null) { onRescueAttempt.accept(player, true); - if (type.contains("IRON_BARS") || type.contains("IRON")) event.setCancelled(true); } - // Cancel interaction with hook blocks to prevent block manipulation if (type.contains("IRON_BARS") || type.contains("IRON")) event.setCancelled(true); } diff --git a/src/main/java/dev/loki/objective/GeneratorManager.java b/src/main/java/dev/loki/objective/GeneratorManager.java index f8ac492..de128b0 100644 --- a/src/main/java/dev/loki/objective/GeneratorManager.java +++ b/src/main/java/dev/loki/objective/GeneratorManager.java @@ -1,6 +1,7 @@ package dev.loki.objective; import dev.loki.data.GeneratorDataManager; +import dev.loki.config.GameConfig; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -12,11 +13,15 @@ import java.util.Map; public class GeneratorManager { private final Map generators; private final int requiredCount; + private final double normalRegressionRate; + private final double kickRegressionRate; - public GeneratorManager(GeneratorDataManager dataManager, int requiredCount) { + public GeneratorManager(GeneratorDataManager dataManager, int requiredCount, GameConfig config) { this.generators = new HashMap<>(); - this.requiredCount = requiredCount; loadGenerators(dataManager); + this.requiredCount = Math.min(requiredCount, generators.size()); + this.normalRegressionRate = config.getRegressionRate() / 20.0; + this.kickRegressionRate = config.getKickRegressionRate() / 20.0; } private void loadGenerators(GeneratorDataManager dataManager) { @@ -103,7 +108,7 @@ public class GeneratorManager { public void tick() { for (Generator gen : generators.values()) { if (gen.isUnderRegression()) { - double rate = gen.wasKicked() ? 0.125 : 0.0125; + double rate = gen.wasKicked() ? kickRegressionRate : normalRegressionRate; gen.removeProgress(rate); } gen.decrementRegression(); diff --git a/src/main/java/dev/loki/objective/GeneratorRegression.java b/src/main/java/dev/loki/objective/GeneratorRegression.java deleted file mode 100644 index 012a28d..0000000 --- a/src/main/java/dev/loki/objective/GeneratorRegression.java +++ /dev/null @@ -1,52 +0,0 @@ -package dev.loki.objective; - -import dev.loki.config.GameConfig; - -public class GeneratorRegression { - private final GameConfig config; - - public GeneratorRegression(GameConfig config) { - this.config = config; - } - - public void applyRegression(Generator generator) { - if (generator.isCompleted() || generator.isBeingRepaired()) return; - double rate = generator.wasKicked() ? getKickRegressionRate() : getNormalRegressionRate(); - generator.removeProgress(rate); - } - - public void onGeneratorKicked(Generator generator) { - generator.setUnderRegression(true, config.getKickDuration() * 20); - } - - public void tick(Generator generator) { - if (!generator.isUnderRegression()) return; - applyRegression(generator); - generator.decrementRegression(); - if (generator.getRegressionTicks() <= 0) { - generator.setKicked(false); - } - } - - public void tickAll(GeneratorManager manager) { - for (Generator gen : manager.getAllGenerators()) { - if (!gen.isCompleted() && !gen.isBeingRepaired()) { - tick(gen); - } - } - } - - private double getNormalRegressionRate() { - return config.getRegressionRate() / 20.0; - } - - private double getKickRegressionRate() { - return config.getKickRegressionRate() / 20.0; - } - - public static boolean shouldStartRegression(Generator generator) { - return !generator.isCompleted() - && !generator.isBeingRepaired() - && generator.getProgress() > 0; - } -} diff --git a/src/main/java/dev/loki/objective/GeneratorRepair.java b/src/main/java/dev/loki/objective/GeneratorRepair.java index 18c75d9..e51f5b4 100644 --- a/src/main/java/dev/loki/objective/GeneratorRepair.java +++ b/src/main/java/dev/loki/objective/GeneratorRepair.java @@ -2,6 +2,7 @@ package dev.loki.objective; import dev.loki.mdbd; import dev.loki.minigames.GeneratorMinigame; +import dev.loki.player.BasePlayer; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -71,8 +72,8 @@ public class GeneratorRepair { if (session != null) { session.generator.setCurrentRepairer(null); // Progress is PRESERVED - generator keeps its progress value - // Only unblock if it was blocked due to an ongoing repair (not a kick) - if (!session.generator.isUnderRegression()) { + // Only unblock if it was blocked due to an ongoing repair (not a kick or block) + if (!session.generator.isUnderRegression() && !session.generator.isBlocked()) { session.generator.setBlocked(false); } player.sendActionBar(Component.empty()); @@ -176,12 +177,18 @@ public class GeneratorRepair { } } - /** Give every online killer a compass pointing to the failed generator for compass-duration-seconds. */ + /** Give only killers a compass pointing to the failed generator for compass-duration-seconds. */ private void notifyKillerWithCompass(Player failedPlayer, Generator generator) { + var session = plugin.getGameManager().getCurrentSession(); + if (session == null) return; + int durationTicks = plugin.getConfigManager().getGame().getCompassDurationSeconds() * 20; Location compassTarget = generator.getLocation(); - for (Player online : Bukkit.getOnlinePlayers()) { + for (BasePlayer bp : session.getPlayers().values()) { + if (!bp.isKiller()) continue; + Player online = bp.getPlayer(); + if (online == null || !online.isOnline()) continue; if (online.getUniqueId().equals(failedPlayer.getUniqueId())) continue; online.sendMessage(plugin.getConfigManager().getMessages().get("generator.kicked.notification")); @@ -196,7 +203,6 @@ public class GeneratorRepair { ItemStack prev = online.getInventory().getItemInOffHand(); online.getInventory().setItemInOffHand(compass); - // Восстанавливаем старый предмет только если в offhand всё ещё компас plugin.getServer().getScheduler().runTaskLater(plugin, () -> { ItemStack current = online.getInventory().getItemInOffHand(); if (current.getType() == Material.COMPASS) { diff --git a/src/main/java/dev/loki/objective/SkillCheck.java b/src/main/java/dev/loki/objective/SkillCheck.java deleted file mode 100644 index eff6f52..0000000 --- a/src/main/java/dev/loki/objective/SkillCheck.java +++ /dev/null @@ -1,142 +0,0 @@ -package dev.loki.objective; - -import dev.loki.mdbd; -import org.bukkit.Bukkit; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class SkillCheck { - private final mdbd plugin; - private final GeneratorRepair generatorRepair; - private final Map activeChecks; - - private static final double ZONE_SIZE = 0.15; - private static final double ROTATION_SPEED = 3.0; - - public SkillCheck(mdbd plugin, GeneratorRepair generatorRepair) { - this.plugin = plugin; - this.generatorRepair = generatorRepair; - this.activeChecks = new HashMap<>(); - } - - public void start(UUID playerId, Generator generator) { - double zoneStart = Math.random() * 0.7; - double zoneEnd = zoneStart + ZONE_SIZE; - - CheckState state = new CheckState( - playerId, - generator, - zoneStart, - zoneEnd, - 0.0, - ROTATION_SPEED - ); - activeChecks.put(playerId, state); - } - - public void tick() { - for (CheckState state : new HashMap<>(activeChecks).values()) { - state.update(); - - if (state.isExpired()) { - onFail(state); - } - } - } - - public boolean tryComplete(UUID playerId, boolean isSuccessZone) { - CheckState state = activeChecks.get(playerId); - if (state == null) return false; - - if (isSuccessZone) { - onSuccess(state); - } else { - onFail(state); - } - return true; - } - - private void onSuccess(CheckState state) { - activeChecks.remove(state.playerId); - Bukkit.getScheduler().runTask(plugin, () -> - generatorRepair.onSkillCheckResult(state.playerId, true, state.generator) - ); - } - - private void onFail(CheckState state) { - activeChecks.remove(state.playerId); - Bukkit.getScheduler().runTask(plugin, () -> - generatorRepair.onSkillCheckResult(state.playerId, false, state.generator) - ); - } - - public boolean isActive(UUID playerId) { - return activeChecks.containsKey(playerId); - } - - public CheckState getState(UUID playerId) { - return activeChecks.get(playerId); - } - - public static class CheckState { - final UUID playerId; - final Generator generator; - final double zoneStart; - final double zoneEnd; - double pointerPosition; - final double rotationSpeed; - int ticks; - - CheckState(UUID playerId, Generator generator, double zoneStart, double zoneEnd, - double pointerPosition, double rotationSpeed) { - this.playerId = playerId; - this.generator = generator; - this.zoneStart = zoneStart; - this.zoneEnd = zoneEnd; - this.pointerPosition = pointerPosition; - this.rotationSpeed = rotationSpeed; - this.ticks = 0; - } - - void update() { - pointerPosition += rotationSpeed * 0.01; - if (pointerPosition >= 1.0) { - pointerPosition = 0.0; - } - ticks++; - } - - boolean isExpired() { - return ticks > 100; - } - - boolean isInSuccessZone() { - return pointerPosition >= zoneStart && pointerPosition <= zoneEnd; - } - - public String getVisualRepresentation() { - int zoneStartPos = (int) (zoneStart * 20); - int zoneEndPos = (int) (zoneEnd * 20); - int pointerPos = (int) (pointerPosition * 20); - - StringBuilder sb = new StringBuilder("["); - for (int i = 0; i < 20; i++) { - if (i == pointerPos) { - sb.append("◆"); - } else if (i >= zoneStartPos && i <= zoneEndPos) { - sb.append("█"); - } else { - sb.append("░"); - } - } - sb.append("]"); - return sb.toString(); - } - - public double getPointerPosition() { - return pointerPosition; - } - } -} diff --git a/src/main/java/dev/loki/objective/SkillCheckInventory.java b/src/main/java/dev/loki/objective/SkillCheckInventory.java deleted file mode 100644 index 3ffe8c6..0000000 --- a/src/main/java/dev/loki/objective/SkillCheckInventory.java +++ /dev/null @@ -1,245 +0,0 @@ -package dev.loki.objective; - -import dev.loki.config.GameConfig; -import dev.loki.mdbd; -import dev.loki.objective.Generator; -import dev.loki.objective.GeneratorRepair; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import java.util.*; - -/** - * GUI-based Skill Check minigame — ROULETTE style. - * - * Green block moves sequentially left-to-right (0→1→2→...→8→0→...). - * Starts FAST (2-3 ticks), gradually slows down (8-12 ticks). - * ~12-18 switches, then stops on final slot. - * Player must click the GREEN block. Clicking gray = fail. Timeout = fail. - */ -public class SkillCheckInventory { - private final mdbd plugin; - private final Map activeSessions = new HashMap<>(); - private static final int TIMEOUT_TICKS = 60; // 3 seconds — не выбрал = проигрыш -10% - private static final int MIN_SWITCHES = 5; - private static final int MAX_SWITCHES = 8; - - private final Material successMaterial; - private final Material failMaterial; - private final Material neutralMaterial; - - public SkillCheckInventory(mdbd plugin) { - this.plugin = plugin; - GameConfig cfg = plugin.getConfigManager().getGame(); - this.successMaterial = getMaterial(cfg.getSkillCheckSuccessBlock(), Material.GREEN_STAINED_GLASS_PANE); - this.failMaterial = getMaterial(cfg.getSkillCheckFailBlock(), Material.RED_STAINED_GLASS_PANE); - this.neutralMaterial = getMaterial(cfg.getSkillCheckNeutralBlock(), Material.GRAY_STAINED_GLASS_PANE); - } - - private static Material getMaterial(String name, Material fallback) { - Material m = Material.getMaterial(name); - return m != null ? m : fallback; - } - - public void startSkillCheck(Player player, UUID playerId, SkillCheck skillCheck, Generator generator, GeneratorRepair generatorRepair) { - SkillCheckSession session = new SkillCheckSession(player, playerId, skillCheck, generator, generatorRepair); - activeSessions.put(playerId, session); - - Inventory inv = Bukkit.createInventory(null, 9, Component.text("⚡ Skill Check!").color(NamedTextColor.YELLOW)); - fillInventory(inv, session.successSlot); - player.openInventory(inv); - - // Schedule timeout - plugin.getServer().getScheduler().runTaskLater(plugin, () -> { - if (activeSessions.containsKey(playerId)) { - onTimeout(playerId); - } - }, TIMEOUT_TICKS); - - // Start roulette animation - runRoulette(playerId); - } - - /** - * Roulette animation: green block moves left-to-right sequentially, - * slowing down over time like a real roulette wheel. - */ - private void runRoulette(UUID playerId) { - SkillCheckSession session = activeSessions.get(playerId); - if (session == null || !session.player.isOnline()) { - activeSessions.remove(playerId); - return; - } - - // Check if timeout happened - if (session.totalTicks >= TIMEOUT_TICKS) { - onTimeout(playerId); - return; - } - - // Move green sequentially to next slot - session.lastSuccessSlot = session.successSlot; - session.successSlot = (session.successSlot + 1) % 9; - session.switchesDone++; - - // Update inventory visually - Inventory inv = session.player.getOpenInventory().getTopInventory(); - if (inv != null && inv.getSize() == 9) { - inv.setItem(session.lastSuccessSlot, createNeutralGlass()); - inv.setItem(session.successSlot, createSuccessGlass()); - // Play tick sound for roulette feel - session.player.playSound(session.player.getLocation(), Sound.BLOCK_NOTE_BLOCK_HAT, 0.5f, 1.5f); - } - - // Calculate next delay — roulette slows down - int nextDelay; - int done = session.switchesDone; - int total = session.totalSwitches; - - if (done < total * 0.4) { - // Fast phase: 40% of switches - nextDelay = 2 + (int)(Math.random() * 2); // 2-3 ticks - } else if (done < total * 0.8) { - // Medium phase: 40% of switches - nextDelay = 4 + (int)(Math.random() * 3); // 4-6 ticks - } else { - // Slow phase: final 20% of switches - nextDelay = 8 + (int)(Math.random() * 5); // 8-12 ticks - } - - session.totalTicks += nextDelay; - - // Stop roulette after totalSwitches — green stays on final slot - if (done >= total) { - // Roulette stopped — player must click now (timeout still ticking) - return; - } - - // Continue roulette - plugin.getServer().getScheduler().runTaskLater(plugin, () -> runRoulette(playerId), nextDelay); - } - - /** - * Called when the skill check inventory is closed (e.g. player presses ESC). - * Auto-fail: treats close as timeout. - */ - public void onInventoryClose(InventoryCloseEvent event) { - if (!(event.getPlayer() instanceof Player player)) return; - UUID playerId = player.getUniqueId(); - if (activeSessions.containsKey(playerId)) { - onTimeout(playerId); - } - } - - public void handleClick(InventoryClickEvent event, UUID playerId) { - // event.setCancelled(true) is already called in SkillCheckListener before this - SkillCheckSession session = activeSessions.remove(playerId); - if (session == null) return; - - Player player = event.getWhoClicked() instanceof Player ? (Player) event.getWhoClicked() : null; - if (player == null) return; - - player.closeInventory(); - - int clickedSlot = event.getRawSlot(); - boolean success = (clickedSlot == session.successSlot); - - if (success) { - player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.5f); - } else { - player.playSound(player.getLocation(), Sound.ENTITY_BLAZE_HURT, 1.0f, 0.5f); - } - - session.generatorRepair.onSkillCheckResult(playerId, success, session.generator); - } - - private void onTimeout(UUID playerId) { - SkillCheckSession session = activeSessions.remove(playerId); - if (session == null) return; - - Player player = session.player; - if (player != null && player.isOnline()) { - player.closeInventory(); - player.playSound(player.getLocation(), Sound.ENTITY_BLAZE_HURT, 1.0f, 0.5f); - } - - // Timeout = failure - session.generatorRepair.onSkillCheckResult(playerId, false, session.generator); - } - - private void fillInventory(Inventory inv, int greenSlot) { - for (int i = 0; i < 9; i++) { - inv.setItem(i, i == greenSlot ? createSuccessGlass() : createNeutralGlass()); - } - } - - private ItemStack createSuccessGlass() { - ItemStack glass = new ItemStack(successMaterial); - ItemMeta meta = glass.getItemMeta(); - if (meta != null) { - meta.displayName(Component.text("✓ Нажми!").color(NamedTextColor.GREEN)); - glass.setItemMeta(meta); - } - return glass; - } - - private ItemStack createFailGlass() { - ItemStack glass = new ItemStack(failMaterial); - ItemMeta meta = glass.getItemMeta(); - if (meta != null) { - meta.displayName(Component.text("✗").color(NamedTextColor.RED)); - glass.setItemMeta(meta); - } - return glass; - } - - private ItemStack createNeutralGlass() { - ItemStack glass = new ItemStack(neutralMaterial); - ItemMeta meta = glass.getItemMeta(); - if (meta != null) { - meta.displayName(Component.text("-").color(NamedTextColor.GRAY)); - glass.setItemMeta(meta); - } - return glass; - } - - public void clear() { - for (UUID uuid : new HashSet<>(activeSessions.keySet())) { - SkillCheckSession session = activeSessions.remove(uuid); - if (session.player != null && session.player.isOnline()) { - session.player.closeInventory(); - } - } - activeSessions.clear(); - } - - private static class SkillCheckSession { - final Player player; - final UUID playerId; - final SkillCheck skillCheck; - final Generator generator; - final GeneratorRepair generatorRepair; - int successSlot = 0; - int lastSuccessSlot = -1; - int switchesDone = 0; - final int totalSwitches = MIN_SWITCHES + new Random().nextInt(MAX_SWITCHES - MIN_SWITCHES + 1); - int totalTicks = 0; - - SkillCheckSession(Player player, UUID playerId, SkillCheck skillCheck, Generator generator, GeneratorRepair generatorRepair) { - this.player = player; - this.playerId = playerId; - this.skillCheck = skillCheck; - this.generator = generator; - this.generatorRepair = generatorRepair; - } - } -} diff --git a/src/main/java/dev/loki/objective/SkillCheckUI.java b/src/main/java/dev/loki/objective/SkillCheckUI.java deleted file mode 100644 index 468caf1..0000000 --- a/src/main/java/dev/loki/objective/SkillCheckUI.java +++ /dev/null @@ -1,120 +0,0 @@ -package dev.loki.objective; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.title.Title; -import org.bukkit.entity.Player; - -import java.util.UUID; - -public class SkillCheckUI { - private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); - - public static void showSkillCheck(Player player, SkillCheck.CheckState state) { - String visual = buildVisualDisplay(state); - Component title = MINI_MESSAGE.deserialize(visual); - Component subtitle = MINI_MESSAGE.deserialize("Нажмите ПКМ в зеленой зоне!"); - - player.showTitle(Title.title(title, subtitle)); - } - - public static void showActionBarSkillCheck(Player player, SkillCheck.CheckState state) { - String visual = buildCompactVisual(state); - player.sendActionBar(MiniMessage.miniMessage().deserialize(visual)); - } - - public static void showSuccess(Player player) { - player.showTitle(Title.title( - MINI_MESSAGE.deserialize("✓ Отлично!"), - Component.empty(), - Title.Times.times(java.time.Duration.ZERO, java.time.Duration.ofMillis(500), java.time.Duration.ZERO) - )); - } - - public static void showFail(Player player) { - player.showTitle(Title.title( - MINI_MESSAGE.deserialize("✗ Провал!"), - MINI_MESSAGE.deserialize("Потеря прогресса..."), - Title.Times.times(java.time.Duration.ZERO, java.time.Duration.ofMillis(800), java.time.Duration.ZERO) - )); - } - - public static void clear(Player player) { - player.clearTitle(); - player.sendActionBar(Component.empty()); - } - - private static String buildVisualDisplay(SkillCheck.CheckState state) { - double zoneStart = state.zoneStart; - double zoneEnd = state.zoneEnd; - double pointer = state.getPointerPosition(); - - int displayWidth = 15; - int zoneStartPos = (int) (zoneStart * displayWidth); - int zoneEndPos = (int) (zoneEnd * displayWidth); - int pointerPos = (int) (pointer * displayWidth); - - StringBuilder sb = new StringBuilder(); - sb.append(""); - - for (int i = 0; i < displayWidth; i++) { - if (i == pointerPos) { - sb.append("◆"); - } else if (i >= zoneStartPos && i <= zoneEndPos) { - sb.append("█"); - } else { - sb.append("▒"); - } - } - - sb.append(""); - return sb.toString(); - } - - private static String buildCompactVisual(SkillCheck.CheckState state) { - double zoneStart = state.zoneStart; - double zoneEnd = state.zoneEnd; - double pointer = state.getPointerPosition(); - - int displayWidth = 10; - int zoneStartPos = (int) (zoneStart * displayWidth); - int zoneEndPos = (int) (zoneEnd * displayWidth); - int pointerPos = (int) (pointer * displayWidth); - - StringBuilder sb = new StringBuilder(); - sb.append("QTE: ["); - - for (int i = 0; i < displayWidth; i++) { - if (i == pointerPos) { - sb.append("♦"); - } else if (i >= zoneStartPos && i <= zoneEndPos) { - sb.append("█"); - } else { - sb.append("░"); - } - } - - sb.append("]"); - return sb.toString(); - } - - public static String getSkillCheckText(UUID playerId, double pointer, double zoneStart, double zoneEnd) { - int width = 12; - int pPos = (int) (pointer * width); - int zStart = (int) (zoneStart * width); - int zEnd = (int) (zoneEnd * width); - - StringBuilder sb = new StringBuilder("["); - for (int i = 0; i < width; i++) { - if (i == pPos) { - sb.append("◆"); - } else if (i >= zStart && i <= zEnd) { - sb.append("█"); - } else { - sb.append("░"); - } - } - sb.append("]"); - return sb.toString(); - } -} diff --git a/src/main/java/dev/loki/phase/EndgamePhase.java b/src/main/java/dev/loki/phase/EndgamePhase.java index 3b1d45a..65b8624 100644 --- a/src/main/java/dev/loki/phase/EndgamePhase.java +++ b/src/main/java/dev/loki/phase/EndgamePhase.java @@ -78,6 +78,15 @@ public class EndgamePhase implements Phase { gateManager = session.getGateManager(); } + // Если ворота уже открыты — игра завершилась по таймеру эндгейма, + // показываем результаты сразу + if (gateManager != null && gateManager.getOpenGateCount() > 0) { + this.complete = true; + announceEndgameEnd(session); + teleportAllToLobby(session); + return; + } + // Set up sidebar sidebar = new Sidebar(); for (BasePlayer bp : session.getPlayers().values()) { @@ -101,7 +110,6 @@ public class EndgamePhase implements Phase { } } - updateGates(session); updateHatch(session); checkWinConditions(session); } @@ -123,6 +131,10 @@ public class EndgamePhase implements Phase { hatch.reset(); } + if (gateManager != null) { + gateManager.resetAll(); + } + // exit() НЕ вызывает session.stop() — это делает transitionToNextPhase() // Телепорт и результаты уже обработаны в enter() или будут в teleportAllToLobby } diff --git a/src/main/java/dev/loki/phase/GameplayDamageSystem.java b/src/main/java/dev/loki/phase/GameplayDamageSystem.java index dcc226a..0ff4519 100644 --- a/src/main/java/dev/loki/phase/GameplayDamageSystem.java +++ b/src/main/java/dev/loki/phase/GameplayDamageSystem.java @@ -42,6 +42,7 @@ public class GameplayDamageSystem { private Listener vanillaDamageBlocker; private ItemUseListener itemUseListener; private PlayerJumpListener jumpListener; + private org.bukkit.scheduler.BukkitTask swimmingTask; /** * Initialize damage and combat system. @@ -83,18 +84,21 @@ public class GameplayDamageSystem { p.playSound(p.getLocation(), Sound.ENTITY_PLAYER_HURT, 1.0f, 0.5f); p.setHealth(20.0); p.setSwimming(true); - Bukkit.getScheduler().runTaskTimer(plugin, task -> { - if (!p.isOnline()) { - task.cancel(); - return; + swimmingTask = new org.bukkit.scheduler.BukkitRunnable() { + @Override + public void run() { + if (!p.isOnline()) { + cancel(); + return; + } + if (survivor.getState() != PlayerState.DOWNED) { + p.setSwimming(false); + cancel(); + return; + } + if (!p.isSwimming()) p.setSwimming(true); } - if (survivor.getState() != PlayerState.DOWNED) { - p.setSwimming(false); - task.cancel(); - return; - } - if (!p.isSwimming()) p.setSwimming(true); - }, 1L, 5L); + }.runTaskTimer(plugin, 1L, 5L); }); killerController = new KillerController(plugin, playerManager, damageHandler, cfg); @@ -138,6 +142,10 @@ public class GameplayDamageSystem { * Clear all damage system resources. */ public void clear() { + if (swimmingTask != null) { + swimmingTask.cancel(); + swimmingTask = null; + } if (jumpListener != null) { jumpListener.clearInGamePlayers(); jumpListener.unregister(); @@ -156,7 +164,15 @@ public class GameplayDamageSystem { */ public void clearManagers() { if (killerController != null) killerController.shutdown(); - if (playerManager != null) playerManager.clear(); + if (playerManager != null) { + for (BasePlayer bp : playerManager.getAllPlayers()) { + Player p = bp.getPlayer(); + if (p != null && p.isOnline()) { + p.setSwimming(false); + } + } + playerManager.clear(); + } } // ========================================================================= diff --git a/src/main/java/dev/loki/phase/GameplayHookHandler.java b/src/main/java/dev/loki/phase/GameplayHookHandler.java index 2c1ede6..55df515 100644 --- a/src/main/java/dev/loki/phase/GameplayHookHandler.java +++ b/src/main/java/dev/loki/phase/GameplayHookHandler.java @@ -4,8 +4,10 @@ import dev.loki.config.GameConfig; import dev.loki.core.GameSession; import dev.loki.hook.*; import dev.loki.player.BasePlayer; +import dev.loki.player.PlayerState; import dev.loki.player.Survivor; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.entity.Player; /** @@ -18,6 +20,10 @@ public class GameplayHookHandler { private final HookSacrifice hookSacrifice; private final HookStruggle hookStruggle; private final HookRecovery hookRecovery; + private GameSession session; + + private static final double CAMP_REGRESS_RANGE = 7.0; + private static final double CAMP_STALL_RANGE = 13.0; public GameplayHookHandler(HookManager hookManager, HookSacrifice hookSacrifice, HookStruggle hookStruggle, HookRecovery hookRecovery) { @@ -27,12 +33,17 @@ public class GameplayHookHandler { this.hookRecovery = hookRecovery; } + public void setSession(GameSession session) { + this.session = session; + } + private int hookTpTick; /** - * Called every tick - checks hook stage progression and teleports hooked players back. + * Called every tick - checks hook stage progression, killer proximity, and teleports hooked players back. */ public void tick() { + applyKillerProximity(); checkHookStages(); hookTpTick++; if (hookTpTick >= 20) { @@ -41,6 +52,45 @@ public class GameplayHookHandler { } } + /** + * If the killer is near a hook, slow or regress the hook progression. + * < 7 blocks → regress (goes negative) + * 7-13 blocks → stall (no progression) + * > 13 blocks → normal + */ + private void applyKillerProximity() { + if (session == null) return; + + Location killerLoc = null; + for (BasePlayer bp : session.getPlayers().values()) { + if (bp.isKiller()) { + Player p = bp.getPlayer(); + if (p != null && p.isOnline()) { + killerLoc = p.getLocation(); + } + break; + } + } + if (killerLoc == null) return; + + for (Hook hook : hookManager.getAllHooks()) { + if (!hook.isOccupied()) continue; + if (!killerLoc.getWorld().equals(hook.getLocation().getWorld())) continue; + + double dist = killerLoc.distance(hook.getLocation()); + + if (dist < CAMP_REGRESS_RANGE) { + // Regress: -2 per tick (faster than normal +1) + hook.addStageProgress(-2); + // If STAGE_1 and progress goes to 0, that's as low as it gets + } else if (dist < CAMP_STALL_RANGE) { + // Stall: cancel the normal +1 by adding -1 + hook.addStageProgress(-1); + } + // else: normal progression (Hook.tick already adds +1) + } + } + /** * Teleport hooked survivors back to their hook if they've moved too far. */ diff --git a/src/main/java/dev/loki/phase/GameplayInteraction.java b/src/main/java/dev/loki/phase/GameplayInteraction.java index f13a92a..bf03269 100644 --- a/src/main/java/dev/loki/phase/GameplayInteraction.java +++ b/src/main/java/dev/loki/phase/GameplayInteraction.java @@ -110,21 +110,7 @@ public class GameplayInteraction { } private void wireMoveListener(GameSession session) { - if (moveListener == null) return; - moveListener.setOnSurvivorMove((survivor, loc) -> { - if (!allGensDone) return; - if (survivor.getState() == PlayerState.ESCAPED) return; - ExitGate gate = gateManager.getGateAt(loc, 3.0); - if (gate != null && gate.isOpen()) { - survivor.setState(PlayerState.ESCAPED); - Player p = survivor.getPlayer(); - if (p != null) { - p.playSound(loc, Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.2f); - Bukkit.broadcast(Component.text( - "[DBD] " + p.getName() + " сбежал через ворота!", NamedTextColor.GOLD)); - } - } - }); + // Escape check is handled in GameplayPhase.checkEscapes() every tick during POSTGAME } private void wireInteractListener(GameSession session) { @@ -156,10 +142,13 @@ public class GameplayInteraction { Survivor carried = (Survivor) other; if (hookManager.tryHookSurvivor(carried, player.getLocation())) { killer.setCarrying(false); - Hook nearest = hookManager.findNearestOccupiedHook(player.getLocation(), 5.0); - if (nearest != null) { - Player vp = carried.getPlayer(); - if (vp != null) vp.teleport(nearest.getLocation()); + // Only teleport if actually hooked (not dead from exceeding hook limit) + if (carried.getState() == PlayerState.HOOKED) { + Hook nearest = hookManager.findNearestOccupiedHook(player.getLocation(), 5.0); + if (nearest != null) { + Player vp = carried.getPlayer(); + if (vp != null) vp.teleport(nearest.getLocation()); + } } } break; @@ -190,10 +179,12 @@ public class GameplayInteraction { Survivor carried = (Survivor) other; if (hookManager.tryHookSurvivor(carried, player.getLocation())) { killer.setCarrying(false); - Hook nearest = hookManager.findNearestOccupiedHook(player.getLocation(), 5.0); - if (nearest != null) { - Player vp = carried.getPlayer(); - if (vp != null) vp.teleport(nearest.getLocation()); + if (carried.getState() == PlayerState.HOOKED) { + Hook nearest = hookManager.findNearestOccupiedHook(player.getLocation(), 5.0); + if (nearest != null) { + Player vp = carried.getPlayer(); + if (vp != null) vp.teleport(nearest.getLocation()); + } } return; } diff --git a/src/main/java/dev/loki/phase/GameplayPhase.java b/src/main/java/dev/loki/phase/GameplayPhase.java index c185496..44ce48f 100644 --- a/src/main/java/dev/loki/phase/GameplayPhase.java +++ b/src/main/java/dev/loki/phase/GameplayPhase.java @@ -25,6 +25,8 @@ import dev.loki.player.Survivor; import dev.loki.ui.ActionBar; import dev.loki.ui.TitleUI; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.title.Title; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; @@ -33,15 +35,20 @@ import org.bukkit.Sound; import org.bukkit.block.Block; import org.bukkit.entity.Player; +import java.time.Duration; import java.util.ArrayList; import java.util.List; public class GameplayPhase implements Phase { + private enum EndgameState { NONE, PREGAME, POSTGAME } + private final GeneratorManager generatorManager; private int tickCounter; private boolean shouldEnd; private boolean allGensDone; + private EndgameState endgameState = EndgameState.NONE; + private int endgameTimer; // секунд до смены состояния // Sub-handlers private GameplayHookHandler hookHandler; @@ -81,6 +88,8 @@ public class GameplayPhase implements Phase { tickCounter = 0; shouldEnd = false; allGensDone = false; + endgameState = EndgameState.NONE; + endgameTimer = 0; winConditions = new GameplayWinConditions(); initManagers(session, plugin, cfg); @@ -104,7 +113,6 @@ public class GameplayPhase implements Phase { if (generatorRepair != null) generatorRepair.tick(); if (interaction != null) interaction.tickSurvivors(); hookHandler.tick(); - boolean timeExpired = ui.tickMatchTimer(session); // Particle effects around generators (every 10 ticks) if (tickCounter % 10 == 0 && generatorManager != null) { @@ -119,19 +127,29 @@ public class GameplayPhase implements Phase { } if (tickCounter % 20 == 0) { + tickEndgame(session); checkGeneratorProgress(session); - winConditions.checkWinConditions(session); - if (winConditions.isShouldEnd() || timeExpired) { - shouldEnd = true; + if (endgameState == EndgameState.NONE) { + winConditions.checkWinConditions(session); + if (winConditions.isShouldEnd()) { + shouldEnd = true; + } + } else { + // Во время эндгейма игра заканчивается когда все выжившие мертвы/сбежали + if (allSurvivorsIncapacitated(session)) { + shouldEnd = true; + } + // Или когда истёк таймер после открытия ворот + if (endgameState == EndgameState.POSTGAME && endgameTimer <= 0) { + shouldEnd = true; + } } ui.updateSidebar(session, generatorManager); } - if (timeExpired) { - showGameResults(session); - teleportAllToLobby(session); - session.stop(); - return; + // Escape check — каждый тик для мгновенной реакции + if (endgameState == EndgameState.POSTGAME) { + checkEscapes(session); } } @@ -193,6 +211,7 @@ public class GameplayPhase implements Phase { hookRescue = new HookRescue(plugin, ab, cfg); hookHandler = new GameplayHookHandler(hookManager, hookSacrifice, hookStruggle, hookRecovery); + hookHandler.setSession(session); hookRescue.setOnRescueComplete((rescuer, victim) -> hookHandler.onRescued(victim)); chestManager = new ChestManager(plugin, plugin.getConfigManager().getLocations(), cfg); @@ -267,12 +286,30 @@ public class GameplayPhase implements Phase { // Tick helpers // ========================================================================= + /** Все выжившие мертвы или сбежали? */ + private boolean allSurvivorsIncapacitated(GameSession session) { + boolean hasSurvivor = false; + for (BasePlayer bp : session.getPlayers().values()) { + if (bp.isKiller()) continue; + hasSurvivor = true; + PlayerState st = bp.getState(); + if (st != PlayerState.DEAD && st != PlayerState.ESCAPED + && st != PlayerState.DOWNED && st != PlayerState.HOOKED + && st != PlayerState.CARRIED) { + return false; + } + } + return hasSurvivor; + } + private void checkGeneratorProgress(GameSession session) { if (allGensDone) return; if (generatorManager.areAllRequiredCompleted()) { allGensDone = true; interaction.setAllGensDone(true); gateManager.activateEndgame(); + endgameState = EndgameState.PREGAME; + endgameTimer = session.getConfig().getPregameSeconds(); Bukkit.broadcast(session.getPlugin().getConfigManager().getMessages().get("generator.repair.all-done")); for (BasePlayer bp : session.getPlayers().values()) { Player p = bp.getPlayer(); @@ -281,6 +318,63 @@ public class GameplayPhase implements Phase { } } + private void tickEndgame(GameSession session) { + if (endgameState == EndgameState.NONE) return; + + endgameTimer--; + + if (endgameState == EndgameState.PREGAME) { + // Каждую секунду шлём сообщение о начале эндгейма + if (endgameTimer > 0) { + for (BasePlayer bp : session.getPlayers().values()) { + Player p = bp.getPlayer(); + if (p == null) continue; + p.sendActionBar(net.kyori.adventure.text.Component.text( + "§c⚡ Эндгейм! Ворота откроются через §e" + endgameTimer + "с")); + } + } else { + // Таймер истёк — открываем ворота + gateManager.openAllGates(); + endgameState = EndgameState.POSTGAME; + endgameTimer = session.getConfig().getPostgameSeconds(); + for (BasePlayer bp : session.getPlayers().values()) { + Player p = bp.getPlayer(); + if (p == null) continue; + Title title = Title.title( + Component.text("ВОРОТА ОТКРЫТЫ!").color(NamedTextColor.GREEN), + Component.text("Бегите к выходу! (" + endgameTimer + "с)").color(NamedTextColor.YELLOW), + Title.Times.times(Duration.ofMillis(500), Duration.ofSeconds(3), Duration.ofMillis(500)) + ); + p.showTitle(title); + p.playSound(p.getLocation(), Sound.BLOCK_IRON_DOOR_OPEN, 1.0f, 1.0f); + } + } + } else if (endgameState == EndgameState.POSTGAME) { + if (endgameTimer > 0 && endgameTimer % 10 == 0 && endgameTimer <= 30) { + Bukkit.broadcast(Component.text("§c⚠ До конца игры: §e" + endgameTimer + "с")); + } + } + } + + private void checkEscapes(GameSession session) { + double escapeRange = session.getConfig().getEscapeRange(); + for (BasePlayer bp : session.getPlayers().values()) { + if (bp.isKiller()) continue; + if (bp.getState() == PlayerState.ESCAPED) continue; + if (bp.getState() != PlayerState.HEALTHY && bp.getState() != PlayerState.INJURED) continue; + Survivor survivor = (Survivor) bp; + Player p = survivor.getPlayer(); + if (p == null || !p.isOnline()) continue; + ExitGate gate = gateManager.getGateAt(p.getLocation(), escapeRange); + if (gate != null && gate.isOpen()) { + survivor.setState(PlayerState.ESCAPED); + p.playSound(p.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.2f); + Bukkit.broadcast(Component.text( + "§6[DBD] §a" + p.getName() + " §6сбежал через ворота!")); + } + } + } + private void spawnGameBlocks(mdbd plugin, GameConfig cfg) { // Спавн блоков на местах генераторов Material genMat = Material.matchMaterial(cfg.getGeneratorBlock()); @@ -333,35 +427,6 @@ public class GameplayPhase implements Phase { // Cleanup // ========================================================================= - private void showGameResults(GameSession session) { - List results = new ArrayList<>(); - results.add("§6§l=== РЕЗУЛЬТАТЫ ==="); - int escaped = 0, died = 0; - for (BasePlayer player : session.getPlayers().values()) { - if (player.isKiller()) { - Player p = player.getPlayer(); - String name = p != null ? p.getName() : "Unknown"; - results.add("§c☠ " + name + " — Маньяк"); - continue; - } - Player p = player.getPlayer(); - String name = p != null ? p.getName() : "Unknown"; - if (player.getState() == PlayerState.ESCAPED) { - results.add("§a✔ " + name + " — Сбежал"); - escaped++; - } else { - results.add("§c✘ " + name + " — Погиб"); - died++; - } - } - results.add("§7Выживших: §a" + escaped + " §7/ Погибших: §c" + died); - String msg = String.join("\n", results); - for (BasePlayer player : session.getPlayers().values()) { - Player p = player.getPlayer(); - if (p != null) p.sendMessage(msg); - } - } - private void teleportAllToLobby(GameSession session) { for (BasePlayer bp : session.getPlayers().values()) { Player p = bp.getPlayer(); @@ -395,12 +460,11 @@ public class GameplayPhase implements Phase { if (hookStruggle != null) hookStruggle.clear(); if (chestManager != null) chestManager.stopLootResetTimer(); if (chestHologram != null) chestHologram.stop(); - // Clean up gate blocks + // Clean up gate blocks — don't reset gate state (EndgamePhase needs to know gates were open) if (gateManager != null) { for (ExitGate gate : gateManager.getAllGates()) { gate.removeGateBlock(); } - gateManager.resetAll(); } session.getPlugin().getInteractListener().setGeneratorManager(null); } diff --git a/src/main/java/dev/loki/survivor/SurvivorHealing.java b/src/main/java/dev/loki/survivor/SurvivorHealing.java index efaa516..b34ae8c 100644 --- a/src/main/java/dev/loki/survivor/SurvivorHealing.java +++ b/src/main/java/dev/loki/survivor/SurvivorHealing.java @@ -4,8 +4,8 @@ import dev.loki.config.GameConfig; import dev.loki.mdbd; import dev.loki.player.PlayerState; import dev.loki.player.Survivor; +import dev.loki.util.TextUtil; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.entity.Player; import java.util.UUID; @@ -98,6 +98,10 @@ public class SurvivorHealing { if (targetSurvivor == null) { cancelHealing(); return; } PlayerState targetState = targetSurvivor.getState(); + if (targetState == PlayerState.DEAD || targetState == PlayerState.ESCAPED) { + cancelHealing(); + return; + } if (targetState != PlayerState.INJURED && targetState != PlayerState.DOWNED) { completeHealing(targetSurvivor); return; @@ -166,7 +170,7 @@ public class SurvivorHealing { String bar = renderProgressBar(progress); String template = mdbd.getInstance().getConfigManager().getMessages().getString( isSelfHeal ? "survivor.heal.self-start" : "survivor.heal.other-start", bar); - Component message = MiniMessage.miniMessage().deserialize(template); + Component message = TextUtil.color(template); healingTarget.sendActionBar(message); // Also show on healer Player healer = controller.getPlayer(); diff --git a/src/main/java/dev/loki/survivor/SurvivorMovement.java b/src/main/java/dev/loki/survivor/SurvivorMovement.java index c4c4e2a..8f5830e 100644 --- a/src/main/java/dev/loki/survivor/SurvivorMovement.java +++ b/src/main/java/dev/loki/survivor/SurvivorMovement.java @@ -77,7 +77,7 @@ public class SurvivorMovement { if (player == null) return; if (isCrawling) { - player.addPotionEffect(new PotionEffect(PotionEffectType.SLOWNESS, 5, 2, false, false)); + player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, 10, 0, false, false)); } } diff --git a/src/main/java/dev/loki/ui/ActionBar.java b/src/main/java/dev/loki/ui/ActionBar.java index daf40d6..d942064 100644 --- a/src/main/java/dev/loki/ui/ActionBar.java +++ b/src/main/java/dev/loki/ui/ActionBar.java @@ -4,6 +4,7 @@ import dev.loki.hook.Hook; import dev.loki.hook.HookStage; import dev.loki.player.PlayerState; import dev.loki.player.Survivor; +import dev.loki.util.TextUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; @@ -12,7 +13,7 @@ import org.bukkit.entity.Player; public class ActionBar { public void sendMessage(Player player, String message) { - player.sendActionBar(Component.text(message)); + player.sendActionBar(TextUtil.color(message)); } public void sendComponent(Player player, Component component) { @@ -26,20 +27,20 @@ public class ActionBar { public void showRepairProgress(Player player, double percent, boolean skillCheckActive) { Component bar = ProgressBar.create(percent); - TextComponent message = Component.text("Repairing ") + TextComponent message = Component.text("Починка: ") .color(NamedTextColor.WHITE) .append(bar) .append(Component.text(" " + (int) percent + "%").color(NamedTextColor.GRAY)); if (skillCheckActive) { - message = message.append(Component.text(" ⚠ SKILL CHECK!").color(NamedTextColor.YELLOW)); + message = message.append(Component.text(" ⚠ СКИЛЛ-ЧЕК!").color(NamedTextColor.YELLOW)); } player.sendActionBar(message); } public void showHealProgress(Player player, double percent, boolean selfHeal) { - String label = selfHeal ? "Healing self" : "Healing ally"; + String label = selfHeal ? "Лечение себя" : "Лечение союзника"; Component bar = ProgressBar.create(percent); Component message = Component.text(label + " ") .color(NamedTextColor.WHITE) @@ -50,7 +51,7 @@ public class ActionBar { public void showRescueProgress(Player player, double percent) { Component bar = ProgressBar.create(percent); - Component message = Component.text("Rescuing ") + Component message = Component.text("Спасение: ") .color(NamedTextColor.WHITE) .append(bar) .append(Component.text(" " + (int) percent + "%").color(NamedTextColor.GRAY)); @@ -71,15 +72,15 @@ public class ActionBar { if (stage == HookStage.STAGE_1) { stageIcon = StatusIcons.HOOK; stageColor = NamedTextColor.YELLOW; - stageName = "Stage 1"; + stageName = "Стадия 1"; } else if (stage == HookStage.STAGE_2) { stageIcon = StatusIcons.HOOK; stageColor = NamedTextColor.RED; - stageName = "Stage 2 - STRUGGLE!"; + stageName = "Стадия 2 — ВЫРВИСЬ!"; } else { stageIcon = StatusIcons.DEATH_SKULL; stageColor = NamedTextColor.DARK_RED; - stageName = "SACRIFICE IMMINENT"; + stageName = "ЖЕРТВОПРИНОШЕНИЕ"; } Component bar = stage == HookStage.STAGE_2 @@ -91,7 +92,7 @@ public class ActionBar { .append(bar); if (stage == HookStage.STAGE_2) { - message = message.append(Component.text(" CROUCH to struggle!").color(NamedTextColor.YELLOW)); + message = message.append(Component.text(" ПРИСЯДЬ чтобы вырваться!").color(NamedTextColor.YELLOW)); } player.sendActionBar(message); @@ -108,22 +109,22 @@ public class ActionBar { private Component formatStatus(PlayerState state) { return switch (state) { case HEALTHY -> StatusIcons.HEALTHY_HEART - .append(Component.text(" Healthy").color(NamedTextColor.GREEN)); + .append(Component.text(" Здоров").color(NamedTextColor.GREEN)); case INJURED -> StatusIcons.INJURED_HEART - .append(Component.text(" Injured").color(NamedTextColor.YELLOW)); - case DOWNED -> Component.text("🆘 Downed - need help!").color(NamedTextColor.RED); + .append(Component.text(" Ранен").color(NamedTextColor.YELLOW)); + case DOWNED -> Component.text("🆘 В нокдауне — нужна помощь!").color(NamedTextColor.RED); case HOOKED -> StatusIcons.HOOK - .append(Component.text(" Hooked!").color(NamedTextColor.DARK_RED)); - case CARRIED -> Component.text("🎒 Being carried").color(NamedTextColor.RED); + .append(Component.text(" На крюке!").color(NamedTextColor.DARK_RED)); + case CARRIED -> Component.text("🎒 Унесен маньяком").color(NamedTextColor.RED); default -> Component.text(""); }; } public void showCarrying(Player killer, String survivorName) { - Component message = Component.text("Carrying: ") + Component message = Component.text("Несет: ") .color(NamedTextColor.WHITE) .append(Component.text(survivorName).color(NamedTextColor.YELLOW)) - .append(Component.text(" - Find a hook!").color(NamedTextColor.GRAY)); + .append(Component.text(" — Найди крюк!").color(NamedTextColor.GRAY)); killer.sendActionBar(message); } diff --git a/src/main/java/dev/loki/ui/Sidebar.java b/src/main/java/dev/loki/ui/Sidebar.java index 96f3579..fd3eb62 100644 --- a/src/main/java/dev/loki/ui/Sidebar.java +++ b/src/main/java/dev/loki/ui/Sidebar.java @@ -94,14 +94,14 @@ public class Sidebar { // Clear ALL old entries in this objective first time only if (lastSeconds == null) { for (String entry : new ArrayList<>(board.getEntries())) { - if (timerObj.getScore(entry).getScore() == 0 || entry.contains("⏱") || entry.contains("До конца")) { + if (timerObj.getScore(entry).getScore() == 0 || entry.contains("⏱") || entry.contains("Time left")) { board.resetScores(entry); } } } // Use a FIXED entry key that never changes - only the score updates - String timerEntry = "§6⏱ До конца: §c" + seconds + " сек"; + String timerEntry = "§6⏱ Осталось: §c" + seconds + "с"; // Simply update the score - the entry persists Score score = timerObj.getScore(timerEntry); @@ -124,7 +124,7 @@ public class Sidebar { // Clear entries and hide for (String entry : board.getEntries()) { - if (entry.contains("⏱") || entry.contains("До конца")) { + if (entry.contains("⏱") || entry.contains("Осталось")) { board.resetScores(entry); } } @@ -155,19 +155,17 @@ public class Sidebar { if (endgameSecondsLeft >= 0) { String timerColor = endgameSecondsLeft <= 30 ? "§c" : "§e"; setScore(objective, "§8─────────────────", line--); - setScore(objective, timerColor + "⏱ До конца: " + endgameSecondsLeft + " сек", line--); + setScore(objective, timerColor + "⏱ Осталось: " + endgameSecondsLeft + "с", line--); setScore(objective, "§8─────────────────", line--); } - // Generator progress + // Generator progress — use actual placed count, not config max int completedGens = generatorManager != null ? generatorManager.getCompletedCount() : 0; - int requiredGens = cfg.getGeneratorRequired(); - int totalGens = cfg.getGeneratorTotal(); + int totalGens = generatorManager != null ? generatorManager.getTotalCount() : cfg.getGeneratorRequired(); setScore(objective, "§eГенераторы:", line--); - String genBar = buildGenBar(completedGens, requiredGens); - setScore(objective, " §f" + completedGens + "/" + requiredGens + " " + genBar, line--); - setScore(objective, " §7(всего: " + totalGens + ")", line--); + String genBar = buildGenBar(completedGens, totalGens); + setScore(objective, " §f" + completedGens + "/" + totalGens + " " + genBar, line--); setScore(objective, " ", line--); // Survivor list with hearts and colors diff --git a/src/main/java/dev/loki/ui/TitleUI.java b/src/main/java/dev/loki/ui/TitleUI.java index 22791bc..13c8c95 100644 --- a/src/main/java/dev/loki/ui/TitleUI.java +++ b/src/main/java/dev/loki/ui/TitleUI.java @@ -33,16 +33,16 @@ public class TitleUI { Component subtitle; if (isKiller) { - title = Component.text("KILLER") + title = Component.text("МАНЬЯК") .color(NamedTextColor.DARK_RED) .decoration(TextDecoration.BOLD, true); - subtitle = Component.text("Sacrifice them all") + subtitle = Component.text("Принеси их в жертву") .color(NamedTextColor.RED); } else { - title = Component.text("SURVIVOR") + title = Component.text("ВЫЖИВШИЙ") .color(NamedTextColor.DARK_GREEN) .decoration(TextDecoration.BOLD, true); - subtitle = Component.text("Repair generators and escape") + subtitle = Component.text("Чини генераторы и выбирайся") .color(NamedTextColor.GREEN); } @@ -57,17 +57,17 @@ public class TitleUI { ); Component title = escaped - ? Component.text("ESCAPED!") + ? Component.text("СБЕЖАЛ!") .color(NamedTextColor.GREEN) .decoration(TextDecoration.BOLD, true) - : Component.text("VICTORY!") + : Component.text("ПОБЕДА!") .color(NamedTextColor.DARK_RED) .decoration(TextDecoration.BOLD, true); Component subtitle = escaped - ? Component.text("You survived the night") + ? Component.text("Ты пережил ночь") .color(NamedTextColor.DARK_GREEN) - : Component.text("All survivors sacrificed") + : Component.text("Все выжившие принесены в жертву") .color(NamedTextColor.RED); player.showTitle(Title.title(title, subtitle, times)); @@ -80,11 +80,11 @@ public class TitleUI { Duration.ofSeconds(1) ); - Component title = Component.text("DEFEAT") + Component title = Component.text("ПОРАЖЕНИЕ") .color(NamedTextColor.DARK_RED) .decoration(TextDecoration.BOLD, true); - Component subtitle = Component.text("The Entity claims all") + Component subtitle = Component.text("Сущность забирает всех") .color(NamedTextColor.RED); player.showTitle(Title.title(title, subtitle, times)); diff --git a/src/main/resources/game.yml b/src/main/resources/game.yml index 05bf4f6..8c843b7 100644 --- a/src/main/resources/game.yml +++ b/src/main/resources/game.yml @@ -195,12 +195,21 @@ endgame: # Время открытия ворот (секунд) gate-open-seconds: 20 + # Секунд до открытия ворот (после починки всех ген) + pregame-seconds: 30 + + # Секунд после открытия ворот до конца игры + postgame-seconds: 60 + # Открытие сундуков (секунд) chest-open-seconds: 3 # Расстояние для взаимодействия с воротами (блоков) gate-interaction-range: 3.0 + # Расстояние до ворот для побега (блоков) + escape-range: 2.0 + # Уведомление маньяка о генераторе killer-notification: # Время действия компаса (секунд) diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 2db8982..289728c 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -116,6 +116,11 @@ setup: survivor-spawn-placed: "%setup-prefix%&aСпавн для &6%s &aвыжившего установлен! (всего: %d/4) %s" wand-point: "%setup-prefix%&a[Wand] Точка %d: %s" map-cleared: "%setup-prefix%&aКарта очищена!" + cleared: "%setup-prefix%&aВсе объекты удалены из конфига!" + cleared-type: "%setup-prefix%&aОбъекты &6%s &aудалены из конфига!" + delete-usage: "%setup-prefix%&cИспользование: /dbdsetup delete <тип> <номер>" + out-of-range: "%setup-prefix%&cИндекс &6%d &cвне диапазона!" + deleted: "%setup-prefix%&aОбъект &6%s &aудалён!" spawns-cleared: "%setup-prefix%&aВсе спавны (киллер + выжившие) очищены!" lobby-set: "%setup-prefix%&aЛобби установлено: %s" @@ -200,7 +205,7 @@ survivor: actionbar: "&a⚕ %s %d%%" done: "%prefix%&a✔ Вы вылечились!" cancelled: "%prefix%&eЛечение прервано." - depleted: "&cYour medkit has been depleted!" + depleted: "&cМедкит закончился!" # ── Крюки ────────────────────────────────────── @@ -228,18 +233,22 @@ hook: sacrifice: message: "%prefix%&4Вы были принесены в жертву. Наблюдайте за матчем." title: "☠" - subtitle: "&cYou have been sacrificed" - broadcast: "%s has been sacrificed to the Entity" + subtitle: "&cВы были принесены в жертву" + broadcast: "%s принесен в жертву Сущности" # ── Сундуки ──────────────────────────────────── chest: - empty: "&cThis chest is empty!" - opening: "&eOpening chest..." - cancelled: "&cOpening cancelled!" + empty: "&cСундук пуст!" + opening: "&eОткрытие сундука..." + cancelled: "&cОткрытие прервано!" too-far: "%prefix%&cСлишком далеко!" actionbar: "&6Открытие: %s %d%%" found: "%prefix%&aВы нашли: %s" + +# ── Ворота ───────────────────────────────────── + +gate: door-open: "&aОткрываем ворота... (зажмите ПКМ)" door-opened: "&aВорота открыты!" door-nearby: "&cНет ворот поблизости!" @@ -307,6 +316,8 @@ usage: setup-killer-spawn: "&6/dbdsetup set killer-spawn — Спавн киллера (только 1)" setup-survivor-spawn: "&6/dbdsetup set survivor-spawn — Спавн выжившего (до 4)" setup-gate: "&6/dbdsetup set gate A|B — Установить ворота (из точек ванда)" + setup-clear: "&6/dbdsetup clear [тип] — Очистить объекты (без разрушения блоков)" + setup-delete: "&6/dbdsetup delete <тип> <#> — Удалить конкретный объект" setup-clear-spawns: "&6/dbdsetup clear-spawns — Очистить все спавны" setup-lobby: "&6/dbdsetup lobby — Установить точку лобби" admin-list-header: "&6=== DBD Admin ===" From 2f4de4fbb63315ee746aa841dbc6d9dec77312e5 Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Mon, 15 Jun 2026 11:15:47 +0200 Subject: [PATCH 04/10] chore: remove bin/ from tracking, add to gitignore --- bin/main/config.yml | 49 ---- bin/main/dev/loki/chest/Chest.class | Bin 2824 -> 0 bytes bin/main/dev/loki/chest/ChestManager.class | Bin 4844 -> 0 bytes bin/main/dev/loki/chest/ChestOpening$1.class | Bin 2995 -> 0 bytes bin/main/dev/loki/chest/ChestOpening.class | Bin 6236 -> 0 bytes .../dev/loki/command/DBDAdminCommand.class | Bin 12317 -> 0 bytes bin/main/dev/loki/command/DBDCommand.class | Bin 13871 -> 0 bytes bin/main/dev/loki/command/SetupCommand.class | Bin 18426 -> 0 bytes bin/main/dev/loki/config/ConfigManager.class | Bin 5417 -> 0 bytes bin/main/dev/loki/config/GameConfig.class | Bin 11721 -> 0 bytes .../dev/loki/config/LocationsConfig.class | Bin 7800 -> 0 bytes bin/main/dev/loki/config/MessagesConfig.class | Bin 6999 -> 0 bytes .../dev/loki/config/SkillCheckConfig.class | Bin 4548 -> 0 bytes bin/main/dev/loki/core/GameEventBus.class | Bin 2679 -> 0 bytes bin/main/dev/loki/core/GameManager.class | Bin 5478 -> 0 bytes .../core/GameSession$PlayerJoinEvent.class | Bin 1427 -> 0 bytes .../core/GameSession$PlayerLeaveEvent.class | Bin 1432 -> 0 bytes bin/main/dev/loki/core/GameSession.class | Bin 8309 -> 0 bytes bin/main/dev/loki/core/GameState.class | Bin 1452 -> 0 bytes bin/main/dev/loki/damage/AttackListener.class | Bin 3586 -> 0 bytes bin/main/dev/loki/damage/DamageHandler.class | Bin 3805 -> 0 bytes bin/main/dev/loki/data/DataStorage.class | Bin 499 -> 0 bytes .../dev/loki/data/GeneratorDataManager.class | Bin 5925 -> 0 bytes bin/main/dev/loki/data/MatchResult$Role.class | Bin 1115 -> 0 bytes bin/main/dev/loki/data/MatchResult.class | Bin 1354 -> 0 bytes bin/main/dev/loki/data/PlayerStats.class | Bin 2131 -> 0 bytes bin/main/dev/loki/data/SQLiteStorage.class | Bin 7559 -> 0 bytes bin/main/dev/loki/data/YamlStorage.class | Bin 6362 -> 0 bytes .../dev/loki/gate/ExitGate$GateState.class | Bin 1180 -> 0 bytes bin/main/dev/loki/gate/ExitGate.class | Bin 3813 -> 0 bytes bin/main/dev/loki/gate/GateManager.class | Bin 4684 -> 0 bytes .../gate/GateOpening$OpeningProgress.class | Bin 661 -> 0 bytes .../loki/gate/GateOpening$OpeningTask.class | Bin 2265 -> 0 bytes bin/main/dev/loki/gate/GateOpening.class | Bin 5102 -> 0 bytes .../dev/loki/hatch/Hatch$HatchState.class | Bin 1169 -> 0 bytes bin/main/dev/loki/hatch/Hatch.class | Bin 4169 -> 0 bytes bin/main/dev/loki/hatch/HatchCondition.class | Bin 3904 -> 0 bytes bin/main/dev/loki/hatch/HatchEscape.class | Bin 3644 -> 0 bytes bin/main/dev/loki/hook/Hook.class | Bin 2559 -> 0 bytes bin/main/dev/loki/hook/HookManager.class | Bin 7441 -> 0 bytes .../loki/hook/HookRescue$RescueSession.class | Bin 1547 -> 0 bytes bin/main/dev/loki/hook/HookRescue.class | Bin 7375 -> 0 bytes bin/main/dev/loki/hook/HookSabotage$1.class | Bin 2656 -> 0 bytes bin/main/dev/loki/hook/HookSabotage$2.class | Bin 1434 -> 0 bytes bin/main/dev/loki/hook/HookSabotage.class | Bin 5419 -> 0 bytes bin/main/dev/loki/hook/HookSacrifice.class | Bin 4503 -> 0 bytes bin/main/dev/loki/hook/HookStage.class | Bin 1730 -> 0 bytes bin/main/dev/loki/hook/HookStruggle.class | Bin 5641 -> 0 bytes bin/main/dev/loki/item/BaseItem.class | Bin 463 -> 0 bytes bin/main/dev/loki/item/ChestLoot.class | Bin 2118 -> 0 bytes bin/main/dev/loki/item/DBDItems.class | Bin 7898 -> 0 bytes bin/main/dev/loki/item/ItemFlashlight.class | Bin 4510 -> 0 bytes bin/main/dev/loki/item/ItemMedkit.class | Bin 4470 -> 0 bytes bin/main/dev/loki/item/ItemType.class | Bin 1593 -> 0 bytes .../dev/loki/item/ItemUseListener$1.class | Bin 3776 -> 0 bytes bin/main/dev/loki/item/ItemUseListener.class | Bin 8894 -> 0 bytes .../dev/loki/killer/GeneratorKick$1.class | Bin 2693 -> 0 bytes .../dev/loki/killer/GeneratorKick$2.class | Bin 838 -> 0 bytes bin/main/dev/loki/killer/GeneratorKick.class | Bin 6005 -> 0 bytes bin/main/dev/loki/killer/HitValidator.class | Bin 3470 -> 0 bytes bin/main/dev/loki/killer/KillerAttack.class | Bin 7010 -> 0 bytes .../loki/killer/KillerCarry$CarryData.class | Bin 771 -> 0 bytes bin/main/dev/loki/killer/KillerCarry.class | Bin 10655 -> 0 bytes .../dev/loki/killer/KillerController.class | Bin 3915 -> 0 bytes bin/main/dev/loki/killer/KillerMovement.class | Bin 5205 -> 0 bytes bin/main/dev/loki/killer/KillerVision.class | Bin 3652 -> 0 bytes .../dev/loki/listener/DamageListener.class | Bin 4451 -> 0 bytes .../listener/GeneratorSelectListener.class | Bin 3019 -> 0 bytes .../listener/PlayerInteractListener.class | Bin 10448 -> 0 bytes .../loki/listener/PlayerJumpListener.class | Bin 5278 -> 0 bytes .../loki/listener/PlayerMoveListener.class | Bin 6649 -> 0 bytes .../loki/listener/PlayerQuitListener.class | Bin 6001 -> 0 bytes .../listener/SetupBlockBreakListener.class | Bin 1880 -> 0 bytes bin/main/dev/loki/map/MapBuilder.class | Bin 7240 -> 0 bytes bin/main/dev/loki/map/MapTemplate.class | Bin 5621 -> 0 bytes .../loki/map/TemplateManager$PresetMap.class | Bin 1681 -> 0 bytes bin/main/dev/loki/map/TemplateManager.class | Bin 5938 -> 0 bytes bin/main/dev/loki/mdbd.class | Bin 6774 -> 0 bytes bin/main/dev/loki/mdbdBootstrap.class | Bin 541 -> 0 bytes bin/main/dev/loki/mdbdLoader.class | Bin 534 -> 0 bytes bin/main/dev/loki/objective/Generator.class | Bin 3986 -> 0 bytes .../dev/loki/objective/GeneratorManager.class | Bin 5264 -> 0 bytes .../loki/objective/GeneratorRegression.class | Bin 2300 -> 0 bytes .../GeneratorRepair$RepairSession.class | Bin 718 -> 0 bytes .../dev/loki/objective/GeneratorRepair.class | Bin 11360 -> 0 bytes .../objective/SkillCheck$CheckState.class | Bin 1990 -> 0 bytes bin/main/dev/loki/objective/SkillCheck.class | Bin 4052 -> 0 bytes .../dev/loki/objective/SkillCheckUI.class | Bin 4797 -> 0 bytes .../dev/loki/pallet/Pallet$PalletState.class | Bin 1196 -> 0 bytes bin/main/dev/loki/pallet/Pallet.class | Bin 3615 -> 0 bytes .../loki/pallet/PalletBreak$BreakTask.class | Bin 1786 -> 0 bytes .../pallet/PalletBreak$BreakingProgress.class | Bin 846 -> 0 bytes bin/main/dev/loki/pallet/PalletBreak.class | Bin 3964 -> 0 bytes bin/main/dev/loki/pallet/PalletDrop.class | Bin 4376 -> 0 bytes bin/main/dev/loki/pallet/PalletManager.class | Bin 3730 -> 0 bytes bin/main/dev/loki/pallet/PalletStun$1.class | Bin 1254 -> 0 bytes bin/main/dev/loki/pallet/PalletStun.class | Bin 3184 -> 0 bytes bin/main/dev/loki/phase/EndgamePhase$1.class | Bin 2350 -> 0 bytes bin/main/dev/loki/phase/EndgamePhase.class | Bin 11001 -> 0 bytes bin/main/dev/loki/phase/GameplayPhase.class | Bin 13554 -> 0 bytes bin/main/dev/loki/phase/LobbyPhase.class | Bin 6082 -> 0 bytes bin/main/dev/loki/phase/Phase.class | Bin 521 -> 0 bytes bin/main/dev/loki/phase/RoleAssignPhase.class | Bin 1858 -> 0 bytes bin/main/dev/loki/player/BasePlayer.class | Bin 1692 -> 0 bytes bin/main/dev/loki/player/Killer.class | Bin 630 -> 0 bytes bin/main/dev/loki/player/PlayerManager.class | Bin 6803 -> 0 bytes bin/main/dev/loki/player/PlayerState.class | Bin 1775 -> 0 bytes bin/main/dev/loki/player/Survivor.class | Bin 791 -> 0 bytes .../role/RoleAssigner$RoleAssignedEvent.class | Bin 1610 -> 0 bytes bin/main/dev/loki/role/RoleAssigner.class | Bin 8242 -> 0 bytes bin/main/dev/loki/role/RoleQueue.class | Bin 2192 -> 0 bytes bin/main/dev/loki/role/SpawnPosition.class | Bin 1264 -> 0 bytes bin/main/dev/loki/sound/GeneratorSound.class | Bin 3856 -> 0 bytes bin/main/dev/loki/sound/SoundLevels.class | Bin 1628 -> 0 bytes bin/main/dev/loki/sound/SoundManager.class | Bin 3764 -> 0 bytes .../dev/loki/sound/TerrorRadiusSound.class | Bin 3607 -> 0 bytes bin/main/dev/loki/state/StateHandler.class | Bin 3959 -> 0 bytes bin/main/dev/loki/state/StateMachine.class | Bin 4046 -> 0 bytes bin/main/dev/loki/state/StateTransition.class | Bin 2391 -> 0 bytes .../loki/survivor/SurvivorController.class | Bin 2907 -> 0 bytes .../dev/loki/survivor/SurvivorHealing.class | Bin 6297 -> 0 bytes .../dev/loki/survivor/SurvivorMovement.class | Bin 2948 -> 0 bytes bin/main/dev/loki/ui/ActionBar.class | Bin 6705 -> 0 bytes bin/main/dev/loki/ui/BossBarManager$1.class | Bin 625 -> 0 bytes bin/main/dev/loki/ui/BossBarManager.class | Bin 7318 -> 0 bytes bin/main/dev/loki/ui/ProgressBar.class | Bin 3358 -> 0 bytes bin/main/dev/loki/ui/Sidebar.class | Bin 14370 -> 0 bytes bin/main/dev/loki/ui/StatusIcons.class | Bin 2337 -> 0 bytes .../dev/loki/ui/TitleUI$SkillCheckState.class | Bin 1972 -> 0 bytes bin/main/dev/loki/ui/TitleUI.class | Bin 7623 -> 0 bytes bin/main/dev/loki/util/LocationUtil.class | Bin 5507 -> 0 bytes bin/main/dev/loki/util/MathUtil.class | Bin 4573 -> 0 bytes bin/main/dev/loki/util/ParticleUtil.class | Bin 5937 -> 0 bytes bin/main/dev/loki/util/PlayerUtil.class | Bin 7267 -> 0 bytes bin/main/dev/loki/util/TextUtil.class | Bin 1068 -> 0 bytes bin/main/dev/loki/util/TimeUtil.class | Bin 4581 -> 0 bytes .../loki/window/Window$PlayerContext.class | Bin 1643 -> 0 bytes bin/main/dev/loki/window/Window.class | Bin 2216 -> 0 bytes .../WindowFastVault$FastVaultTask.class | Bin 1733 -> 0 bytes .../dev/loki/window/WindowFastVault.class | Bin 4414 -> 0 bytes bin/main/dev/loki/window/WindowManager.class | Bin 4051 -> 0 bytes .../loki/window/WindowVault$VaultTask.class | Bin 960 -> 0 bytes bin/main/dev/loki/window/WindowVault.class | Bin 4343 -> 0 bytes bin/main/dev/loki/world/LobbyManager.class | Bin 5324 -> 0 bytes .../dev/loki/world/VoidWorldGenerator.class | Bin 980 -> 0 bytes bin/main/game.yml | 260 ------------------ bin/main/locations.yml | 58 ---- bin/main/messages.yml | 119 -------- bin/main/plugin.yml | 26 -- bin/main/skillcheck.yml | 120 -------- 150 files changed, 632 deletions(-) delete mode 100644 bin/main/config.yml delete mode 100644 bin/main/dev/loki/chest/Chest.class delete mode 100644 bin/main/dev/loki/chest/ChestManager.class delete mode 100644 bin/main/dev/loki/chest/ChestOpening$1.class delete mode 100644 bin/main/dev/loki/chest/ChestOpening.class delete mode 100644 bin/main/dev/loki/command/DBDAdminCommand.class delete mode 100644 bin/main/dev/loki/command/DBDCommand.class delete mode 100644 bin/main/dev/loki/command/SetupCommand.class delete mode 100644 bin/main/dev/loki/config/ConfigManager.class delete mode 100644 bin/main/dev/loki/config/GameConfig.class delete mode 100644 bin/main/dev/loki/config/LocationsConfig.class delete mode 100644 bin/main/dev/loki/config/MessagesConfig.class delete mode 100644 bin/main/dev/loki/config/SkillCheckConfig.class delete mode 100644 bin/main/dev/loki/core/GameEventBus.class delete mode 100644 bin/main/dev/loki/core/GameManager.class delete mode 100644 bin/main/dev/loki/core/GameSession$PlayerJoinEvent.class delete mode 100644 bin/main/dev/loki/core/GameSession$PlayerLeaveEvent.class delete mode 100644 bin/main/dev/loki/core/GameSession.class delete mode 100644 bin/main/dev/loki/core/GameState.class delete mode 100644 bin/main/dev/loki/damage/AttackListener.class delete mode 100644 bin/main/dev/loki/damage/DamageHandler.class delete mode 100644 bin/main/dev/loki/data/DataStorage.class delete mode 100644 bin/main/dev/loki/data/GeneratorDataManager.class delete mode 100644 bin/main/dev/loki/data/MatchResult$Role.class delete mode 100644 bin/main/dev/loki/data/MatchResult.class delete mode 100644 bin/main/dev/loki/data/PlayerStats.class delete mode 100644 bin/main/dev/loki/data/SQLiteStorage.class delete mode 100644 bin/main/dev/loki/data/YamlStorage.class delete mode 100644 bin/main/dev/loki/gate/ExitGate$GateState.class delete mode 100644 bin/main/dev/loki/gate/ExitGate.class delete mode 100644 bin/main/dev/loki/gate/GateManager.class delete mode 100644 bin/main/dev/loki/gate/GateOpening$OpeningProgress.class delete mode 100644 bin/main/dev/loki/gate/GateOpening$OpeningTask.class delete mode 100644 bin/main/dev/loki/gate/GateOpening.class delete mode 100644 bin/main/dev/loki/hatch/Hatch$HatchState.class delete mode 100644 bin/main/dev/loki/hatch/Hatch.class delete mode 100644 bin/main/dev/loki/hatch/HatchCondition.class delete mode 100644 bin/main/dev/loki/hatch/HatchEscape.class delete mode 100644 bin/main/dev/loki/hook/Hook.class delete mode 100644 bin/main/dev/loki/hook/HookManager.class delete mode 100644 bin/main/dev/loki/hook/HookRescue$RescueSession.class delete mode 100644 bin/main/dev/loki/hook/HookRescue.class delete mode 100644 bin/main/dev/loki/hook/HookSabotage$1.class delete mode 100644 bin/main/dev/loki/hook/HookSabotage$2.class delete mode 100644 bin/main/dev/loki/hook/HookSabotage.class delete mode 100644 bin/main/dev/loki/hook/HookSacrifice.class delete mode 100644 bin/main/dev/loki/hook/HookStage.class delete mode 100644 bin/main/dev/loki/hook/HookStruggle.class delete mode 100644 bin/main/dev/loki/item/BaseItem.class delete mode 100644 bin/main/dev/loki/item/ChestLoot.class delete mode 100644 bin/main/dev/loki/item/DBDItems.class delete mode 100644 bin/main/dev/loki/item/ItemFlashlight.class delete mode 100644 bin/main/dev/loki/item/ItemMedkit.class delete mode 100644 bin/main/dev/loki/item/ItemType.class delete mode 100644 bin/main/dev/loki/item/ItemUseListener$1.class delete mode 100644 bin/main/dev/loki/item/ItemUseListener.class delete mode 100644 bin/main/dev/loki/killer/GeneratorKick$1.class delete mode 100644 bin/main/dev/loki/killer/GeneratorKick$2.class delete mode 100644 bin/main/dev/loki/killer/GeneratorKick.class delete mode 100644 bin/main/dev/loki/killer/HitValidator.class delete mode 100644 bin/main/dev/loki/killer/KillerAttack.class delete mode 100644 bin/main/dev/loki/killer/KillerCarry$CarryData.class delete mode 100644 bin/main/dev/loki/killer/KillerCarry.class delete mode 100644 bin/main/dev/loki/killer/KillerController.class delete mode 100644 bin/main/dev/loki/killer/KillerMovement.class delete mode 100644 bin/main/dev/loki/killer/KillerVision.class delete mode 100644 bin/main/dev/loki/listener/DamageListener.class delete mode 100644 bin/main/dev/loki/listener/GeneratorSelectListener.class delete mode 100644 bin/main/dev/loki/listener/PlayerInteractListener.class delete mode 100644 bin/main/dev/loki/listener/PlayerJumpListener.class delete mode 100644 bin/main/dev/loki/listener/PlayerMoveListener.class delete mode 100644 bin/main/dev/loki/listener/PlayerQuitListener.class delete mode 100644 bin/main/dev/loki/listener/SetupBlockBreakListener.class delete mode 100644 bin/main/dev/loki/map/MapBuilder.class delete mode 100644 bin/main/dev/loki/map/MapTemplate.class delete mode 100644 bin/main/dev/loki/map/TemplateManager$PresetMap.class delete mode 100644 bin/main/dev/loki/map/TemplateManager.class delete mode 100644 bin/main/dev/loki/mdbd.class delete mode 100644 bin/main/dev/loki/mdbdBootstrap.class delete mode 100644 bin/main/dev/loki/mdbdLoader.class delete mode 100644 bin/main/dev/loki/objective/Generator.class delete mode 100644 bin/main/dev/loki/objective/GeneratorManager.class delete mode 100644 bin/main/dev/loki/objective/GeneratorRegression.class delete mode 100644 bin/main/dev/loki/objective/GeneratorRepair$RepairSession.class delete mode 100644 bin/main/dev/loki/objective/GeneratorRepair.class delete mode 100644 bin/main/dev/loki/objective/SkillCheck$CheckState.class delete mode 100644 bin/main/dev/loki/objective/SkillCheck.class delete mode 100644 bin/main/dev/loki/objective/SkillCheckUI.class delete mode 100644 bin/main/dev/loki/pallet/Pallet$PalletState.class delete mode 100644 bin/main/dev/loki/pallet/Pallet.class delete mode 100644 bin/main/dev/loki/pallet/PalletBreak$BreakTask.class delete mode 100644 bin/main/dev/loki/pallet/PalletBreak$BreakingProgress.class delete mode 100644 bin/main/dev/loki/pallet/PalletBreak.class delete mode 100644 bin/main/dev/loki/pallet/PalletDrop.class delete mode 100644 bin/main/dev/loki/pallet/PalletManager.class delete mode 100644 bin/main/dev/loki/pallet/PalletStun$1.class delete mode 100644 bin/main/dev/loki/pallet/PalletStun.class delete mode 100644 bin/main/dev/loki/phase/EndgamePhase$1.class delete mode 100644 bin/main/dev/loki/phase/EndgamePhase.class delete mode 100644 bin/main/dev/loki/phase/GameplayPhase.class delete mode 100644 bin/main/dev/loki/phase/LobbyPhase.class delete mode 100644 bin/main/dev/loki/phase/Phase.class delete mode 100644 bin/main/dev/loki/phase/RoleAssignPhase.class delete mode 100644 bin/main/dev/loki/player/BasePlayer.class delete mode 100644 bin/main/dev/loki/player/Killer.class delete mode 100644 bin/main/dev/loki/player/PlayerManager.class delete mode 100644 bin/main/dev/loki/player/PlayerState.class delete mode 100644 bin/main/dev/loki/player/Survivor.class delete mode 100644 bin/main/dev/loki/role/RoleAssigner$RoleAssignedEvent.class delete mode 100644 bin/main/dev/loki/role/RoleAssigner.class delete mode 100644 bin/main/dev/loki/role/RoleQueue.class delete mode 100644 bin/main/dev/loki/role/SpawnPosition.class delete mode 100644 bin/main/dev/loki/sound/GeneratorSound.class delete mode 100644 bin/main/dev/loki/sound/SoundLevels.class delete mode 100644 bin/main/dev/loki/sound/SoundManager.class delete mode 100644 bin/main/dev/loki/sound/TerrorRadiusSound.class delete mode 100644 bin/main/dev/loki/state/StateHandler.class delete mode 100644 bin/main/dev/loki/state/StateMachine.class delete mode 100644 bin/main/dev/loki/state/StateTransition.class delete mode 100644 bin/main/dev/loki/survivor/SurvivorController.class delete mode 100644 bin/main/dev/loki/survivor/SurvivorHealing.class delete mode 100644 bin/main/dev/loki/survivor/SurvivorMovement.class delete mode 100644 bin/main/dev/loki/ui/ActionBar.class delete mode 100644 bin/main/dev/loki/ui/BossBarManager$1.class delete mode 100644 bin/main/dev/loki/ui/BossBarManager.class delete mode 100644 bin/main/dev/loki/ui/ProgressBar.class delete mode 100644 bin/main/dev/loki/ui/Sidebar.class delete mode 100644 bin/main/dev/loki/ui/StatusIcons.class delete mode 100644 bin/main/dev/loki/ui/TitleUI$SkillCheckState.class delete mode 100644 bin/main/dev/loki/ui/TitleUI.class delete mode 100644 bin/main/dev/loki/util/LocationUtil.class delete mode 100644 bin/main/dev/loki/util/MathUtil.class delete mode 100644 bin/main/dev/loki/util/ParticleUtil.class delete mode 100644 bin/main/dev/loki/util/PlayerUtil.class delete mode 100644 bin/main/dev/loki/util/TextUtil.class delete mode 100644 bin/main/dev/loki/util/TimeUtil.class delete mode 100644 bin/main/dev/loki/window/Window$PlayerContext.class delete mode 100644 bin/main/dev/loki/window/Window.class delete mode 100644 bin/main/dev/loki/window/WindowFastVault$FastVaultTask.class delete mode 100644 bin/main/dev/loki/window/WindowFastVault.class delete mode 100644 bin/main/dev/loki/window/WindowManager.class delete mode 100644 bin/main/dev/loki/window/WindowVault$VaultTask.class delete mode 100644 bin/main/dev/loki/window/WindowVault.class delete mode 100644 bin/main/dev/loki/world/LobbyManager.class delete mode 100644 bin/main/dev/loki/world/VoidWorldGenerator.class delete mode 100644 bin/main/game.yml delete mode 100644 bin/main/locations.yml delete mode 100644 bin/main/messages.yml delete mode 100644 bin/main/plugin.yml delete mode 100644 bin/main/skillcheck.yml diff --git a/bin/main/config.yml b/bin/main/config.yml deleted file mode 100644 index ec91e1e..0000000 --- a/bin/main/config.yml +++ /dev/null @@ -1,49 +0,0 @@ -# ============================================ -# Mdbd Plugin - Главный конфиг -# Версия: ${version} -# ============================================ - -# Основные настройки плагина -settings: - # Язык сообщений (пока только встроенный) - language: "ru" - - # Отладочный режим - debug: false - - # Автосохранение каждые X минут - auto-save-minutes: 5 - -# Настройки игры -game: - # Минимум игроков для старта - min-players: 5 - - # Максимум игроков - max-players: 5 - - # Обратный отсчёт в лобби (секунды) - lobby-countdown: 60 - - # Задержка перед назначением ролей (секунды) - role-assign-delay: 5 - -# Визуальные настройки -display: - # Использовать титры при старте игры - use-title-on-start: true - - # Показывать ActionBar с прогрессом - use-action-bar: true - - # Показывать Scoreboard (боковую панель) - use-sidebar: true - - # Формат прогресс-бара - progress-bar: - length: 20 - filled: "█" - empty: "░" - # Цвета в формате &#rrggbb - color-filled: "�FF00" - color-empty: "&#FF0000" diff --git a/bin/main/dev/loki/chest/Chest.class b/bin/main/dev/loki/chest/Chest.class deleted file mode 100644 index 3bc1cc2201e6859200dbbd07fcb16da2a01e33b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2824 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 diff --git a/bin/main/dev/loki/chest/ChestOpening$1.class b/bin/main/dev/loki/chest/ChestOpening$1.class deleted file mode 100644 index 8514edeccbe167b550755bb538a3dda24b63319d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2995 zcmbVO-*XdH6#i~gl8`R6#DYMn6fBZPU_k|h6sS#$6xsr9DFT9QlWSSB-Hp4OO8p5c zf`TZDs4(N`laGqhTF~*q8DE@nCOrD;jQ@cTI?gbDHwh3R^;a^x_w2proO|wfzCCAu zyngjN0FU8f2vq`&X*sG}PR7(zhotB0Np;_zm9}XQH?InzTHt=i9oC0(nT+Y{9<|ar zOS*b{VWKZ*+s2S31*Z9CD&q-=E`gwb$n=_5(tG#cxK9W~Mh&YuYZ+tG6`0>$wvn`b z(;w4!6xOIYU1=6V6qr-dE0wfc?z++fb=`-JQA5x9rls%N)zv|bV5@1H{zid=v5HPg zCr?ZrN=388ojbJ*3REYZw44rsdo+X)R?=(@(-Be9y&7tuDQTXD8JHPC01X;yu|OaY zYZ+84_i31hpg?W6Y0KW+$dGggieN{(os?k>8m_6HOOw?Kb%BKyBfObXf)H?Xb`6$b zX$TJp%$*8#4KcI`giUX|Z83sEV0$BY5X(bYCQx4~w;EPJXSzIDV3A}Rs$+ZAc~;@! z5FQd}sAN_OPs1ZvEilta`R1rBP4Y~&W%%|O*+dQ2VqFN23e32bVlHS{50zzCjyR(X z_<>l_&@${{ef!X1ner1YcTYtK_67|b75KrFVW*^}@M+WdnzRel3`<`D?wgLy%*9&D z*>Phb5o`?EY`YM7s|IA@noGDJ_%ENY=3#h=yHIPur&`?wi&qGeEJ?MV&$ z6$ffkmgC7m)5{qoLLZ*ea1aJ-oE*veV*+tf;6DVG(vVhx%}{|oMru2DyWs}gnhJD5 zu&wuou%{@5VKG_1oIe?Xjcf=GYgvKk1s)e+)bI>gG)eWWG>G)EQf12(M) z0a_!h7%yu$ier5LQ>2$A{Tn4g;Nja|rrWzk#RA9_6RoFB%ThHdkWCSo8U4PI%CK&f zDrltN$+;=H*;EZ}R(UI2p+I09owlL|S==N2Lrz-58+em_hxoZSy5|3ijqIpvcO2jI zT_aoc?M3hw-VWi6K=Z8>nD(fXk$N$`#T;&CwRGGumE3m(J}d{nq+N8l#jw+s^qRXJ zCzH#TT2>jO%4cpf92m>W^2HLj_T61b%Nba5ku)r;-}GgoHi*+#*xBNEKAPA80%V?IAA2rPSEqV5$EfPqg^~TbFtS@ytBO}G>S#BM(oQ}r+lBE5 z#}SP$8%KS7`8ejp=T(nmZv1P^j|axlc&T8xkoTE|?N(zR*5E#@W&ogj!TUli!eWm6 z@WO(kd+`mb`3L@pUq<~EGz(n7BFb|D6Nqz+UdBoebFW}c6?Vrb(0WO&@}l-8wrV6N z(0Ku!Y9`wCCALjs=N0U(f>J9vnKOZXe7wUK4JL8m3Wlg#@Vn$M0wYmx0q>1hkpm_%R`f^f z#-{uVS5IRrE@B%#VL$yGJ@^W}_<`e3Y?D7@2Y#jXZ!BoPW1x_jcoF zPq@QDN>%i-6|YhX;5A04ArSu)yRRcB1iJ=~bFK=n;{?ZQmbH^OMJY@VXL-Ggb9{{h}5`1xeBZP0+a(mV*mgE diff --git a/bin/main/dev/loki/chest/ChestOpening.class b/bin/main/dev/loki/chest/ChestOpening.class deleted file mode 100644 index 301340150553ec8af40547801ae20b4c1fe1ddaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6236 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 HOC|pUP8pCX diff --git a/bin/main/dev/loki/command/DBDCommand.class b/bin/main/dev/loki/command/DBDCommand.class deleted file mode 100644 index 7f9af97ae439af4e09aed26095d1a631841a3bc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13871 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 diff --git a/bin/main/dev/loki/config/ConfigManager.class b/bin/main/dev/loki/config/ConfigManager.class deleted file mode 100644 index c4a4d5cea5c1bcb294331fec5af09020ed86b860..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5417 zcmb7IiF*^r75|N|mE{FH<_HD?25e%>HVQYfl7JDIqdou=6G9uhme#Vcq*bMr4L#DP z^gfbaX=&P|XX@UCG!_(^kY1!s@B6;*>mTUXFZ4IFE3IrRp?vbUvorJFoA-Y2n74lB z*^5sC=)u1=R0!M@H79}zYdju|SgFx?EErZpzmYOxW=2DmK*I@R!U!geR4h0+a>9(* z0yXJGE*4J-)b|znlhKiANWdR8Y@^poM9qxA{657Sw}QR#gvs6dgcULDxRuH}=LoFw zB)A&%%_NaBV@A>}Ff51Dfa1_s^gpPeXP*o=Akp%*c4*l+|;% zhGx-7y^=;eRp40PXJul+k=*!r+;+jtWt6SKQ5vrhaA@6S3aGg)o{HOd2sE~N=P4lD zhXty_R@C&P5;y8tfF%NzZSBLg5Ll|C8Z~|_#|jNM3Cx?}1RX2U%*B{#?<(;{LtFby zZ%9e2b!hPU(So%aS_Sk{f9bdxZB)`c8PD2Tb^P6uG@zqHZ6wE|@eDWW`{F5cAeS65 zGlz|lgh_j(6BENmCNAghVwF7>C-q9t)JU0_BP{cVY$Gz>Z=_wux`bs!9qh6`Y$Wgw z~3?+Re?KXXX2??sQtQqBtg1W#|>!IK+RSbk#<#|6|6qo zPW6jH?kL!e?b3le1U9u@w*rpGcj~BxU&Agsf3^x<`1{Z+;FHPX92~}WssBD5b|WI_6=%hC>3)vxUq~4Id6O5miz}WKubT4myI4=%`17 z4Bn$U?#3~JT1IN06=S^-SYC+IoE=ZFFvVDAVnJs&umbrn@ES+seo3pt{gb6*G zOC(PDaU6z*7Yi&=fm}w2juAwdTk+JWC9tSmkTCV;XN?K7hc!V3Xx5KzjOvJC%+c0a z7T8E_uQ%&uz@E@Cjsyc%9#at3TSk}bmfk+>M;N1i?3a&&^3j5q$nYb$YupnG^|(xe zkX^vmk;8<*f=I?RY;%`6YUC1jLC=De(!`osS=xs+oD^s(6q9|abk1f9nnv=FNvCC` zQZLo`X?c(M@hZGp!+lg%omM1~ z7fx2kX}pHsOqr7f$LjyYBo7rj$hILg=(s>SQ@1`V(0Emk}{GG=75rX6Gn zOGS-LH0;c&${X<}f$BRC_a5KIEcVVSaJZBqKPK@O>9My8Z16l*VnFD*nWg_9z}q#v zO(6LEp?TCuy7BE^NIKqucM9C#RZ(|CAnfVkc<`E~bdGdo*MmCVEpM{wNW#kUZaagA zG`zRqJQY!g$1>KWyft*Z5ASC+HKNg>Tsoa$lABS6LTQ>5i9_wfjcjWk(eVL%P~gU- zF)kB}&Bl?qJ;t{z{UI;0wWaLEYeBiMG@xZA`LK?U$XcOI8krQ!kVN)T3DU;|dOSc> zYjdqSFc%IDA1~O=c;7d;`((saA$G+7jWiz#b3JQaN6rOOu0T)6|n2YTqv_%M&`Dl>Ny(r+f{VlhQ?gJcS1}e5n+4 zPvb_Gy+?TWG0K#&4*GuE$PfX^E>Izxml7a7W`_3H@r;IVTr=mSB&UuRbMBk?7EzEF z0aMRIK~k!qu8?}wMASt@1=U^Y_RzATx6kROX0;^jS~N1rE`j%d8G5gOAgOeCp(kK_ zScbf?>zF|n*=TwlfIv$bCU1WRTYpLa>>pCVJ6Jb5WbS9kI++8E)SZ@PXYGuU?l|gt{WaMj|m3x6M#}4Swmv9|YRMRxS~3 zPFZ%dO!4N3a(*+fj;?K;&7-6rVSn7+EPVJAuM&^i33!)Y?f->o=cRp1uB*F#(-VTA^vkp)y_ zJ(jrYJWN8twPS%m_H&_6EeuR! zkP8R7Fr*gloW?LMXv*WR#uw&skF=sfS+Ro1fr$FCn%b}7S_^JRD+aKZ&GgO665Ub9 zwL~CVRMjFDQq|4Wjq-c)F!P90FHZL6kyMjDP6qQxsmTy0!+BVocuFj$#Xx``1RVsj zQysgB$4MBS!#BH!SI7@D2Pcsw^wRmKFQMfq#jff&k92>h@>gx3gD+VzAiAqAVe%*^ zrz)SoD=y%bkKwiF@#gO8rs@m0zp45Pd`;DPyzA_M_uh56yQ=GH)HYQOOrgH3sp?VG z@|nkbx-Jj!B#C3kMLZ1T@uAKO_~=<0umvIXQk|99jUkS`e9Cbt=SfU)o>Zd~JsVVf zuBXWx7>654wVCK|VHj*yCWf$$d|R=HV+yz8UVbr1I5sJ$P8Xx(@HfRBnVYLsHP}w79YnW>^PP<8FnM;f59@`6 zy(MU-i)g0t6@?~k!dDfV_4LixaE0d_X9e-lyalz-qO}0tQ&oM}0Iq?U@e|EK4);@D z74>ZGEREefo}R+Ok^uX*YpzVO1{SP>d5wy>k8AxjZ-6O#K$#P8gci+db%TQk;X5pR z6{IdTg8#7_qEn@A-^KS_-GUtDfz@i6pT VNA>(O{>mNs_4_yc1OGzP{{WIRdF%iH diff --git a/bin/main/dev/loki/config/GameConfig.class b/bin/main/dev/loki/config/GameConfig.class deleted file mode 100644 index f328d7f9834ce230db563c4075a49cabdc44bd2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11721 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 k;4h}LG5)BcA)i;#M@f%W!7hg8=f2wkrqyPW_ diff --git a/bin/main/dev/loki/config/LocationsConfig.class b/bin/main/dev/loki/config/LocationsConfig.class deleted file mode 100644 index bd911d010243a27e31f1fa5488cab81ee97a3938..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7800 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 Lafw(WTB!Vgt0X&x diff --git a/bin/main/dev/loki/config/SkillCheckConfig.class b/bin/main/dev/loki/config/SkillCheckConfig.class deleted file mode 100644 index d162c855efa56ed0d7bcf3df39004d4128ccbd41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4548 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 diff --git a/bin/main/dev/loki/core/GameManager.class b/bin/main/dev/loki/core/GameManager.class deleted file mode 100644 index b533ad992e82d1b820342b7f32d0957623d1c59f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5478 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 diff --git a/bin/main/dev/loki/core/GameSession$PlayerJoinEvent.class b/bin/main/dev/loki/core/GameSession$PlayerJoinEvent.class deleted file mode 100644 index fc4d24644c1087bdfbc80de4af993a6103f2d8b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1427 zcmb7ETTc@~7(D~D+t$@W1rbH?Qlwp!^?pf>7w`h6A`!xaK26®#>9XWE4S;i z3@yrr$bunfB84s|5Qij1&c{vatGf}`9hWTTOFH`Bn#};=L!&oU1 z_S@RFsOw7keV~2L#5m3~JUxzfFER4=$nhNgm|;4hb+l9EjT{CsZDJA^!yGrL?QewM zl8sgF(|l;*Q^>hB+4Ae+r4#gJI59W#K?4X{kWwq{^Jc_VIb21_z%2Riw#aXJ+SwI$ zlyhupq6~{6Tl=HHu%9fDb}#| z(oa$rU9MCTh&4VO6-j#kYf|F&<Jlz|%z69>C;cnoRoqn$}? z-ff1NZqfSWZ{RL%T7OfTgs50F%qv3aC8;!F(LUoQE#M#x9xYq2g>*~NJq3fF8G4(c zlLe^t1=-JZ8Ndm8rbF;2%n$)aXx~o7lv%O~D2CNR9ym;*@*I!~INgIZ3VaGpx}K7x zah#1wCGs>tmKkfVgNc4D`d#4y*#;?DF)L?%!<04m71{lNdb>nlQb9d}x?B#;uAoS# oNg>Qp+`&CM?}rQ<59rL$*RaCB0bBZ7qyPW_ diff --git a/bin/main/dev/loki/core/GameSession$PlayerLeaveEvent.class b/bin/main/dev/loki/core/GameSession$PlayerLeaveEvent.class deleted file mode 100644 index 3081fd109dd97741b832782bd5903270994cd708..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1432 zcmb7ETTc^F5dIF(Zd+Fi6+{%p3rM>t>-~}%Bj5#+ibMzx`gGb(U}4!)_iUT+pL~!+ zW5RN{`j^39l#u(80ZtQn$)pfwe8pq<&*td?$9b} z?I>?@#g)6{*GP8gWrw`Lz<|Kumh4E|mEMN^ju_Gu$hIO!f$`b_S!}ZBrKXssDsZ`6 z>FqGEpqiA2K*2-?S%G5B@o2fdQzw5-)?E@P)l@^e>(Y0^_r#bB)N0^6-iE+1$LMAl zTdO6mchJOX3<*3hcXRk}#nofT1ag~FZ-%J~^p`73A^V7l63z+OCu3h?@#te)x>{hQ zoJ#y{eTy1FwemhBzhGh%7X{`{M1C9_hkNRHPVh`%B1LwzS(Wty`Y~Z*99N<$*SYg= zDA-iZ73uSg1mtthg;mw|8}!NvTQiuNo!PJlY?@ap(19;oF;*9F17!o#9KYKozwHIi z4%u$D-^_;8dY9sRFaN%~jJVk(DBk?RmJmpqUBh@G^7+X7<;>vDJ!S-N;_ z(%W}WV5+NH4*?83;BD*e%A*jg#q+#OI#^UXU|YP?xWh}>&!fi+7j7coGJMa#;Af8C zruY=0)%t?`XTJ2|6hE_(@h8m40u1raok<|m>=Qx^Yad16Fo^Xz0F`j|7|<~ADRSvX zN`ppmJ^__EQXhNfteJg`^+NG43zyh8EXhhx1?w9wTQgsg-}`5@tNbMs>JjR4Epoe# qNj^0wKMbk&b_(!yalX(kaOQz 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 diff --git a/bin/main/dev/loki/core/GameState.class b/bin/main/dev/loki/core/GameState.class deleted file mode 100644 index 2ef79f414622223a349e8af49ac1b49ef650b707..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1452 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 c+yB7i_@% diff --git a/bin/main/dev/loki/data/DataStorage.class b/bin/main/dev/loki/data/DataStorage.class deleted file mode 100644 index 8f9df8e5c7cc04b4f9bce4de36a3a6c6b14f05ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 499 zcmah`%SyvQ6g^W-W9y?)L2%>7O|r1_0TEFsrG-_`39Zp^J1kO{{NL{?;G9^QD!cT09k}~CDSHN3RLsHW!lMgRT zl^B6hMU8sYv{q$o$W#JjKeDvi}+b5S3Kfc;Bv!t9&|>Dm>05FoM$UCb*Thy|F5{-(#;La zIf*VRmfG>#RSe^zE)zA)HA7x!{o{6}eE}x&xd4Z+;h>N9DlYbH9AIeUJ`R|7$gCcY OI6s2Ne}Q9*oO}bb2#eqV diff --git a/bin/main/dev/loki/data/GeneratorDataManager.class b/bin/main/dev/loki/data/GeneratorDataManager.class deleted file mode 100644 index 893726ad64085ca29fb02f29b1918e15bacab937..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5925 zcma)A33yc175;B#CT}u45*Q$62q3$egk%uok_3^+07k>0MuI`BeVIIl2a}mF3lOz+ zY3=6P*0vUFTj_#nZN(}9q|(i5YZtp$yV=(6t6l7h;(zaZGxKH$3VdJk-d)c5&wu`N z?tOXc)NQ)(>tq<2ivzo7TrxUwvtJv}Z$~fQSlAUX@N|b4DuHZzS_(^-4b-@t;8TNHU+W zQUVKl)0sqMFu!e^m5bPe5oP&8n!i{r>JsovENiT!DNx(1rmb{DzH`ni=LAl78;Yk> zo2^8iz^!yDvY89jYN9C(b8Gc-D`n+Y2rO=L?>+&Ha6g@`N)MR^Cx&e0K)Dxh+;!U}5iTOQuWWi|AO2(@DFz%gW}sljLoZ6KCjX zmlKoY8Pmv_F>|NPt)%WO9cSYlff{nsn@&)C0<#KyRoYjL{m)fIfCrYPHhEjuE zMbQdet>g7zf2rM^&I}tAq3uo}d;%E9SKB1SVQOGu)t2NY9q8B$O3Tlj<_s&viYQZ= z-B-K9o1_6t$5y%6Lo#GwNgcyr7Cl*$;hZ)>I4&RsOZ_sU5t$7ZyFXcsWrkZ}g%D+L zO)9dcR1zcLGgGBzIK^)JqekZZSGi=okwt3@tx?_lhnJ*OVPEcG}pLGUjl4 zhv`y+x2Y%GFUfhMj_Yv)@n)@SsA~3=9yxrIjyK`WY&iB#NpFwSOI-&SZH4kwvg^)dj8SPZ zfLk$L#&D;Ocj8^lmX)&)V$xe?zQ-BwnuNRXUJdVIQc5x_%<6a_?j}Jga~I_@y{KZ~=6g7R@8EkHzRUc%=sjOu8D)mPukLTJE>AmAe*93N z>dNaRvCr!G5q``|t5UknS4IDI0EL-|G5l0su6|Z|`q*}((P+3|!_Rs1D8aDrPixev z;W~9a*&OdMK6;fmplK5jz}cO)+IZ_KU5;&6%u+m^&J1y{kPVA1Sg>8rbERTJ$LuuE z+nsDvI%QsJ3|V=a@LSoQlpNp{aN^^vqELAl37mIQOHb7Dn`fnkksdpFzIGxvPr5Pi;PcY0WMBQQv$R4FfIXm>HaV z0Q2`_QS&%Xdq^2*=FfU=08XL92Gk%#w=?;v(ufu{r%Yi9TKPt!3IbIrzbG7sx6qwj z)zY?&8Po1`RzrUwQj+fNghx&7#+}Hl+1#M3)hf zgaNWzTZ9oL5g?#RbXrGejc9YZpXIo(t8^c8-1lRnQ5&l%LwHR=BAyzoJlxmA%b%htY+Is zF+)qS9T_4BkhLswq@a#_^4LK%J84-`WY6v5oaAm2#7l^1h->WY0@va?CxH97MJh2; z3ZU^GENEPE2yYPBL;Q`0aO11sw=>#Bf6J+@bD7r_jO#oS+O4q9wapi?M{qOVqVO$p zu$K_akpf~r#8I>nG1tDenC@;`lgX^J;R+X>Rf^79IMQmx6ZENh0nL==AQzf{^zR-Ys|*kH(r?$MOD7U&!|a z^p=p%PO+T7mp8Cu&$jHNF+0EWS=2PlpBK{AMQEa)Bg{!VMSL#b*WwZdvRzeZj|0+A z_CCza%5p#3;i-u%*g1|cwEL(4pUQSU!Q1Qi6xSD6JOx$9FdIG%LM1;=wcRC4T;L-v z7Cx$2Xs02`RG=8W48!JC_9$S3i_buj&yV2-{~>&uU46jI=SL3WVBdg`Pe;^KHJ`p9pAO>j5@cJMSCN~m zF`d@u(0&sJ`4^0je?lQK+Rn{EH%O!i3Ggsqm~SH|(wx+O<^d*BoMmUxzpfO66_yaEJ^oG1gs@0N^*IDyShcD#y+UuX`&_Z5c;ko88#s*p&d<|Md%>n#m zUneco@iGj-#BGKgQ|d4?I{r{}NmYx)UeC4R#(FRh)1-;#76Z8qX}e9~yS4!`G9 z4Q*FZsDI$BY$Xlw9+iKU_@nyy;86tm%)cl;$CZD=0VjnExkvu>;hbHIe^n}ck$B``)m^H*)?($2#aMXv^PIbX953uf^g*WVERAX446E-LPxjKNy^>V?2mdWn@jpq0=qCOEt@nu- z1MKiRjA(mtPDpcl(O747sJeoanW1V)N{7F}-{2)Lfd+04RmbEe)u0}4Ej6fS<-+cW z8oycR;5L@X?L2z!U|4q|%CFb89KVFnrNS;CU_vUA)mJ2|&mpUdYyYpv(%9^dQbS%^ z4J!hxX}1n9am-&ls-(36o;5a=y^_ixG}W>sm88v6pmTP`c!|>bikTvbef^D*$xp(e4bMD;p`_K1l06Tc4VuWGgM05j~&5~HN7Tx>fE>z^ zsU6U*9qzORZB}ymp`B=0!V?wC44Ih1ZV-xd9V=L6NORxk-KO`Y%TS2-ad>c@@f3N6H*tbphX+9^cIz$Upaba!8n9-0ZNDkr z+4A8sF$)!CDfMRAEtiLFpN=%ExzlwtAZc7O>46Bs z_g)ZgZ_uO_^1QM=BV7Q{N(KNjvvT}&lAu+?7}e<%)hL#~;t#M!_MUQy@e5?5;9(*P zCP#nLk_zCckT3D00)gC27;${T+H(Q5Ua diff --git a/bin/main/dev/loki/data/MatchResult.class b/bin/main/dev/loki/data/MatchResult.class deleted file mode 100644 index 0469a614fe956aa739d3036eedb9edc3b7db63f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1354 zcmZ`&ZBNrs6n-x2R@e%Ru?b^iZi=RM2Du&@jM+Z{2nS#jYi7hvC=w2Q<;d zMdJs5fIrH3?(HN}%7^xx(|ewCo^zkm-+zAo0`LOQRP-M2A%Qp7* zs_V-Pis#y#As3#=LbbrNoI^TGd~hAAalkNCw_Ue+;#yANzcM|CQ!!R$$hQQa^|ogQ zmh04b!*!ZILu$oxtYDR)T#k0U+~=TLt?Uz#HMhyrNFc8vivo2oSN78wK~cr%g+Xg) ze!yEA#!w<=jkf1;C)lN-w=CPXs68P!`oJ)uA&Hdmu4_=yE4*n9eMk%MhK39@;oa2G zj{)J$YZ$};!{Dan@a=Z1&b?i;9$t{!FztQQvqaqes02r%UupA7k?0n+LoV5MCCO0u z_FR!%xe~o029;8Fq%8S=#}|c3TK+pB4Gl`-4pMMe2U3yTWoI)+r zdSy7?sco3T7sg{pd~c1P_`;u*NL8r*QoIs|Bit9pSH~}{fv?cQNZ#2uae5$+r@rkN z&z|k?-BL*NJzqG7!XKPi6NQw0g-X_BAV&ODG%ewuU{N@=9S3ve*zr7b=Wt?^TF>{tpl4!nVIj>OpJ z=WtW?Pi*9`AN+4IQJKmM%MZ%SrEByy(`rD6D^KU@2QjE%-F63KYiPNCRM^@ieO2x4 zb3IDKS?w2rc7Im-7$Vv#<9siCA+?BMwzGiKFN3#KjSgoUIJ=j8b5&uQa~nl5^rkM{ zQlE@0cm9kM{YIfBxNLBGC`Pl&0+j1BX8`Dj1sZ_=&ym`D80ejuWeEU*xUYqeSB2QU z;_h>p9Y2K@pLo;pzU;)8tfaaa_ky8!!vS*W8@6K$Qf>t zGrWTN0uX9c$9MrxKL9O#4>}KR9yDE{?i?&v$*=!KaWm=&BA`e(HI8x}cY znxfoXmoQpzA%szAlls_U8Oh+aH>u!OX7Cnr41#Z<2FzUPKR=^2^*iW~Wd{5g6A+b% z|2n-JLfk~QT*hKw&xqC&MJPr^DAG1w42w20b+pntE+vvEL`l4tt)s;{T4^2a1VpUk z{Y-v6&3`!&9P@vW&95`Rp62f)AY%RxGx^(T{ws;#nE#_}{x?{`lzFWzmw*_Dj|Y)nDN7S^hxN1PwBJJQQwAOO|(Nt|A}gB&W>&Z zRDF}@)bg@F8fZX*85Yo54Ybn=x*~45X5_YJ$Z=CfD(wARbUP$7VBT5pb$`K)WbbWd z%Kn`0guy##X8t5e+1-wq`$`1ub3Kt#QuYqM8r%T8_@fVc@iF9ZCOTxV{fMv88MR*X m`n9)0_fCH%wfd`65PuuC6Zz?(URGJ4Tx*v*dk+sey8kb8bT5(s diff --git a/bin/main/dev/loki/data/SQLiteStorage.class b/bin/main/dev/loki/data/SQLiteStorage.class deleted file mode 100644 index e360f2c9d2e4bee5d387f35497939ba7f8ba1a20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7559 zcmb_hX<%H{b^h*XX5MJ@WXa==u}yfy1|)f8QDYmB@SrLvm+Yxhu8^Fw z4R{qgPbJSJ`!dPwT;IgZDSNhLz^@Q)95%wS?jQw!K2x4cXB9f))n4l;mHxTNcGgMl|Gv^VV9goPW~IA`mnjOH>ayFjycbvxU4hYtj> zNx_h*wx(u+SdW`ze>W>^>T2xhylIC_l?v(X+(7pc>EC6d8$H}6XBwO-<}&4yeK1)% zNqbc0svi_02qGqWu~lK+eDbtSAIv68N7JQ~d@7cb*%GaAvpaeHNO$4&O+nm>Z3cco zVQtl?BZc%CyD*l_5=jLUw_&?ug_^Gwy05N&2`t3JJ597A*oHgMZ{SXaRn@s_I!z4V zE*fFBU?&C0yv*C#5*Jo6f+()G)9eJ=w}&UAgNdk>7#xa6t=OnFK9R7Z_r#_WQ&v8c zJZBe9&>*Fv)fKe(uUt;2tVHylgmrK-Ha0jpZQUK6j#%@_((FmQXvM}8(S6ZLYa}{4 zcsQQ0ZjIMb)vdOlabpAi`mm-$-GOE9mV7s`=AaC0StL! ztBVf3^uvc^BLhq5v#vM!Du9&2gR$|c=w!m0n6xIN2jhdo488HhL_@>{yTtd^*os(g z6w$9bW+Il3j!1nhM6?F+a(D2^VEk}&%Iew^v6lW4|99YrP0WE5*_kic`DCG6BaP+KJXgLnc@8hC#tQ)sg#P8M?aOS(7l0eq0-lBv{GIZyu=i#AbtUA^0@or&2H zJWiAv~?4`=gUl zCn4^#_K4L#W#U;p$KuHK$Dy)apnDq9@1$KUXG&9cX`l_C!3zeSug^hMsfi1?Nao7g zX9-Ax;g}$1LF%GQ^l9@>bSQkz#EZh?o#`x#07?EX*aLWpPII%gO#B5Czm6{w^TeLU z{IWSNCX@cAiI*Fdx{(mTmn2Kp!s5#&z9Kz4s?$5c5x{Q?Jy!$ecTN1B^jlHwr^6+H zKOkZ>sRi&=g|@n+CJXsv6JNt?97fpIg%YjQ#c&Pa8!j3pj%1I2YU0oE=UgK9=!DL) zn>--8zh&Ze`~_V>-A%FR?P9=%Sa(MV$N~Xbmr1G~W3EtX{>6m2m?O0172Z@=$m?QS zw>zVBHuy({teXvV3eZlfR1Lu{C%jHLsX!_Ko&1-OekIXIY6<@8{NEkK75s~Ve{Lep zx}}-;SNt1Y;8K%akN^)g6aYHaiLU=J@t;ESV&_S&P};s@;tc_?FI_yE%Sy|4O?*$t zYBhV+c`r&Lu~X9Fe@y(ZbXdm@dL<)n`7&kC=CUcW=@l%R3PPDC`y?v0ObA}_jK82m ztC?)-wnZnct?_~u?04$3+F_%{Uop4b*DZ1OFH>b23p-1<(;t-0h)82AY@TRY8YKL3I$Z$V4nEMp%LmP1nG{dVFfw zipR!c32RS4tzgIqlo%wc(^MMaE%;8Bl8&Q59^_{AwNfM_s4T)wJh9xB4>a`7}AuaNNu2tIsp8 zSJpP3X3ym-C)(b+oFsj(?GKhk>Sj~jBFGJ-i^Eb4r=(WeAA(;N6P(JG3$wOUXNDTS z7;Kg7#l;Qfa;0Lakj#(SrIR_rR&70 zSgLrIe7|d9oekaIj>7%PY${_HH^+0i)8+g?v*GJn8U`k4m1Vjguj^m2eO;5QVmO(} zO!4!`K!;!T2Gn*I52sQyv;EB6Z0%P8wUhP3Xp#kZ$|~h7`TSrx_UX4My@PRGlL|jt zx-`(j{sy7MXPuBI+NC3P5a^LSz=msT^+@-;rNw(2#QJbkTNGIྒྷY^a{Ptj1r z3O6;mXgQ-BDoSF%c31L|<00J0b50BYd@Q0u@|}iXA3SoJ=iOj?8%$o?`8LjW5AQ2_ zF7j{73s~860jr+V{nzp;L2f#pi#IZg$hokw{TY~iASo4HI`-bya>MlNp)7r31tg?3Rgj9ah| zT{wmwy@?*Zx#R98R$?0^$Ek4(TYeBf#Leu(D!c_J*mf_qw!-rUMh#4?VnY%$ywZm1 zd8#oeel;{ZuKK;I-zWR&U4ZRDzd!8va>eNdWLpsS`yv-mTEJW7+0W-6bDs@9zs-FP z@c9w?q z&)aC}?fka219xI4qPQK0NMLW_+iCPu&j6msUHB4qYpd@juhCdl=)8)L;G;C9w0#U8 zr`20n{rw`I(yMp?zr>CCsbRJDgjaiF5XK^xXAsN=P8ld0c-p`d`Zp(SPkayU{MzzF zd;204dh7d%cw!AF`~-g4@u25JoQkkfy`f(jQ{qE$V8n5tFYK#xpl<=csgO4s=smXq$B73D-_G(4;Tg|fH zsmOl6A`2Uw;ScrO1^khI`}zX@#6uT;lW#r&0@q7qJS#5;+?Vs%J67l3G-c#*c@yd`siU$9X=5zrtS=NxSetjWdHE&|1M%4R{7VLnso-#wz`@$VdoWt((BG{9Q7z z2CF&9TU*;A0ohU=p^++F^LO}r2dQd-TqEK0V(1^PhSYzmvW?G2=J|Jrd3=68fBQ)o z-t+LbIE3Oe*!ExUbAZqP?LK!(=kGg2<8z7T{{umawsHAoHNE#BHxj_R`6GyVnm-kO z*~SC~euQhGXI7JmH!=46$iu_*zyzuHILY@UW~n2EXJF%V{H`R3*iKB+I2Ab+=PBsBcm_*WX}#A6_*7O8hRA-$DT>J98&-i@NE;zs3FOvp;y z=b`hNIy?`Nb|hcDepv;kFRI}9D%GYli0bzX2Zg;32^nFdj)V-~M#oWx!$zc?q29~5 zGQA}nSf$z*REG!h6w=(_{fO)IaKL2?k*(IUi)!tH3Nzh?1Del1uy`qKNJgP%H>3EZ zA?P-QeJ?Si`6Q$G`+bs8d||(26y7AGP%O!hnVxJToS|;e9`AjYF0k+z2@^E?C-?&z z;8p%i5Ydvjhgdg&2_t|ECG+f^MTB2CcF@VYaUTZxg>IC|c&0JACzN%s2KD{CWznx6~sCJT5K5loNWVw;(R9XCw(i6JI5*n9K s*`gx6M_{OJQ0g{)-J!3y>+7BRI-sw+^mUIKz>% diff --git a/bin/main/dev/loki/data/YamlStorage.class b/bin/main/dev/loki/data/YamlStorage.class deleted file mode 100644 index 8a6b0ba441c549aafb35304c894c93cb26f6b07d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6362 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 diff --git a/bin/main/dev/loki/gate/ExitGate.class b/bin/main/dev/loki/gate/ExitGate.class deleted file mode 100644 index 210e7f10a76be9bb8d1728cccd5ed855df475940..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3813 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 J@A8yR{tqQC2h#um diff --git a/bin/main/dev/loki/gate/GateOpening$OpeningProgress.class b/bin/main/dev/loki/gate/GateOpening$OpeningProgress.class deleted file mode 100644 index 7521726f39af25ac84bdd87c868a4bddf59cab7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 661 zcmaJ;%Syvg5IvK`R@D5Ib_pYq?DRtd)d{KSN`~caLMc%{ zgv>3eJ?Y74pRlw3PhH~b7qVVy@m@8*E5<;WG%y?(e$(tBKN_n#; z(ir91hV;bg-A!8r7f#z{Ub%+faom;@NEQDi4aI`6kyv1eLsC8FlsWhBf{r+nYOFO> zyQM@Wn03z+LCtl-P_Wv|gyLUGhgx{k#PbkFPemA=_+f+#!6-_MqqimZhZN zi1^RKWIN8@B{Udp^VN+3CaQ0+s+$8$R~HAEdF8x@IX-i7%_C2E!UUc%jTaO+zY=5R jQN%n)JSE1|Vo#y!{FOM;uz*Fj8Ac^6ai50OIKT7_35=H> diff --git a/bin/main/dev/loki/gate/GateOpening$OpeningTask.class b/bin/main/dev/loki/gate/GateOpening$OpeningTask.class deleted file mode 100644 index 00c0d0c5703aced36d5f4297b2844f9685080497..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2265 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 HyJY-74WT0- diff --git a/bin/main/dev/loki/hatch/HatchCondition.class b/bin/main/dev/loki/hatch/HatchCondition.class deleted file mode 100644 index 30223bd85085d5dde565435906cf0e17197fb911..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3904 zcmbVOYj+dZ72Q{_!SV>3hm8TtC=L)?7(|;Cl8Qi#Y_NljDWYym)5o=AP0}W9)7E@yR~M^a_|mSF7C!U`boD2tUETMNJeDmjvl@FzGjrzLbN1PHpL6xE z|33LAfJxjp5EIDOthIvUt=NTS8B~`GGwQqKxivemJ=Z`&p#QF1lLbe*ONIHxyH+(2 zIIwEFm1bkjUh^9M6|XU0w_E`+E0DTiyLNC?KzQ%?6Xc*xm8MR=&C;*R4k3vh=MR`nGsc zg-NrPArpsjgtSz>rW;H;_L>#3BXGET=;Ao(GQy~=Y_K~}($TQ$(r#F_tCnjuWI)Er zp4^dSa64)1^-bbl=o+Ao|lBb~4 zte?b~f#(Dcb`yk&apWmR+YbR#blj+um@si#z1U;>CCBrvnlctloNXCr>{`uo)s}wV z!~q->Nb363_H@fby%|;Msw8Qg$4drYXg|23D~bv$$s9Re?iW>9>V7QN|n*+_9a&Y6!g4UTBwy zyWtamk-LzIE2fn-1 zVr{SOm!%(UPQP7-ALs99R6SSjtu9;Dl}WdD(^|8nqq?|Z!dK@@s-aD6u}z<_I|bHE zd;!lY-+Lz3m2bk+=hhxat}fQ(@v~}AziZ-qt!Z%0=6ONUin>6$;x!vp>x!*Tr~}(i z$umm)JSQ)EUO@HB`kWOkdo@3epWrP6KNT3=8VR<$=B-$TvQ9}yc}G?`)7MSBjdyr_ zt!|kF{@rR9efYLkhQVi~TXQV`c-iw-n)TM?)o$!(?nk?2+rnEs8a~_0Fy-!RTaDL_ zwVsl#brSM~cf%cNZ-xJ00+x_^Nn!4|scoPeBe6Jr1E!#&XzD%2e4{77J&bmAX zOOEt?%Qx^_ffF6%cB9C^?*&G7ccpqlKJg5}#5oap{HmWRyzAw?fj#{0;nNkw_z$G> zf9L1u-;ntWpJM3a_g=lS7YUg3&7hyQ!O$D~7*GABbyP}AoicnkKwFGnD)u_>61?{1 zPd&n+i`n5nA(?m>e@Ih8CrImH{e-no2hWG@QSd$-#V|uN1hVvs@zaA5e#dc)Rr^qNcqj;A7A)MnH&ih=Y;N*zr#0HY_hrBs;A0{tn?yKkgMD`Irw}mex zV1TO!`MYSS4P!3Cn8WjULF342w2I7}M%#{2y~`1g!k9p;r;jVx!#fauqALU@LPQD} z@o8Wr@LVGQ2{HqTf8gA?WOg9=#~p0$*VPRZ

UupHXI0TXvDGFlK~!B0@Y7A)aU< zK19Y8zX`5R;{xxJZA>fw%_{aF*8d+I7K&^BW{fI%S#y1l&x(oBQ;)&l&`&T0JjP56 z`6syEx_yi<3B0S=j%zgxG8b@yIZqPzbIdiy3Qp)6LfMT*HH>QHJcYO-RDrT66~t7N z@u~#)CZCk}M@ZyX<|h7%Z#=*OUaAjZ@^a@v#9%vu3F0`-sAnkY0xLVM5#+*15rPre zxXV0AR=S00w)zyq22Ujcr-PL;y%Z}c-4I)qQ?;}{-&U#Wh_Jy@9hEAJs#IVV zF5`t7_jJXtwK8OMhQuGD0>g$26P<5Ml!+2$Iua?%W@E)6)ZnOhX!e~}R}Cr6ZeV}d zLmTMf^XuEXJ=ABB$uDqJyv&}uq=AH8KNJBOiu5_8At}a&Iyy?d+teb#4H8_?0q$c8 zS+#sNe@eA>a{~uMn1({f&l}qi9?_jrqVlJRW}3`i3RL_Xm>wX>~Xdu+r#dUInk2{3Cp414jJMNF;VjLp8*v&@=cxg$FISBx1d1Bd?yp>sa* diff --git a/bin/main/dev/loki/hatch/HatchEscape.class b/bin/main/dev/loki/hatch/HatchEscape.class deleted file mode 100644 index ef5738b6df001d93456d843346f7ca829cbb728b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3644 zcma)8Yf~HN6@HeRg#2O)VMu&ygmXjUBJ703F0Nw&!d5IU0gP)}hb+<}*2ofFEjTp2 zI8NInb)7c1HX*6gHq+7zZEX_c$eHnUm`*#>Ps?BEFX+d9NSi+I?ji|Wo~aqHcHe!^ zInQ~{bI!j1`0uUT0DADT2Neo-C$)u0IyhmV6FDKT(Og2E(>$nB;6JA>sFAdq zNkxXH&S?o#L0xpTw`VvyInvV?J2k36>El{&Hj^{ej5)5R=e3%r{>>2lr=Z$)tDq@f zE>O3Enj?BfH;*dV)lz;-Xk0;6Z#Jpme6=D-8TsMuuZ{^xSr7l=g&`R z#+W*l))WNd*@T)NR}Ec0yNgxkjGj}lw`?RQYeK3ujYa1{!M+kyb7^%^Ga{q&#)7_( zHM&C+KJ39h5B4h9SuQ<+FW~{EsON^}w2Y0KCJLGb_G6cVdIlQN7Bn^8lS%f@Xo*=L z9>OCYJgngUg2Ow)3OtGyf=p@Vunma$w1nbWBNdsNpPkjsh?X&Rb1~w)?cRnk+B|5b z%X{q+Xh(;FZFDJFGxaRN-nZ51=8JBbK&QX~93%)m*JIj}q4$r-n@-rfpYpKZKu-P(A$Sz>-d;7J@Js+^Wd4rsZY znqpZSTjE7Uj+%y^Np*+DC8jS6bmIu6IHwuYS>ycwRY7XYn{(^QW+>|74$`Gioh7;J zUOaMF-KeQ1W(U+cS8=roHRB+WTImyrN=10}+zCCI)G}TiC)4Z8Pg?KG)Pox@G5?Dj zmp3kTbaY6In7}ixMQ=Kr(~@4qZHt6!VcoQ@ZQ3+Ti$Q@Q4BNGdWk%SzWR1O5g1Jze zzR(1*qzff)EW1lO9TPYuB~nL;JTrfu*%`c(WjZbJRVf9psin2KtYOOS69Qk8ZR(et zIq65Ir#U^O#aV&pFi8t~IGr`pNp{axt=X&HwNR1pV2W-^z>j9u$IG{h@I$ z&a;)*m(}&I_ zZwMIRe5#d_AJa`a$HHXd^>2*3CY&SWq4wB+1&|EPSpOaQS7bn3;aN8uEww@s+8fY z0=O+Sh;7tWSYSy(R z5USQ5M)Rhgj>PqxNtwNkpL+0)g6&)12>cB1l0n_n4AsmU{333#j=Agfu!Ijhc%SZz z9yZ?!{2W)APeyxzA7a@x#bM}to>{Le_=UhP@he745|f%qP)7Hf&V4n zw!W-M89UR+y3HZ&&ZB18j=vT7oou|Or{hDtCnpDo#-fwX?QlFccwBb3E)!T0_@kU! zo*6YaXk+!-=Kxa5Bf$ly>9=&L)AA&k9mwkT>r(svlG8|s%oNQW^p(V0f!(M^4WB&r zlNSMb5a7K$6$sSvx}8t`+*!e2U-%|=gj;VQaNXX&lh^IGryZz*pH}r~HSAtOZMby}!4+N}9BBJHsw-E*ZFz(gtRb?5y0*Y$ zd34ceMeaLXwL;@cNC=NGFnH%!7N8x*S8$Y& z8rh&v;TS>n&=(I${?Fm_Al$@vPZvPH=z`u~08Nx-0T3o#*w2+c;36lK< zB>P8@24u{q3jPy`W{ z{Qz+tBwvr=0X%^aIXi$ueCjU2+f~5Z<>IX-$3?tk?sIG-aSaWG$m5L*_!wD`5)zWR z)}8RKVL;-juq!Af2zn`sM-<`+Jc|*&uaE~5*W2GHS}C59&Gf6Tw>c#l&11X*r=5p0 z)X&%X9kNxlisyyMW4an`fpj3__xX?beR<5)pmi1I8onuI^&Kf}M^znmBlMD+KI);L zx;jo?Vrb=2qLaT}ILTwk0OC9-Jd5EHjz$XDM+zJblyKyQQYa}WyPMN2Gn6?sl;jk6 z$*x%ulq055f*K>JarW!!lE4jxzzv1K+sg)4@G@oQba#rslKuxB(kLLGbN4;xhpp)@ zyix?xL0DId5zqT1_ciyaGS=8n6`)Wv| zKPXuG;;%)_j@lFO^4wDgjpU_xWS?RG>#XlNQkmj(K5yp`w!3!9&B4n||75GMjwiT3 s;~Hz#&OVm9ue2uy=gNN&@ZgFEsV}et)gCC$6KCrZ@Hn%VNGh=UKV^VyMgRZ+ diff --git a/bin/main/dev/loki/hook/Hook.class b/bin/main/dev/loki/hook/Hook.class deleted file mode 100644 index 863b9f5a0488e470d27bad248ea38c72df07e4b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2559 zcmaJ?SyS6q7(K$q1|uAHhX5f95Fo#{hgJJa9P>Ga$yAsbh%A9SyDzvZ0sec$z;fB*J7fCW4cqd`GO);LZS zth|{xw5)t$jgK&b3ff-i$9kfm7juctgBM1otf0Zn@_R}iRLW){v9pt0npV(Murhkt zw2BJ4QwIpn|Y%6CQrIG?ANjz32Q#mpXqE+_!dZ3q#mkh^k)-34<1#uFZ zF^gt-R>5ezo{=wy{n1?o!9^=;L=ZqsMJFyQ2*gKsn?X7%8W9q^eidOfiQQ!t?PzPp z6YSK%n}hLOA1k@R7?xr&FO{3r^%J%;&Oy6KT|O) zgjMzIv0ls=ZVNbNK8wY&^Lr-0t{+LZBIiRDi&$cbipF=WbYFb5O6k1bq~GC2-?q|v z#x}n-Gn6q#v@+dUH*FbqMz#$hFNNm!I5qqcn^{U0(`CDo%L(~;x-ST=tJtV13$uSJ5H5tfj=#dBYNn%l40?tqLVsF$L{r0qT~Zg{yQ7P?{$CatyfZ5JSMVL3E8= z+0SxiH_Mg1ELV<*T$zC3sA0Cy4)q2$zXJ z5PYxgonR#RjS%((LmzR!t?O`x+mXJX(JnrHz~nCoYacNqxCSUBD6Xix#ye_^@{SY8 zO+27zQ<$jXJMF?4VkzcW7zOk6YC<52zo79iMohoUe$i#$t~oFk&dOaCI4axjE-%Y_ ztkV4&zU?00WiQ~I8?cokPX1T0Np|iOdv&@dSgRLo1*y+&j3P2i1} zAVfQ0sRn-34LmPx6wwfy*mA>(rWOv34A=XPn+91rsnd5655(Wr$zRPX%A*Ll~Iu+}*)l&j_Z*w^`UU*~~(=ajGW7rxGW_0H?Q r&d>0r%Xx}8MazY>zEkW~r@*PzhV*u>m5^I2+KTI({tCX5Jiq=2f109v diff --git a/bin/main/dev/loki/hook/HookManager.class b/bin/main/dev/loki/hook/HookManager.class deleted file mode 100644 index 03c3a6bde08816504cc933d51d53ff6cf925173e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7441 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 Rd5F98cz2e6TzCX+Uj|q-Qe6N5 diff --git a/bin/main/dev/loki/hook/HookRescue$RescueSession.class b/bin/main/dev/loki/hook/HookRescue$RescueSession.class deleted file mode 100644 index 347809e5d1f93d8b73953597560bccdcd2b8268e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1547 zcmaiyYfscr5Qg8gS6qsVh%2IqD3YaK>Rk~uD#l2Hmk1%zPnL25bxTXyE{VUuUt!`c zUP;tMV)TO_{os!>zUQ=d*A0mz>`c#@dFGut^XvEb9{{f6QW-gcu_d`~c|pUqR)U~m z-Q>?b897ZknwU8mMQ-4iQ4r{TWUt$nXZy?6oyAAei3Q4`4h{tdXEV~8XFryqHP;N+ z-Sr@x6euXTKz}PHtH#@&rDkZytTOL9jYvSu@N6v%mI;s2vqEe~B#g`k;j*>ZY&6{1 zikua>)bv>Dnm(9k2yvw;*LUN~0;lS&dYzhDH!USI;|r8J9W2QT^5`?L9Xkc`_3?#m z5ZGm)8x`g4Hc&)Kd3y|$(WSh-2DYIhP@Q#sdAqr~D8qSs(USswvw>rK3wG$L@AR+` zuej{AO<*QttMRj|9j@<$a#i~A-E=Yn6*rm=R@XckvkrAW;N0e7+iBdg*Zx*tmRZ7G z89L0@q1Q`S?sEK&@J2WCU#fGTrAll|Rr)zGUdIDsEmTPtA9_`VFM zJv)kIRK`Vtfox$jOp?JVCQiEi0$sOd#QIT;1Dsc$Q!AoREdjkgwF2650cdk-O|<2N zXw}_zRGHUHugUuY?H=f zop^}>yuuLg%>;z~80Hs|T9DA5l9bb)5~TzmU~VGeEWcG$w|V~y`U?-Kp;fe`uU_i{ zMiQ147{S35agA_=sG213fABeqg^m0MkMdf3f_c-1siv4iI!36;jN)+0yU11)uUGM& zDBzQzA7hP=JWGa=0N=I&dox{ijAxvjZo8z0YIb(@PG{GWh%CE=qkJb-om-i5X43v@ zlw$tmL(zQ0aRF1L-1au#x2dZA+vYA}PvLZmwP;nLB6+n>9ld>MqZBiBXK;3la diff --git a/bin/main/dev/loki/hook/HookRescue.class b/bin/main/dev/loki/hook/HookRescue.class deleted file mode 100644 index 4ea8ba4900b614417ad0f2d54c00a5b491809c05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7375 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 diff --git a/bin/main/dev/loki/hook/HookSabotage$1.class b/bin/main/dev/loki/hook/HookSabotage$1.class deleted file mode 100644 index f14c4eeff05a2758c12e84445a45884118e3889c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2656 zcmaJ?NmmqC6#gC{4NWPCqCpgif_67(NhTB9I51-xR2uN8iJ|Cz(q$J_ovLag8I2iC zHf9^$xkz%dNRFNZB(iXkg^R54FXVT4a`L_E23iK|oL6tS_ub*U!~5sI#U}vH;)f8* z1oo!ojBYtuQ_na~Rv+LmX-qo4F(q3&L#Plq=(tn*WImfUecelCWIAt2SMLfAM)J08 zOj=SPBrPN7$+UnN6sYtwrq_Cm;uD+8j|*rshSloj-5GPnaRv6Qa_1~#mTHnk8hNV} zZ$58QMP1^CF=Oa?-?a3xvB92Ys&YYK=c<$ypU6?G?x!+_J0(ZWRMw-FCr#V*PYGO$ zY;a{6hWILNtx;>uSmj(*JQy7psOWamvKq8aLkLxBwM#=a!fN%3h8k#UwMWBNY*VYf z8fsA)Mmd@_)M39sc_ccnD6eYRf=arRFl{-UpPrQNXdwjk2`6P(BZxI|73g2{Wf!!~{vrLF9Jp&pBaZagr?Ca*#3*}Nc()*2R*&R^hVI(jd z!ceL2>$o(W#|3Jo4FfcO(DtQkq?9QmhCNjPw|S+rYE`YxkSn6F_XgbxJ{*wWXtvyN-(MtX)xmv^P^%bUL5?M&w! zn)$HsnX+djhuA~92qYJMt7t26oSW&qYArL*ZKIt1N z=5#LT4=$noBx)HzoT_)!etMcrV*}RP|oE&}*kG$7586q@Qt!&d0c^(D4n| zU*;9q_Y%LNSJ=wC9LM*3*T@ybcwu~s&qMf3pfzanLA*?R#>vWJ78LTOk6G=wvnr9k z5csJyx<&4SzyZTfThePy(1m<1zCNc)PF}b;I-8RluwO0VKRzGGF?8rQJ#~Lf<(HLvkGLNR% zpV${GpGV81;Q9gnw*|^iU_at$W#2x?GmRoCi2F9q0*6Qql!ysb&`98q*c=)ba5&Na z6b}P-BgU3jfDVd6==>c|eQu-S>8W%7X=%>Zy zP~MKCf&bHl_Y9i(#zfJDBk1N^*UP7_kN;l22>oom1DN0{jdN@|2{;(Sml(z^cK17+ zf5b)lIfCDi#P8%*sKtm4ktw29g7!q1h1HQfe+uY#^>oDv=OGD;~!7)LFdViDqXl z@>cp-skD9VQ{VauD4|@G`~aRdKZL)4`c2|cSHwcKwR8FQ%y-T=GiP7Dd9eXt8sAum zF&u7)j^oLe>nusxa%QQS=QXK$Q)H(sBp8lM)pTlMtL17Zs4s~|=n3V_Yz1zHzRzo( zU>ML#Zjha%gw_5TiwuJu?qv-X!~R{6gc!K!`mVmra4xqCU`JeWmv_bdB157i8zKpY z4{YqgfElH1SQs2a9HTapNHfH92AZn6zL*Q!HK7)^t4LR6oqLO1xn|xCCQNAz0G`Cb?a88TpUIo zr!5pH;eXcKID=2=6qINa3&Y9W_DYZYP3PO%JyF-iZnECcARGqg`|?crZszr$>#tY; z%0z!`{rqA=>JpnC|Zv;X#O%RIbAt9pURx z2}g_j+WA4MHrLJ^Z;QqP1xnJB%Eo8-oc8Ye&FMP~lhyyXnrc6f3l_d)IM#P%Nw$}z zPfBcj1v=e?QNz&e-Hv&!T)$a-Fa2BHv~zt4w?SP}I>k%4Vu5Th+T*`%*V*_Q(+tU) zlDtvp0m(X*>!0{-CB=M&VQ5~4sxGd%#(zwXI^3cDfnl5E(xhU*j- z_eDL_V&^t8obB=Fvd35Gt1us`j@yx{uRHCE?+aD(cn}D>yMuEg(6cho$dFIt^j(UL zj2PPjBWYt=6QL)GA$mVdqYE@QxK!cv8tlTEHS8_?jgiM&zD0J#wi@Y zL7FifLb{u#Nofo&Us%Q7_)~mHy}gQYGkuEebL3*Uot}7t$!GZD87|)bmtf4O!!M-m uA^G`NjN>;Pr9Ow>dr0$L(gbD*9YYCa>J#MitC*#csmBN~zY0Au9Qg+>kceCW diff --git a/bin/main/dev/loki/hook/HookSabotage.class b/bin/main/dev/loki/hook/HookSabotage.class deleted file mode 100644 index 0bf6cf5d4afd73107c22176c385bb981f98aaf9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5419 zcmb7H349dQ8UIg`&4kS;Ap}f7ASh}QlB@_`ECtDd32uTVArP$6$?hZ>vzb|DW~1q0 z(bjs^vsw#n?S0!8C<%lpwHLNl+fDD%+urwmqd)&|W{=q%v`v1$eQ)0T-uJ%a{~hm{ z7muF+uo*APD3Guurj3N+=8zs5G|iz<8-KdgKGRVLG#Nz_%5GFg)KFYC2148VZq%ZV zgyKXzIiMRn8!@ecP+xLrNOwZsV(40TFHEYaY4qy@63&feuke;aSF6KXv%5>WQgLsG zYVbl!!qOaZR-W`GY0K=iXw8GFMG?q-e#8|p>FDuLhngVKye@sfP@SZuNodO7-QfG& zv7@~u>{q~!4r;MvT(d$=u14LeJrv$ZhG$t?)Ev>QQL$oEvkkhTI~yf**Z9xp8z860 zOr>*sGjy!&kxsnV|Da(AEq`cSZ?qp-H$D>#;!w)vlb2M#0NKe3X)@dt|G?~z~m|!iTJ`dJeIa_LTPR(+q^bvH*=%9;c-lYCLsp>bBHab=RQY?^LIbq$a2Cub#R!bue`(b%HwwNpY|`b$n{y z)P1Srse_G;jq@;sVHt4=jfUoghDJ?G52>*ch71#M$kA?gLj9&StU94iX8l+<7n;qu zX(=#ZGMDzYMk3qj?~5b<-+6}NUf42d>GS41*=!CcOoOs0aFAqX74k?J@Efwru~(i)!ZPkrg^Dib08;PMo6LW>G&K zu2e1Q=E<_@z?C2+rd8_vbjG6s(h@3i>~k0wc~sO|ty_ytYRK%zX;( z#{-0wr46%WOSsVQYOjHz|6CFLrJxjd;UNWY7S*;msv1!(9>gPfRK{Cab$!x#t$`>R zZ*>!8zA|L(qs_Oo!0Q18Z^PRq1hnCVLr~PQB+LoknOJ&E!8-+(&JtMK>}LNal>wk+ zFyhrpMYq$Iayz71Y_(h9YB1@<%$p2hw)ZRe06s|7N7Q&yqnj)9$}Iyn&d!g;CS1V9AdF&o@iC0 zgX~uP-kr(LbM+?`91-pcMB^-DY-qHbwP@1Oav)jb%l*>>W;U#gbRNMm1rs>#2CS1Q zOvHT6?%JLbJi*eFPMHV1EGY8hWa>of31-J9SBi9aLcym*Y71Pwy|uMdk7VsZ&HLl%T!}g)h3Mo$E4UU z+JtW__>O23miXF)?ddi>-7d)Z?wK2fOM*Cs?~6v^2NKr$z>-aW87%o4h3p=)vpD}F z1wY2~x#}NL*_lb$c&6%~mnCM)cWzhpQw2X0O>lrJwi7bBXNZ@IOES+AHdu6x71g%r zqK{wD#&n*Myio)k5zu6sj_p`#qC;~A&6pj;Z}EE>zhm{xB}3g9F^9BJL>=ynsU%eU z*kBo@n+>(T6{h2j=(qrDH8nL)$uZmEPWFp;4x!E>TYiC^P9qb-WXnyiM zu4mlzt~~Quf7(xTZdT**F5S_>^NaDDIUWf;W%%>_d3aF5syv_0>bF`_|BYa1Hw?{c zj;pqtLtQk}(l0nX+=--*8OV$RF3fWIQk-%V~s9P8?iVqx7R7WW=S8pg2lkjwXc{x0XuzsjxHBPnAy+R#jVG5BC2zs~(beOq?Wj9~s`?3p3a}r6!pFIGX=lUJV#=MB4HLMM zRrUy0jAPR{TGtm<6`jPws-kgRa{#4ce7SqhBk3-y7`!YniCw*QtLv+Z76p!CH+Pl= zgX6etQl+jv7n)R@Gx#XhQtI$3Q+VoMJuGbz*g6cjZ`ay3amjD zE};?Daqm)=+;#lDjOFGEz9870^U-5++{>?9(2F~;n+~`R_i}s$*SiL5^VH57>`}Z5 zuclD~cnGh-YiY15p1lRH~{6)qI z2+CN08g()v(hF#lWcET5?!lWpgX1xB7C=}h^j|%JdkgRs?&_#NiB+^b<6`wOJlxrE z5{oi6Q5ue6{{-Gq009Zl8cSSA_7Qeb+9ifcXjn$Q*J98Ihjm%)*5O^$iS1%q>H<

r~ahSTQIJv)b<$s8I_n?vvH9Qr16 zSbN$WwqhIgtuE-Ze2=HOmVXs3fBg*9w;Kx;T!U+A={rbEE&DqDlCEr|wd=RG2W!W1 zeP_*csIQyAE@9(m=pX{max^xE%e~`?uGJ^ewK}tGZ$qFea1vKm1;%mUATF(`8^^o0 zA3@!eJ!eebQ*8EZ=fb{|n6E!|%I^f;J%PLPk%MmooegNApsjSpHpZ%U2A9nYC|l^z z9USRI7kY3tda)CI>}&KRj;(kHuE*_coIk)(b>lXM86Gto79PZha6iE)VB7Wqj^~l; z3Os~|2}&a)@Q3jc2CAKml`mjl8BQAC0c!SZ_#8EJfKtp!YVIAc2 z-64hN z2dN8G1;=Ii5iH@TYFlS<;z_DiXA8`1;Amyh7#5lpPhyUl(TVE7(fp%?)6H}VoXO`~ zS(@BN_qv_teg{>2CxL%28gLgj@heF`?xynZp-bJ%(fjyxKmU1vN_h~Ur23BW`8m4F z1V>(>FMONe{v40smv|Jv!sGZgo)BTzy#$A44xTcmG2*HvV;WMHHVvvOZ5oT&9IKPn zl(PZfk@KaVs@%l?Cg1|Okfza(7v&;86;iUN25V9R7|<9lS}0? z))i_(>rqy08{>IRir!?*D7GLL4$-D8yk_CI7T)0hDJ@RnEDIBzmMl_7mql~Rf~uW7 zZMwV0MJI48lI2w5<;SG)Fsj_ACiwfdYVrNubp9_s~^P#>r9m5lyb*{l@2KK6@2Wiv? z#?;JpQ?0SMx^dYwE?dUsYK`X^LhEX2QYILC#6MrvMunH-vlRU~`WOp9CXBT>PH;~! z79VFEo?yCpfuBiVG)KF{l{I^`A){cH+l(I?Tk}X^jX7>U_b!m_at+U?>RO1xQgv(N z>y`9%zMN@^<}&v9(_nlm4My_`xvq(as&&shA)!3HB!g~>nzxM6P9n~HEPLn>3Icli z^ulE)BswASd~El)#R4Pq7fAXger5k6OV}@=iA-|^Y;*QJ&FS+5aFrx^syyzfm6T}s z*HiF&{O_vZ7eY}&8V=UO8!=^NWgC=fl$`NpRF5;5SC(YdE+?kIf*^e}iSqAaXCx zOP~7+o?EXrr6=TrHI#StggoR{TX~*~&rb}0_i|I3<}Y$EOQoJPluAL(33)^h<=y;K O&*p;c=ErrFJn=u_S$&EC diff --git a/bin/main/dev/loki/listener/PlayerJumpListener.class b/bin/main/dev/loki/listener/PlayerJumpListener.class deleted file mode 100644 index 8bf128a6aba521669f8b64840add7e2f77f2f0e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5278 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 S;&1pnS7ayt2mXa;5&It?FL)yW diff --git a/bin/main/dev/loki/listener/PlayerMoveListener.class b/bin/main/dev/loki/listener/PlayerMoveListener.class deleted file mode 100644 index 1d8b557d6dbf334c0389ee70c7e2bd0740534a22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6649 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 diff --git a/bin/main/dev/loki/listener/PlayerQuitListener.class b/bin/main/dev/loki/listener/PlayerQuitListener.class deleted file mode 100644 index 931b260fedd397e614874acacf4ab00ba508fa90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6001 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 diff --git a/bin/main/dev/loki/map/TemplateManager.class b/bin/main/dev/loki/map/TemplateManager.class deleted file mode 100644 index 1121587038c699449dd97fe08a8adc3871b18617..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5938 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 Q$3Iz6V|beDA+8ED<%=@nQeeXNx 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 diff --git a/bin/main/dev/loki/mdbdBootstrap.class b/bin/main/dev/loki/mdbdBootstrap.class deleted file mode 100644 index 04e844c9125d4301fe9cabb13614a9895e4583bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 541 zcmbVJO-sW-5Pj3Hv^BL_wRrVbJ-7&phl-#DPeBEx_f4|Yt!Xx-o8sT{BzW)#_@l&0 zQVWV8c-S{PZ}tsuXWl{Oyxp~NX8R! z<4;v!9W)3>+K5CZDxC#o6iJj#bS(TYvA8XWRWm~4Ovl=u6RLy#F`+gxp=zUwH5U$= zgs!J!b)C(8mEKD~QiPso0vU~Es`GqF*6f3x6L!7dO%DmJl?lS>!28?k%H+tzRz2Ba z?#~IzgmCEbKjCVQ9<6?@=W@Tv1EDjazVj4jRtN8(sNctQKQD7%b} sf^4G0cei|ib#yu7JzDPd)Q(mY!||vPrO@#zyJUM diff --git a/bin/main/dev/loki/mdbdLoader.class b/bin/main/dev/loki/mdbdLoader.class deleted file mode 100644 index cd5429f63e311f33b4706b501ae975649b802631..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 534 zcmbVJO-sW-5Pj3H)U-9)+TOiY1@|O^6+sK0f(lCSn`CLXZj+EE{a>C05B>mulsKCd z1o0pq_RYSTeZ$+CkI%Pv0M{5fs1XK{+6a?8Yq5%g$WLUXG6xO9-coL)FfyKt`(UZU z+(CaJJ?DtnTFQG~vqgwo7prY+wl8~H-72}A!EuMCLPwhZ)2%ZL?Chwrek>|j;!%T1_j?Lp&xG!b7 u%h)QDZS?rwtsY<(9y8t%_8G1Cj8DzxehPb~a8wnyLM!cKz(_bKg~KmmDShPt diff --git a/bin/main/dev/loki/objective/Generator.class b/bin/main/dev/loki/objective/Generator.class deleted file mode 100644 index 8ef29ffea55d9b152c2d83e12320723183a4ed03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3986 zcmai0TUQ&`8QlXCATfX~Y;0o3p}Bwlqej652V zIF~kQ)7;uV^r>0NN*?m;wbHI-Y_|`6>_dN4SNC^jG#bW3%fp|NP^h z050HfJocpEoVJ#cnZkUA&2iPG&i01#uh<(+WuPQcYp&V8 zBkO207hHGf)QMWmDkD#4i|EJWV)Y3FWU*Etiy0Gn49INO#2|)bcG5%vMVbBB#BeyP zm@qLSdrz7e4QEf87{dYC`-zEzAh8uF5fSFu9#4W}L0 zZk-+--Q!W$!r9p>pwLLdm8yOVbrX$n-+q^N z>_(%DEH%Gr;tgD*r}nnjaRY+-YTMgU-7~sg$g)UAafj#1>(UB?8>FuLwZvpDrn|nx zv_8=HCE`4Aay&|0Pap(-$d3hNjPjx!cQcX{){IzOO-qP?Kd_lAF9}*c2xVrxq3U!| z>r+>O3>}qnMWQv*=umwVg2r22K^v*t?nTw3 zFV(NZDQdH)_jF7v`ZrPGs%rU)S}m$LxylSV+iJ~eJ5-truImNbAZvdjQTn|*y5v7M z@mu^ZEU{`_^~K9x$FHjw9Fefm`01FJjNwOgzMr*Lpmb1-I4g-1>5)Rju}@@3j}#$2 zQiAkI0n#JoM~@UAj>m{Njzjz&=Bh?i!7p0J=I&$S9*+M_pM6C3hz(58_7O~RHWi*E zr$@Px--VH(XTqsZBcF(nzvt;Ze_OEb;W6vjE~c%yU6ifaU0BxWF6ONMUChhplx6Jl z7-y&DbEd~&p1uK-$nm)-kohQ%ll#LsiWB@kLLO6?A)h(Up2TCCrNz^<8nax8SuW_v ziBAh6;^b%G8T>TjTj40a93 z7h1M{NL`-KynGJNMweT3S6rGu`FHS{Ci(JRRPW-&uaWP+&COT3o6G#o`s!QcbGQ4& zzkcmsnB)Z(!&BPQM2HrLZyv8=I4LJJ&Ze{@1cxn0n0GhZF#VFYf^XX<-$qevl z=H*lA%U3clZ=o4kevb7g^*kVwaVi~_HyF8V2`>iXunb_E@+K|p!prbtA>Ea4W)f-P z<^x1dQk~L7-X;-yA0j?=SBUV%im^g%8D_p0{*~&$P(m9CI^AST&#`#qzsMj{r%tD% zdp&`Yk78q>gPoX2BD$y3PBrP&_C8L%qm|IWyLckPS{80(SfW#>zr%=ijbpAs6&KvF zWkz+Kx7cwv`Co85!LAgsi+q&+z7@x-#+5)%hS1|2=D&t%-Nk#9wLSV3MsFv9Jh>P7 z2$4R(hy2QW_Zo{UY(19O8S8k&Hq`o%?fZPrQPmB78zxzt;$%)+9?mq-5aZn8@>_Wkku*p}T`q*`fP9 z!77y$DP#V_!U%jqDA0WP9)8MEg1HbG8Df6;>U@@Nu|FlChvI7d0xP^H_n(b=y&(7b af-I+{{Lcx03vmhx(c56)OM>*_5B~*;T!rQU diff --git a/bin/main/dev/loki/objective/GeneratorManager.class b/bin/main/dev/loki/objective/GeneratorManager.class deleted file mode 100644 index 854b4d2c5a1640d4f3b3ef46fa3bb2d54e775f5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5264 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 diff --git a/bin/main/dev/loki/objective/GeneratorRepair$RepairSession.class b/bin/main/dev/loki/objective/GeneratorRepair$RepairSession.class deleted file mode 100644 index eb718b7dc0eff1a9db1f6f2c1957e9d8663e2f39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 718 zcmaJYx15Pg$`rb)N$7Lo!53axr*1L~q)i;z$xpi)#2MY%hhQR=R{uGUUae-?+R z5(j<&e}=C+V!VL^2y(FJ!{hh-X8h^LhmQcBVY`kB;qj0siLseZ?BI-3uP2bh|knSB}V0=l12SJLD#+ zSdFlRm{8r_>o*|85w2k&c&!L^ECz2qLIX|0YES2UJU$pZqZV^uyz6>$(RUL2&0MG!7K$y!1rc3Hd>m9oCwxxz~4;S_6~M^oJB#0OKf z-%CLSH)UTJFyJ$4_#!Z0v4U@C;X7_g_Q4DQx3M7+&@PDsO}nHH1a~B=;4bcoZ3?w~ M8@bnz=Z5^|Pcsa$qyPW_ diff --git a/bin/main/dev/loki/objective/GeneratorRepair.class b/bin/main/dev/loki/objective/GeneratorRepair.class deleted file mode 100644 index ff4eeba7af83262299c7e592e2fa647250b8548c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11360 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 E4;E6CkN^Mx diff --git a/bin/main/dev/loki/objective/SkillCheck$CheckState.class b/bin/main/dev/loki/objective/SkillCheck$CheckState.class deleted file mode 100644 index e49e9e45567952f6ae6559a41c039f2d9b44442c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1990 zcmaJ>ZEqA+7(KVU)7`dHx|CgLOKG82?M{Kkl%n=!DYT_jON(q<1mBqM-n7$QX4aWm zpjA|qpoxizU&O?iNHpOKQAt=xH1WIs3;7}9xic#*Se>MM&wV@3d7kIo{_)o@zX3Rg z*JG#?=qt!enUYhqGS1Sf%=^|QnaLHcQfYie=8L_-Z_YP;8ADVcv1(p2GbPhr&ddeJ z1>)tBxhCD|0(WPE?TT-eG7AgS6T<=x%hHyv={v4K*UT2NrvBMihu0ljGMMWNhzWt1 znortfZYevK?MwHx<5|At*aFS2Lsf*ivXnfb`BuK@@!qsR{fK2-epXhlKmbD^{r>-8hcWDa#e;={U~KHBP^bV{${^TPog^j*~dVMc)ZC5zrqSltv_5&7a|9!=eIp z-V!bHpIT^Bi*09}Pe1KzHf4g$Ij7?0VX;m)tW-ICnjMBe!%c?ZcdI21}1y(Cv{zpRLpc%k^k z2vKK%MpcjiWq-xMxz@o4cyTBiIilUhk(9RQJ8Wx@whrCL$l2TINol)pA(_%TzYmtj z!sRBOIIiGzO{BC$^46o@xiX6ORiH) zeLs0;xu(%fz%FQy7_gqk;TOXI%bwU7Q_Y;i>9Atl51Xs0>ioo8q2a@(e!i*hT1`s? XuLY;hAjh$hG=fdP6^E*Tkn{+eF!jAcEOD;cIayr>sS3St87*R*9VV`|nyX3F0q z&|Eev3x*}oHeUOFsW@NEa%MrdbVu`SXId|7h9l4y?g?$2Tfd7Rs+w=zx9dt|-)zM* z%*=#V=7!dsv0!Ol#nA;WtY1A|_j>8l*hsdK$5WJUx3tBIlrMyjjhx=*=hpcF6w;B&VllPS1=@P0r;mj*gBrpK76${85qPhGlps1djBF zwtY#$*9Uu_niYr*+eJN&D7sW^#SVdJe`>as&^uK$p;?Z0sZh|OV7I{LP@VIdyGVuN z=s}mSA)S&Y|LVXZqM&wnz zPu5a%rCg*oa_R#rK8QJLXt<--%Z8&w z*C5NJ6Sj)7bfVR^a+N|scNwfrh8v9Y%ocXJd@H5!RJ;c#q_JfcAC|_N9ev4OrcNvP zh=Lc{XKZI7GhZo{3@>xWf2jBinulrgFHfa4nhAEzs{nA*~OQR{nJrpdQdoW!X(zJpg3d{>~iK~JuAr|PM%;(NHk z!et89E)&zbTQQl+LmQ~&8&Rtvvask{K-7%4 ztb(8C!DZ@h-?(j;D&_ig$a#)oE!5Af`*3EZtp9(DRg(|@w!RJmv%{Kc=Gb$yZO!;m zJ9fxUaZANFP-s)|D^3J+w^iKq=YGctmid^)>)f!Zxvp&b@$lxP;77Ju(nY~zl1amON2CGL*&Dz>Kw?&68`;9Yd5-$c)qRqVNo-q(DbKK|WC%hGNP zTX?nVBA zp43amw4bI@BszdW{yWI`VET|V zH-ov-UQmaxtt3r6;r_%(jxkA92a;}7^F*E+a1M3b+w0lkJl<1Uly K9_M468~PuE*38%d diff --git a/bin/main/dev/loki/objective/SkillCheckUI.class b/bin/main/dev/loki/objective/SkillCheckUI.class deleted file mode 100644 index ee59db9195ba54ad459536266f3477ea4f499a98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4797 zcmd5=>t7Vt8Ga78ncW>_rQ!`u)`$uytg*&KAT%hbD4>R$*VBoIEWkLXcLPYy&6 zxVr?jj<(LWlO3&HUCn!11-7;)4JVoyOW9^rkB=BhCu18?$2j9ehs>loWTeyjfD!HB zxWgMa2&j!QixW@%Fq7ch8EQLycoIx`!u(tgP zAQOwl>A}=!4tRk*RqZKzAljcvBupntKuu>XdeG9x47*`|d6jPHx*Xjx8mfDP^klV$ zHF$=0_h(Ei-fN~ay47N)hbc{jsE-&jI)2^Wn`xpUZXxL#!*34J2x_L5Z zb^z_@RM5cyxcECPwb7Q0txE(o9KbF`{YF1JrMKuNgWx@oEC7g*M48*y^!N+f%2@*Jzz zEtbCfYgNPrs{CqrE&D*$!O3%zA4anOba&n6^Umb?$@AHpb#--qKno)TJ7yWWEmOnP za9Z}GpgZFhj{qzr6%0}Iyv=D^GtrR3FbmLGR%vz@+Yt~gQjV=5Emst|(wdA1IhWBe zf>F|Pz;F(x%%o%32UBTN($ekrEego=#6Mj?wh+$~!9FlJ9;7Uw&7`J8Z*^aotXw zbX(8E%a^3ucQw3+iwu^N@&q!Kn4mK)XE>E%&r#lv;$C;{Gvm%6VQS;l6l}zSihZoS z7yqF9QjjJWR?d?D$PG#}S>zaiSfWE8b}t_)E(?@D>WzoGTk9jfpT|`Ef~I@S`s6DW zpE7_Rqz^BDq~fYv^dLFG8xMn(tGTk$xaHGzHRG68w5O-7rJ<#zC6D_mz90gg=wlMM zU&%|*m$WNilvqE1GZSr^b7M*btx>(U)y7DNJveeUklmvmwnf7(Y9(iVN*0|Z0~P#* z(jT{*n0KWzcFfpq%I>}-=V(t`o!rV8wI!2=z01i5)@GW;n3g9i$KNRJ+JXTzD z7v(dL1l=Q=w*kwsf*S)^N&TM2i?l};hN?{ysOY$b@aB7Xwg85mVt11?WjPU9;VO@K2d9*mPbm-k$^&S| zP9K1{kL`vU>GCeuk*j- z`3B#L0KPY+G2v^hbv5d)MyWgIkEqyqqT+Q_TuH_2QO;IYNnAG*Wr@8P>)I*B15=83 z5_d_IaLqli^bpk6yl`%!ftwkj+G+B_zPzCPx!^%3-eAlYQQn6&Un8-XkJt9qjKkSc z94_6iY%EtUBtF=#R(s!p6~*2lcpqnu+{M}Y(8^HR>*M%-U*UG`26mKd<-sqon3Lz_ zC%T16#owiBaVJI@>2d)VVjJ4H!! z+2s^-4i{zXBOpP%En6KmhuMpM%uz9Qy^f#YeJ1#7u6@7}f4?BX)9;h)wdluBISSH- zBlrlH7|v#D{+M$benu@7DE@|q1r=C@g@uA21!ow+B`cHy9^;kwiIE5{FcLq{7l|ti zh{PweBJoQ(lQ$CkiAg&R?;u78h|WRca)^k$N-VmGLJ#rpqr-<8i6e}}QAXkzBXOJ< zpI{{V7zv$`=>PwUL;#=Rb3YQjeol;qwI?87cI_^%*N3Lqug+qBz+-=K7W;oa3-hn? zVBW+O22RnS0rF{(c$-Y#1j~elIt(!nlH_~}o#bjSUL)c*(Y3fEL$;1g!*~q8#qTH! z7;~8|i^!PEds(8#T;3N`PX@mycljSQl>P^fRO&SFM~(v2d>nt`C`kQ>e70|z&GtIU f_CL>NdjVux%hG>~-(?(GxQ#m$e3~H9|^!N diff --git a/bin/main/dev/loki/pallet/Pallet$PalletState.class b/bin/main/dev/loki/pallet/Pallet$PalletState.class deleted file mode 100644 index a08f42c6be1324a7806575e020b27c64efaa0306..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1196 zcma)5TTc@~7(K(b-CmZ9MXOxAVUe~V6%jOPL#VWBLum;MO&Xt;GUDQPOLn&;{3|UF z5RJrVf0Xf?X@z~j*nQ~iH*>x-=X`tm>-V=y00q2KF~l%)z)!MP`?HxnHY|&K*=@Nb zdyDQF9#;`y7&$UdjI3qYhuM*Ny{%-uP}wW#46`2wBMRr6mT8;b8iSHb*BJsE?E@Z0Fbak-4Yv@dJMw)F%$#hA=iD7j(z09T316hkAiKi-N$%Rkysq68UhB>4dB8KA_ zr_J{9DMQ9@thRr|n_jN$^ZIv-%+m0smfA;#*Z#KtJko;t6 zck>nNwF?m%%0N_acbq1FYl;EJdLdgBD6*!ThqmE$96DL`k%`XyAo|vbUn|=-ccdWh zs(8texH+3wx66oAoU7dR-nU(EeThE0LjRD!`h-XaKr019u9OL2Y*HjbASfd-XoMf8 zsztSU3g5vR@e$=5qh}bG#hrjG60*1#l*L5o2jP@1#`Q*^i-g_?b}^x!Vd^W94B7q0#6pc&`D2DkBwbPh)@N+%~w(KB?)3o3aV_SA`EL*N^Y)EO$SeiH!O(aDc zr%C#tr9gPLKua2j1&cl)EEX)lD>j%9?YDmD$Mz5OACw=!g6?}~B#&H$YT3GX&YZi? zYoBxVk1s#_D}WKatD#O{PsY3$xAR#mUNCIibmFsW(GV19IcHon;qE#T! z+qW1+JN9Vk5NN9rijKYL6bPm5e2&iS?d_|H9)Z9<9U+7xxC7l9zA13$|My$Rx1bBu z&o7M3BqnE0NSFgU8lXqH`?ijQ(#z(I=`ic_PH`>mtQF}-bJEJ0Gi&Ep%;JKvVpGy8 z1GN{8q9va_VbD2im1O>Fd%~>MTcueRHcPGjReAH5sqa(+25`5AL*$7sM?M`Laoi)I zt(wll<--3aYMMo&YxYnChjB#1V0E_3uXTJ6M+Ks(k*Vd`1CxRbo3!6ksi{apcpuR5NY~)Dam#qNiWSwhEs6G6I}5GkxR37VbQQH z8WX43KUa31qb1Wx6!V3GnUU;zSjVDdjh2{8&CZS|WN{wR@hEsqqpDkg>Ncq4t#2_r z{BIScit@CMWjyYtYAIi|X}!HVRZ7YvtstX;p|to2FrQz`WptQ0L-}YjH8!=plu9L* zN9V>zrW7Z4W`oil3Jwnr4mQ9-R>Qe!Fl9)Gjq{AYU>ld!34wtsURL_q--a&s#6;g> z1bJN0P^hNYtWk8Vv~B7rf=mx7S9dY1tTPlI{uh1ZCp^5pE`IDTC6Co= z4!Lf#`7>6DnrU+(fBRvckX`o&9WS9%&hvF0H}E^Rqv&j zn}!*)4#NSAPc{s!20A+*X{g1b67DAdZ)qgIX!wQ~G(ZRCkYH1WHcPmfW*j%#P^ z6STzox6rnUuGj|lZ=xr*g*!i1C%?n*J;VoZtspvy(}gzd6fZBAW6= z5Sio4vo!5lYU$rbzrY6WeFvf7`+@hVAAqzFrY6wsLu{!aw&44WLf{8VTQm`jcbE$; zUiU)&G)*r!?n7HUhMStUFhcpXCu%MWW;{Vt6SZ8O`-2r(vnL6~2DUK1 zj^@}QwQ9ke2nLRZV_iY@+!E^w`Cn)q;dLf+U=t@|hc+>J69+o9b+l4nin>Bd*0`e} zlkBG8Bx3>-P|v^{nYN9v@*!rLhOsk>sw9=vOh#U4S-9nBgu+O9oQhg=p_2X7NLo z<|;MkxYJY#`k;M%KdPM3 zU0lx@foE&lR9$-uv{^|cZ9Z4FPn)iMx6Q|B^E7QP)8^x}Y1Fj&BKz8%8i%>cIP1Mi zeZ+m8uZPe2&PyuGsUYM~_0AusJ$b&pMx}RSo%dn2SFnDA-+EYat`aLmte)M6FZd3J zDu-WY@3?`Ccm->che^oVBgyfhG%Ozwc*yj9`1LygL|?z+{Lel`#oOs zf?Z~?virI@*ssYx;{O(|-+Jk6| diff --git a/bin/main/dev/loki/pallet/PalletBreak$BreakTask.class b/bin/main/dev/loki/pallet/PalletBreak$BreakTask.class deleted file mode 100644 index ee950e49ef46ad98af7c50dae5b479c0d2eb47e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1786 zcmbVMU2_vv7=BI@nkL;sO;hAcK}jVar9mj51QA*bL_&$Q_JS+7+e5nSb~o$?L)CG> z@lWW#V5SWt7hHPbPjVc`=bXf0gQhZE?7rvYJ@5Ox&-sr(j?oM%Cz`fegmz+q6Bo9B-}5V713>zUf=0yJiNqn)eseiV%TQ|BqL7QW4X` zCvapqXyOWDFNfp!AcGUc^xwTS@F7kLWZN=oY4QY)mCDJm(u?e9n_MUb)WV1$w1(b}bScp};Vffkq7 za^(AC17}qyMlI8`q?^S&E@W_CV0MpGy}OZ+rh$w2M3Jje4az?Ww603IWT1}Atdc1; zP=RwpQ4VQry?jqWy<*^VTxHQ#90X)?)wUeUK{QmJ1p|xtf>P?RZk=f9{(Wgh0vAfd zyEH6eL-93_>jrM97NsMmQdt@XzQiqo3CrK=@C}h~UlQ*M<*Bstnmh+ILJ?1_M5g83 zHaq=WkX!NNz>?Q(^#)BQ9?`llJsOXM0FwPt;dO0vMfilV?TOuj=TdZSY5;>@#u=Csp0IM>CeL!7F8kDmFgi)(7s#nR6> z%#jY-cj@A$j!h6Ls1h%+FyJAn3NVe3L`Eng<^%AUd)rvTw`kxyD(44$gC`{8DZa;# z9Q~xJIM^$wPsJEdG;y2dE;H&l(tlz)gP8-x^GtV#OCxCEE809qf||TbJ5RepyQ=rA Fe*+^u&eH$@ diff --git a/bin/main/dev/loki/pallet/PalletBreak$BreakingProgress.class b/bin/main/dev/loki/pallet/PalletBreak$BreakingProgress.class deleted file mode 100644 index 58188ab0c4a51f4fb9b01158f242516f11ac011c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 846 zcmaJ6Oq9gfq+%0D6G4sBWm1=}yJUCD|M8s{ z6B`pB`~m(b4)5ya^@3eH6wOBM9Z^CFXC z+%|WVjQUwR%4D8bU=zGEaUp_OB%|QX@Jxn^P`=6~)O)kx_6Uwjm57g`aGVpUOK`(U zmdQjFrn34J!J2OY1HwsA{RFE-TAUZ4&S5&qLisY%wBBFq+SQBUxptF8X8W`q1N^^x4H*N8EvEk`yu;l4k@C!W&Ry{pG)=GR_EOGpGmPV}G z{5JeYQ!M-6vEuJcal>y;QS+@S>R(ODExv0E3>-7u38%ip8s4Lh57=O9%aAv48%@?2 z&J>}k8m0_g+8x|2Nc$X3+ULLhhPwTcX?zy=)V^TBzO*jcX+e`Zre4AC&=9#-i3L&1 a#L+qjZ?agzJ=`}*{BzO91GYRg_VynKq_&#? diff --git a/bin/main/dev/loki/pallet/PalletBreak.class b/bin/main/dev/loki/pallet/PalletBreak.class deleted file mode 100644 index d51ef025c16acded7d24e19d16c82dcac0ff5571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3964 zcmbVO`Eyg(75=UyTbBIdML1pn7t;i6$%{xG2u2ixH!$)-u(1oJCC~ChJS0D<(vw@d zOi9|(C0(*~2_z}q^9wU=GsTQcLOb~(o#~Jn@mKVpU^@Nol`Or7{vEdqv=e_jAr$8+OVUi)MF%P=qW#Z0!^3oRXv*4tz>j| z>9Ucq1%gZR?Yx;tZWnTfz^wc2 zVaLxiXC}vDQ=b6pX$6hGPUSMmoRQDRj?jATVbe10BLcg6s)rL9>!O*A9@kflQS~(z zUJ&q&W|oa0ylB)=k0t?cPk14S5L*1$Ca}HYd(&|ZPoh;|Thg!{ER}hnmB|1E+BMXm z){pH1%~cLg==n?JA&3q%%3Ylr{HT*WnU*nASXnZ1^ZHVn+=Qkw2|c}_=S=y#yy&wp znPj!I8r$Y`BJ{M$s-5Poj7N|?;mhvMo_&+<5rh3uuN1s4zB`q$18U_%hxMWHc zaK_#fcA_&Z+qAC`oeV4H$1?(bRa=`hze!#}?8Bf`%CiDP&JZ>o-IAdrHR~RTsOIb(Ym@~i)o?IfRyUMOr3)`S0LO|V$!|Gsb*=X;6sQ+>!)be&Ft9DaeyuF;sbcGpSkd?HgApsUz zZO&N9tWu+Uof<9OXR(j1lZ#aA2k$&ry!qfN%i?PBU6#oE#e2JX`CYv=F7;hcbZ*2`pT#}W$ zs^QD{3O%yR$g9LQGnPP`yD4tGh)JJc)$lcZoq;Wzycev5F;58XE-6;_hsSD<)^U8` zpLBLr!;5%{DWLW;5+!PAJ;fjIQq(5reG~=_#VD5&@eJJI~u>R zI6FIb;l$*;x(uuLjM^FV4J+S2#E<>>k=vB=rQs)dg(S&VqfW5je|#)XWtVJEOvnMD zvC^eB8q@)o0k^)lP;`t<-#0vU|0Ca#`}aShkQ14eEaxjjY3KjC4HqPVZ)mtKscLdi zHFA3VSll<VVjv@gShwM5Mi<}1?BN^2T*Dy1>)eQ}*&NB9U0mM|%6#u=fUP zytn8pa>&==`-l8-7yHge`XYZp+Z}x7Pz}HA{HR~AiVzI*)8eYdS4GDkVyBcSld`N9mKnxh<2hIoty}E;V5w)C&F{YDA6A& z;i{lNk9nLSYGTC#7FBHL$S)>9N@IpE0 zS9w@c*1ZwUI&=^Ij(yX8AEHHuKhysq>ia{63QaOy!oOW%>ZZRQPQhVD5Mf-sjB7w) zj+D$+Fn5S6c9mH{M2#@0Pck zx>iyOk{iGQO6(w0H$*ToN7#cE5QCLe4VF{YjvbD$>){Io9wNxRgcuX2qB7DK=tR~? zYwtR~$(FT-Z@r6ehkl@~#K}iWEI>u;WoNAb0MU9j16An5e6%>&Q zibzGd5$d6qXr)TM5Mk2rGyJ>^?2n{D0vpilQg|ul?s)- zSXFGP;^H(o#neqRbu+BJX{K(Ls(qgNJ23f3 diff --git a/bin/main/dev/loki/pallet/PalletDrop.class b/bin/main/dev/loki/pallet/PalletDrop.class deleted file mode 100644 index 2ae340ff5d086f7058d56c991f11620ae80bf29b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4376 zcmbVP`&$&}6@I_ng@I)diYRIn5z(?-Tuq`;*A|h5iY%83freh}ush($vb)djKtiuE zy(LZBwCOFewfELuY^yY)XoIc2*rujk+NS-r{XddEeZQGmm@%Nw)758p=6vTn=RN1V z=X@Wp{`dMKfOh;#flpvdLZ1mI)00Lxqa~BN86L2HqSM+0=gk3dy--%#ht_KuLPVhWh>A#E(F6L2gY*OJ3p){yUxFkqfGaspe|a4B;|Y>Jtk zm5&13+~AVhtey=IPG@I~nRGT18V#Zrbqcl%Y+4D|tEFNG>IF(CbaTL3q4UO2ES;SQ zk4;Zb8fI8enT9zVwpSx%Xuxg-yJ&JP9Tjg!BWp*KGDOozrvz%eMhgp(AezvkpqZhp zKy=f?sfdbJ>=D>JZln@@x|Y>*<{)X1Fj5mXjRf{Kx?wMSh=$fkW~2mr1@_#!5YL~_ zUs-ypE`KwBDSw0i_>#XQUl;S2`FbsXHNUuYmcna0Wc&}RcnA+O!knH;^y;}BIVG^6 zF}6bBK{HEak?VYPaZ@Z6r@LdvRBJk zou#0g`FAn4U`;^}n{*{&x0N7HV0RG5(Wjyx1B@|Y$k`KTwKsXHRbX zNDw_+-1cvKpcl6-yd*#8N->Sc70h^D^=ec$w4{nBFw1oJxA&YHh_(0i@DTBEs-Q@J z)A+E8kKm&m)$y!O1ILo-_+(TwHG!SpYK+O1aDq$WWhD;AF??LblQ>K6?@`yWoWQa8>Bi&JcT$98;3fW>M_=G^itqWTIg{5cf@|R_2FP)VwpTFkmZmYLH zrQ*~041>`!ndEHe6Q{N5oIP)NWVjgNZM@L1f@cJ3T?(1B+!h|Nemcj;c`ldYS$s~x zb37aGtvEEBVYxq#=gIBCSpP_0=O8Q4;P$_YdAW-Pc^Y4oXXy(9%^t*S?da|v9Ssf3 ze)_VCui&dP_C&&sTNd&@zIkYpN=8l|F;0gT2ID>R#-p|g=Tv+h-(dMk*!E=7-pJFu ziuAFLhH2AChGU!|WXm`4Z3W*FSm#|)@g01Z6E0_xgi`_!c=p=TFi#gQMyl8h-&gSi z{E!zAlP97;okx9qIu*C8m(>#n38vHWkMI)(Kjw+N;@D$W#ZPgO2*!;hyGY=WbFNw7 zSFz}h&0~o81b!~@{enl8C-Zl)&Xt{297xEQRm|a+q>+}IWz)t_3+%WbE>^N6sZEU~ zw1$0hp3JMbDyMj`FvW+`yi@WL737f1#`P{kUdt-%vdQA_kr|RhHJvsYnU?9*&C}^b zE{IofQ^6wnZ{^UsvKpzG^rRk+Sq`bFjcai;ot;(jYy5_Hg{c*hz#aEp!P#jWKh8T% zQqQqR(v#Dfh-(nA=<-V8l6W>+UGsk}+Ai;H*eS9*(hi<%g9a&8QH)>Rb^R#}t1nJX%qN-%F0Kb&Q8-;8n|pz+Y6njDvLc8f5}%cPgc4JCa&1 zr{@&>U0~N+im_Ts6}-*?cW+g)-_AdFkivepnIBtFgkruaeDk4%??Kml8LH$xpKA(r zDp1MqxACoux<38}o35g&srd>vT(AZpNTd)m#P=|v|%Td(h7 zyDi`k+mM!l_n?hBJm#5#c53=)=@2>)rJwDz)Jb^&@1n0N_}@U8f`&Iyui&_X6YHtX z3$qjMGfud*&323}^N1Y|v`XN;4E4qHC<wFxwa(*{k|uUV_OK4XUS@J1 z>F^L~vmZNgfRQ~yFb9eB0IP7A=pz`$5i8y%8`^TbBTh94*NL}?G0M95ts0a-yn!HV zzz}(Da6%j*%_Vtjns4Cg$L8?a%IYG&|0=$)fG_zlvclvl%Uv5G9wqbJNS$^IhRx=h zWf(P1+6BIb7ab>KbRnJ8OYY9&r3IW9xQ_1u3%KAz^L6}8K3?)cme^;J)b$(Jql7F{0v8Z)@klniY+%`zs`XrhYkU`0 v#){zEa8%BQ1q;=6+~BW__ZDTp!=LbH>*)^uiaeIMCja328~%ZRV)Oq1cCV%T diff --git a/bin/main/dev/loki/pallet/PalletManager.class b/bin/main/dev/loki/pallet/PalletManager.class deleted file mode 100644 index bca417af91b85c198bb6e0d99bb4c90f85f313cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3730 zcmbVOX>%Oa6+KV0v}V+@WZ^|4V{D9NM)ES2B?$5e8(YFy&PWKP7;KiLHPe#YYITdA z9>pdkYzbS!ngz#!@KIm*099a@?J6ptsr-iI59Bu>&U@YJ=@BEjDm7KTym#+?_ndR@ z?fL$P+us2=g)cO;2<)zy%LUtAunJ3tZJT~!O5G+5$Cx)g4M~B{%f_-%unlLv@Z{`e zv+N6KfpL|aCAC}gExS;%s(w)*Gi}W~hF|kcf&O*dBcf4SwTYrjo^GEvJWIZZi%I{IMe9BF zRGTp<`LNe=7r4J}y#cT+?!#UUdl)&Qs=29-`>{_TJ8$|??p^u5b&MC=upb9B^a^aL zvmy!6@gVX7t(I?khVOa;I~u&l!*xdJ#~}>|Nkl!u+OCenI6^HP^9l=N+ggNJxfC@V zCF`y?Uzn{eELeUdriNoYG=kZ{Uls!xlDa-5(48+e@n#K3Y(LZS2!<)XQK?YUe1JcG ze&0ojpr~U6kFs_z8P!RZEX(C0{U{Ipnw}ugKJ6Rjg$ZLRR6WB}0=5Nq#mclHcU7I~ zV2Rn+HE*;M&^>d}T{eS&63i1i&Pp)pV1wsV-BY$5Sg_mJRo6DzUyH_-r^67M6S%Uc7cFNj z%!TDC)8eTNtN4_`3>~v_YNXU6J<2wnPkZiy>2z^KnmXn%PhX$82<&ZOey-*y{t8o` zS+O{qOx0+Xj>}k32T5Va=h*Ub;+we18k8!}xV~YJx;2Mqu`yfjn@+5Yo%lF({;Q6^N#~4J4Xcgbf8jm{ z*0|%C-l%OlHAH0EWUn`fLymleUtIlgX2jUiNYl_!sVUnB*8OB@epH=3tOU9e!5rb(67N47MJfs$&#mj3n^*h7r#Y*!qa~ zGUD#LL>$LHo*t-oPHFZqF$io?=6ZcsWr%pWJhW(uYo)y9#3*b>b^or z(!38zek5wLTBFppoOT1xUPpQbyKO;hPLj^a4M$}9nBS+(TJY~!0!K*CQPMbogM>85Uy+HQ#6wK^C?@!aNrF79gqey!PDLQ6@SFmfpzZSt zWE$u20@qTE`hWtiF={7XP8p%DCu4Qm8v@=*L4wMEj7Mw@ zx-7x;gGAc-P>wP=LCK~3oidZ#r~tQcsYz3u=4=^_m2YQwn1GE%MvxUS#Jh}@4Ny4( zU-B*90B2$mvQdPWq6o6#WrUs}0zc8Wu`E;ibqg=Q6?kWT#B;HTJyFEhH;t%3ZWwX0 qNyG%+P)Ody?|GN=^^er=PxuI*sHZ>UQ(VK}xhLoAb$o_@BKITaP%ZTU diff --git a/bin/main/dev/loki/pallet/PalletStun$1.class b/bin/main/dev/loki/pallet/PalletStun$1.class deleted file mode 100644 index 57b782359d8846ab21bbe7d40ccc881472d5675c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1254 zcmZ`(O;Zy=5Pg%xBqR%o5fBj&Bxt^10r4}43TjE202;w6ZkuE(ELnC_`;jV+dexIR ze}PxEKtW3m9zBIWWZARCVxfxK+U=g1p4UCE-|U~iKMnvq!a@i>hJh+?%9>GE<%XhZ z+?H2dQ?eaBITb>HVbm~da@ncZRa>?y8@%dh+?40tiI~nYJe_X?zWauw=YT&x9+S~GqyGD`0Syfl7**Z@hM0tN2nz4Kgb>2QyC9(hkqG?gkq|{MgFhuU#R{si+`(Oj zsKxbakz1BhJ6%)BHdVcr7me#I*-E8eR2uCLMM{QaR`^p@C_Hw2GbY4|Y37Mu(F}`r z7rDJ*R3$vXL(+`kpP}fLqnBN;6uk}4d!^XWoSLeW%7t-@lNPC|=7OeJ7N@3$m$+p= zGc22$PSntq_Q&Hwqd+_%6zW>iC$0GCjY6WhPV(kx93b1B$?l>nliNi+Gro&N<~zE- zxX~Bs8>DDp9DVc^J1HKQ&`*}(GJ4xsb;1&Bxy%l_b}&FD{tZ|6k@Dd+4HEm9VE9OB z$WP4d%%PWlMT?7n4|v~=!ncM Lf?Ukg>%-tbEGR+i diff --git a/bin/main/dev/loki/pallet/PalletStun.class b/bin/main/dev/loki/pallet/PalletStun.class deleted file mode 100644 index 31e8b1883dd18c1fdecd1590e67c5d028650d902..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3184 zcma)8*>@9F9R6+-nl>F;2((ZZDNt(Dg^02TTDsCeD21dg#RaFyvR7e!G~ z@u(CKjz?d3;Q>&JwMQO!@f@GR|Ksua-APDhK+*JcmV57S`M%#afBg09eE?m!=0Taj zs}lDJ^CSRA#st)nii`0TB|Y zmhXlZKd4hdnu|4IODJpVi9kd%gA|GAlZI+$)0)6~=k6Zc>+o=>H`u}R<$H8PH#-E@ zHHV81#*)T_J{j1rp4NJ-$Dn^iz}=IKYhJieqo4{)1YFJj5ifjL?!huUz9+;L)S^zn zH>sH=&;?vn5~_s2N(GBh?!hX7r6o`UYUU(?c~OrVd1|c!4=N;Z-OvWJr^mH)R2@$c ztS_95sfiIat;_eqqT4*FlcqH#Xiso2ImkQgIQIkw$*rD|(P97uR@>-GCDdsx9mq!| z=s)hov+#S+EKpaZ)Nw{Z3t9y{d*wqY~KoUv?O2iT#LzqY_hP zcQ`cID?v%CQ3bvYiF$sSpS7&H&) zpIx2hoPr5V5|}I?OG2Q{K}yjldqncO`}_SP70^lSgB!62HxjuYazExS=B}@=z?6Xh z!Hpfc?{l|u3;etL@NC1wncVH%FS&(=+@0L5hckR{$o-bPpZiJjb6SCcBpu0UMm(yU zvgfqeD=%WEbz?GUtHr`fC=~LKc<>t2zSIuv#Uz_b;}$Pc$jJ0!<3D1r$H$KbZ8hmA zXFCCo^s;I)g)<6X#~T7lno~v1OodfbOAB;3=yVqI0Y{x?VkfnDmZK-oZB@QhBKv2) zsX7~t-D~TN)g3q{>|Q#JNlk?Y;W*{Q!iE?z)!5V_HT9_V%O)0@7|_k`>E3iQmD1u~ zoW+M8eBfxoc9#^K!$*v!o+(IJxSlapBc?@}Q7avai|Op|E#Jq|kU#nvOK56ZI`h=g!(P*l zOA2OX?<`Mir;}&sxtG^TGpnmKgR^P>% z+m_Tby!zngbs4YADP4;dsKYw0)aB*TK-==S5*x6Q+S#PBsbHm>XQY+tmY=bPMw;f) zR)(8gDTCB4eF8rjO8Tmc`l|6fUa<5rCV72gClM{8#H{pq`xUrv^S*PpyWagfpG!ve zlwq{qy@1ZKJLux_iX~o`>mK&c=CXkGV=154lKge3A*5Q1oJROb%?=W@7ftBl z%pKx=gsX9WXq@6biB`-oH7*eHC2Y5d*_wx3Bxbfi3~9hL-n0mw#ann=e(~Wv-od*J z)_b&HiL%N+QRQJ*6nOs;i@3&Z$zoI69A>UQPGY^A%O78Xx23hMeGZ?MK&`U!Y8PV= zL^bv>A36xOlaRV>jy4q?Z7Mq2RCKhd;Al1TrQ|3-Rx9$3E+HHibw1vlU2ZF@Yuj3_ zkj&xp<@oCIbu4n3TFZ>!+1i2=k{K7oGTQhW-xMtEr(Kz; zH4J7UQ@>@Zl*+(sZ4VH5$g-19e;M2L6r*4PtP7XwD_rC!k C5*x|@ diff --git a/bin/main/dev/loki/phase/EndgamePhase$1.class b/bin/main/dev/loki/phase/EndgamePhase$1.class deleted file mode 100644 index 2ebc99fb3737d4739249f5a24cc5d716598bd866..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2350 zcmaJ?*>@9F9R6;ac4#`#QWhy&Q6hGsOpBsGaA`|`LK;e2qM`zmMs_~7x02mdJRcatWW&_d3coV$F#@Ba4RzyJO9H-J%mtsx??FE1Aj z+nu+J;+*MABkAM|=7OA3oA`)^sK7zjD;U|*{Ja$yer`_YOSbfkvC6@8$#KlAEd|HC)J2<&N~bFL?ivwVD}dP!{CDa)~fR|FD$4cvM~6OGGt zB>fqI=(wAg?GV_kqZMsx)u}_nrWjhVRYyCz1zP$Pv@>NnGF@88N^iDmSa-_JnRdqX zEVW-dj4EpddK(X~*D5|j3tGIA6GIR7XxJ^#Q+Lgydg|DVeFCw945n;zS$bsO+Si}D zVJ@0RDX?r~(kv!A(2J)v9H1pl7doE7LAr~sElEo5YLXmxZCmC7`kMsL;yDe61hzK_ z8uvQ-&@Zsb3Z!QSt|zdwiD_c(oIHaV(r{RyyTMbt)o}y{z3#}RfDhFeY||+i7qd60 zNvbI_vbEGJ6)bitRgLw8UC3wii5T*DR|5q%H(lr`V2-VX z@l3hd?DC}Pm<7pV>J3xebUiz7gaIVH0b9d7+hUz?Jxs>}s844gZCP}^VAidWu=6%K zw7E7^stuy3<2{xC8ryrC)v0Xtbp$FQqJH2OH7v3SDkWVh*W^-87FFjEh-8bbzlICe z)hu}hA-lsV(X0d?QBh=WhcQnIEL}Sjn7Mg2zqQUAn{i8CPM)#U(AgRuS4WiE^h?so z*{*Lng-IFAxp@trhW)v|PwV&`Ur;rEidbq)+ZfIe{e0k#bMiLUz<;5PoZ z5eR&P?flm(>rU*zPVNMrLU)x$94ARD&u$O=fh{Z8RmOgSGU5W0_i*)a83O|UU^q3n zf}`o7hqy3Q#)|@XFgEl%PL(kh0Z+~-nezfXyI98M2u?&a;K zg=;Iw4XwZ;wJUIU^|$J=cb^I+Sx?tdqDsnuqf{ICmc!~h#PK~w@B{nqk3{{%e)BW2 zcaX(h6p2~JFZcw%R*W4$R2j5pY%eb1CYHz^M~b-j$v%b6_y8Xg_YslD5M3p>MI%OI ydSeym5#>(9F!vgpE0-m)N~s2j!XHyOf?IqT+}*}!_>wCXAmw@W`-)!#xBmy3ba3PV diff --git a/bin/main/dev/loki/phase/EndgamePhase.class b/bin/main/dev/loki/phase/EndgamePhase.class deleted file mode 100644 index 37635b3b016cd9325eb821c1cf682a0ba687f75d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11001 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 Nj8PmxvlJo@{~yfc^}hfB diff --git a/bin/main/dev/loki/phase/GameplayPhase.class b/bin/main/dev/loki/phase/GameplayPhase.class deleted file mode 100644 index d131d38eab8c25a140054bb849cf9ac91bf023de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13554 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 Xx)yDdK)sz-sOzXqy+hrAP^|1fL}+a4 diff --git a/bin/main/dev/loki/phase/LobbyPhase.class b/bin/main/dev/loki/phase/LobbyPhase.class deleted file mode 100644 index eb2771b59dc1b92ac3073072cf22bc44b957948a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6082 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 Px;!-wg(1=GfKy`gv diff --git a/bin/main/dev/loki/phase/RoleAssignPhase.class b/bin/main/dev/loki/phase/RoleAssignPhase.class deleted file mode 100644 index 19b62eec07486c6459a7ec8d670919b11ec2285f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1858 zcmb7E+fv(B6kW$Q2pgGOoV4L$%q4(DgOc=Kr%A&ll-40BWau=VKFIdLC^i-&3x@Ou z`p_@vLudNdmp(L|5SVn559pKgL!GW8X=I0#bo!uk)81>Xz4zJYufLzY0B{SN8e#(3 ziaapuPR%y=cC4l}H=Me>)oj|;#yz#ykPsMnXdPH)-D*_LyQPP+>}lv0$ei-@?FD)) z-&?u@qs7R?C2R+_bPEDW&o0-RMY-(>h&6hao!z~<^dz?r_`6xN_m*YddL+<&-EP?4 z4T15wH(}i)$NQKR=nbxl!eLsq zW)P{sNT53Qrt^OrwPByj_uX}Bq{(2$;4d*rybX;ltbhRhqihnt>j zH>!pIq>qFb@@LxyMjQv)kA!|VyX%J znVrOWNc9otZrb&spW^^`H|ZDStQqt1V+=m#GKLJtlz%)x^Ff^F{z72J`7Q3~;M4FG zQV&Q7R-#Ru|1!og-ZtisFk-}yFlLM%VZ4oefigj#1bLFg?jzb`Uo?!eZ^eVQgUomLRKgFe|m>Wk&5p_71M!=q>*6EkBx7hU@B1w_@{nG zPjDP*$dVmo)c8#4m}PW%=D?tmc}(GQhmPq;$MmZ@(&wq;lSs!3v#&~-9xD8SPfxIP zg0-*PX%7l|m1NgCz|#?UIs_NEi+f>$P0oUlT?}pPH!gy^p{@{Uu5zUZ1|f{VSH9K8 EKdG~w-v9sr diff --git a/bin/main/dev/loki/player/BasePlayer.class b/bin/main/dev/loki/player/BasePlayer.class deleted file mode 100644 index 8fa42f1df205f7ee189b434602d4da784079f8fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1692 zcmaJ?+fvg|6kVrHo3;c>3zW!3Kv8=EqKKlRXrVNn)Fp%XB8^WM9_ad+n9!@4r8O0!ZVj2oJ+hQQKFHN=a9$hI*jY zlqI#UZCFbfy00pRTHaOG^LtvsWDpt+y-1#%ZWRH45PVD zR2y-VyD6@_URB?hbCrT>>XkCXK(12TRq~BeNjH`MW{UGa)XTcL$j}$>ESA`zMwTl@ zEd(#Z61vdK;EgACf?$YB@WCHMKVl*V7=|xsN5UWi4B~1wo!eS{#nUfI5V$+fwre4Ho6i89QoC=kJbDFyHERhLKZ4x2U99#9htYwup$>L7JIIc5Hoo4HNJca<3wl>2sMwKt%ipB`ko5ADp z3uF0)dO39at_RzPYi^qpKO-TC5T)@V?P+q{Jwh{!7YP_mAqDjMdfA|@Sz34K^KuV*y1 zxL(WF3u;v>av466=z}9g37Kp7^OFYunIB)zKk&kUZInb&zJm+$Va-^kbcY9Z^7_RD8PYX zd=T~`-6TF^Ykb1 zh$?~Xi_MB_RFCgarX9-1czlSkeOo$&&wC`aYTBBZbFm>i^>`I8Sd4(OboF56AE&81 AL;wH) diff --git a/bin/main/dev/loki/player/Killer.class b/bin/main/dev/loki/player/Killer.class deleted file mode 100644 index 6af8a1ae516feae6bf88a86d91e9a2067ca947c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 630 zcmZ8eO;5r=6r62Kfwl^Q0>a4~ps_yyL!uaskr)$&1GfSjU9HsggM|O&#YAJ`!5`p{ zGQMpIV$)>%=Jn0IneF$_=NEuuG_p__DpNkUUGGuY&#trJzI`cNm-|_04E6N46DQ!; z@fbsH;`shT%%{MNeby-#TNLGnD$?#Bqm?FC<l0xbY%?!q0>>WG3uG84P>mU8NgjP-FnAG^!~Soq0m% z)K}>@SyYVlE5qGN;qqY`7 QUq#U4n~@QAiLIdi3(&`8egFUf diff --git a/bin/main/dev/loki/player/PlayerManager.class b/bin/main/dev/loki/player/PlayerManager.class deleted file mode 100644 index ff702c03f7f79a579c6ce388193338e83697d327..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6803 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 G2mb)lLw@}L diff --git a/bin/main/dev/loki/role/RoleAssigner$RoleAssignedEvent.class b/bin/main/dev/loki/role/RoleAssigner$RoleAssignedEvent.class deleted file mode 100644 index 128db7f6cf062c4ae7b4e50022c848b1836cd38b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1610 zcmb7E*-{fh6g?f1Ob8=c1QkSZ0Z9gA#08fi%A!T8B2sJ*`qW9fU|^Vuv!se&@f&=Q zDk-aY@B{oP%R38XAdr%W%$>e{&pFel@6DgT$G-v0_4iF-I1=Iv* zVKEFhDrrzEErj#~01I=mvu3tH zydwQYd?Yxl8JaW4poW62+itnje#6DBG`cV<;~vKRlW$SGd=$=(SzqNA-xrRs=oIO7 z)3s{igXZ0BF4BM2l-F8>SujnO%s9xqqT^IIf#WeTaMk(S&*cg#a2;4Ymh$UgyEUn>~RurY@)JEj=p}}0VG-~Ry?zE%A|Z1DBzrj|M~c@&$T-n@Dw1-HKHxlvo$BOh zTyI?f8UVhZ`?x4*2zNqIfs|rYnNlW>G298oXkPA9t>=PD(Q_-K{K5le;s`y;8*!GkA#syg~_YD9-tq8NBr| L9-DVh{w@6jDT{t> diff --git a/bin/main/dev/loki/role/RoleAssigner.class b/bin/main/dev/loki/role/RoleAssigner.class deleted file mode 100644 index bfd9a7dad0bf52c687de1eaf55e60f0ef173d967..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8242 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 diff --git a/bin/main/dev/loki/sound/SoundLevels.class b/bin/main/dev/loki/sound/SoundLevels.class deleted file mode 100644 index 2e35833f398eb7c3e9bc747f9c5c5b4a3147ba43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1628 zcmaJ>U2hXd6g}fzuRpR0$pRs9oDT?4djl9+(U#hclg2ip? z5r)*Z)z3NZ13TAsd!6lEoqr9hZ#mrmI{M`Sxb*d}GzvEY}%kzZni0FSH!HWBbcQ zA(L$o^qRYE#SxX4_xB&mMdSBBl3+NkViITQ#zGi8l`-CwQ1?B%vy-n@D%nPYqNi0v zp~MlBi_`m$xo1{IjC@fM1;-7OzU;h1YUMc<+YzS`qbv`SR**3qwLv1FwsAu}N%P?B^ z&DMjOxf@og^i8K{5x4nFc4)VfC}K5+6^8Kv?f1IA)mHHt)~Gtu^US@LySvAr52~}V zb>C|F`RYK^{&!V**JFai#$AT1gK1%7hl;>Ea#KYKG?3Q^lh+)x+szN$_!{jEdp`U$ z*hzXHUdyW3yzAowkL3yvrMl|&PRI0n9vxp9K;-F#VI5k|uUw-ckmzYDE7N=`0a|Gm z#Yz)MCmNp>vC^af<0(FmWXEVi$8du3$I1Fm!~*L-gEh4YNz=5GFL3G^ri3FUYcr~_ z)54yMs@lA;7nENpLpsD%y(u3eU2jGYu~2`8b5992g7e~PnZ7b6h~ing=o(SJAWnG% zJ-v{`x8#rVczr4T0vGiQ&ym&7$j`C#Hr5EC@X;S7%rSwrAY{;RIV>b7n@gkdCqlQA zxX6V!@s-h8RR0OtCxQwmstD(V091p35RgXa*yN?RlTRO$oS=%|Cpa$j55$DGW$|Lh zy&+G@r|`j}9}y$X4!ChWFwzGk=mCXELco+r;T=vRDN5h}ley*n?0s=)jl>tZ$j14%PKVgLXD diff --git a/bin/main/dev/loki/sound/SoundManager.class b/bin/main/dev/loki/sound/SoundManager.class deleted file mode 100644 index ca6579e3f0225e28be255986307dcc276b92f4b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3764 zcmbVOT~`}b6x|mRhK8Xv&<0Xl+FGs9P@^q=v{Y&eNlTjsgb04)03%G9CNT`y`u+Lh zi_i5B_^fML7e2Ur)8*1%;9qfB_qj6+Gi|KZ#bQ=w?!9~ObM`rB=GVV|_z^$>pBrdX zcyQU?%)9k9C%<0bs4eGb<$A@cSu1waKtkbxtJbEKcdgn=eroZmz2qr$G~A69r>1bU zTyL)A7dO_{953%b%1Ytgk8ddl@B%bl~Dj@$CGNG_9x-W!RNb1tk9_^HipDQl9k{N{q_ez_><(T%kh$!v- zSRffYVd6356}p(lZK(=$c%c zJcXxyqvz{QcUfU?T%LY9+J)2N{~5Mw1SB|-eA_?C_Si|ie@>x$*0Yw@u2_wrU3P~t zR_g_qo?I9#>vrDo95+8+cU`vs|EYOa@~pE`v%HNaD|x9k>e;BoxWQxpxy!mRj-r7H z=B!l&CQ7)#)HM`IU(%i?|>Qv7vXP zu|4=swmfmq3>$bgUO~EmIdVnDyyLBI527bxwI4SsYN6i%!6?}brkE zgI7(gV2uMVcGeG2b4nx^ZL8@m+7`n&9ou&Y$3IVfz8!Yq71T{MFvww4tW+nfFD=X$ zW+sZ2g^R_)O!a)RP-QI&-vzto7caZGNz(opX_zP<(=)Lln7!xAQ{$HxrYC2sQU#y^H~{CocAzC-snylcZAUU%!0dyv2b+?(bVe4*;y zyzAkeq(D$vHf+qj0j9%eNv`$ghEHS@x3Etx4{l)~i5>8i2HH!QeHwVgKN14>;wT;_ zAYt$bj_KXKcoc(LR4;~boWg`Q7tk&eA;JBbTy6`)e0`rFHUC>P_melPnFU7z+YTuc zGG{cO1f0=)?PPi!PXv5l1Yr*3ZsFvaL^km=65nJK3_9d}#*esNr?W@%9ALT*!eo~m z#NkNf10nx_j#nZd2>AyB{tonG6laO_EZ1q`pD+!+&=kgSjyZacPuuvhD%SqOU1InM z({WzmO!8|S$tJgOQQ;>X62V)jDBMKX@oYjw&&Vp<<*VC&h))TvI-`9#iaxq=gvy4P zol|r{ioy46Bvd|vdAvw1vLa4N=0*bLeRNtJP2eRyHG^IAc$vQ>mi=hEjV^Q;PzJ^g zykaov1}8o9r0^PE=T)Lw39_EvcKMM$#?hj*a+Ek6k(mxOb=k~`LA{&ax1|m9G z-{N=jF29$s9Ef|3!bF_fX)ftV@N-B^@`*Vdf{s-ou?mS*NUQ>4nHVpi}2HxIf;yL-6h(Sqks8 whJ3f@gO-p*LYDpo^1~2vB2a0H%8$&R%@!gj*&UZ6h-N6#3`Ks*NZat)-!?TU2mk;8 diff --git a/bin/main/dev/loki/sound/TerrorRadiusSound.class b/bin/main/dev/loki/sound/TerrorRadiusSound.class deleted file mode 100644 index 5ae62d7357fb4b3be7644a0e09bb5de523686b09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3607 zcmbtWTXz&y7XD6>?n){ZPzZqzC{YB{orD$~ogvK-APthxNibw)u&FK^XN{FHKBmPt4|yWfasT_r^o*h(thJ0|t zLxOazAc$j-Y({B-<9|3W=C+@B^mdx^h zcj0a!^nise*eZHyq3`N)jlu}^?*|gkBNiUTpQ%p2;$`jfV%A*}L5^+2TUGg!lksMa ztSvr4A@d#OptLL&MlGa70nxne<((p>KvO1;;HZHy`dF`;7UnFrgX0RFZh6KlQWjc4 z=jB@3!U>$D=E?mTT`UT_23uTmyub~vCd03(Zk)oTfeDsbQ(3p1v2Ysf4&8(l%A~3k zwzq=TJ`isjXAI0J^lns+79Pi}c+PsagA&Q?BT(byM0KAyS>z0yRoJrrtA!`^9nofaLhtMQncAEryaX6GfWtDQ^53ABWg0j8tB?n+bB$v7)cv20-(f1`$<^-D|XI_AJ&I^7iKx?2oWfp-H` z7=@@W>>#?EDI98XsYNcS27BvK<2gy}a~7T#c8tq*d0OYt3Y&dRvi;39)QV1RhiA!y z!nWpvb!Nz3Z7`6UhCdPp$45;CEJRbz)vOxwqG2ONp^l}~xVt_U4ofN`zc^(t>*j0X zHN0Wq^=4r--Kq{d3vUXgJ>ttLhmB_5u_Na8yVVJkVC`WW` zdA^HJ_ClmhReK75sUtm1M4>Q}SjC~W0K;T_qzOPm z5bhNY*8tR4JY#b23wpBuSMn%}`ijE!-#=?)$$Xl)6?r_wC42}pN%5ARn^yi5@3Ah97WHA<4&njR5xCPqkv-%v@| zhR!i77g$3Vsg$Ql-X(1_Y(ud+DKVX4i7{3srH7R(M73)_y3p2n8(qu|{rG^#+VJ6j E0Sa|HHUIzs diff --git a/bin/main/dev/loki/state/StateHandler.class b/bin/main/dev/loki/state/StateHandler.class deleted file mode 100644 index 91cad30350f22878f3ae86dca72b15c310cd7c0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3959 zcmbtWTUQ%Z6#ga&3501$OK-Mdv5l65OR9pcLXiMzNl8fs3eu|W5T-C?Izw}zQt$V> zc(+!4b}jY6yT#?|BM<%q|4Wzpota4(2#t1`wPw!jefBxuzI9#o8JUCjpIlMuR~EGRKuF=k@vsS9c*FJY5uSZ4jR)T$Ep zrYxI6Uejae3q~fdnMSNn>o<*D;i8)Dl29|M%@|6)kfrtM%GTYfl1KBpvZ!WbeM(L} zX?=E;&Dna(o30)LZ8i;CHDF#g)M*Kg8=<*8>#8(g(U&!FgQhtr;7a&Inyw2)UD2UL zE~Cr~O(Z-zksRwEJUbTeOC`dLHZ1ZVwxbQZB9h=ala%1^)(kD*Bf;Ao8JFPeH>cGg zyx1;d3$_v>r5WmQ;o_8<9aE-srg&@0%qaS}lGTLlD1G@^EhiFE%5Sc$;>=(ur{>dZ z>$|Ucqa?WsEZlnhUyLf|a@8k03o%y~Sl7sS4J6ztqY8cr)r?J_QZjQAcB~C_alRPr z7Ap#Smm(FKHuSK>1rbC~MU#pl6urD#Mh$`z+#cBM5HU2%kk`-JR1vc+GB%0XtuF5! z-iYaT8Jn%eJa;^wYtCSIb6F1m>$!=X4&pv^1aQBE-6e83g;?E0MkgL%_Gi?*h0Jr` z94P~J7cPjycqo7eS-R4;F3yc*6(gsKW+9^s-Ru%tF0Sk5WpPT5l*i-Vx+1O}P>+m< z(MyM!Ovhm|pyY@XpL^5Dc#v7{lhKa>7Eqa=*B7moiSy^#_;`5!PnO4PaTJ3A9OD_R z*e_)yah%6q$z;@dw%Y>^DP29-=~`}$?R-kc3CsC>R-2hov$p#Ss=LYcSPO#r9dcT4$VLAePTk7AN_C#CE<&^L0* z%+AE73UhN>K1Rp2{G!tix@vI-j|cFWgk86?k?{o1(lITUHgxtyt80?r5)>JAm}38I zj+{vbF@|XwD$Yv?nAvH~P;|>Q>F@2}^~j$9yC7o@oTwp(231AR&x-W}k#T=-*tYWb z+M{Kjm5~E8Ez>+{END5+YRA6j)1tXlbtQ}i1;@y?vUBpuXTwy9VU`(-d3BEin zVfzL&u^Z>JBJz+3`FR;H;6+klLD35;3EjkGl(E6~%&Kcw4OhJ^;}tx@MD@oq6%nNW?A0n=;-K3jaWQV%WBMN5;F>y2NOI{G_dWPsaO}ZZHu~jSWtUy*`xj zk+pO%ogT8yK9TXMWtJR1erhB!5Wr__POE=KhRxAJX7;G2>eGpA*5qH6kc8lTok5W55|Z9N0oX6>}YwsLk7D0?lWCfeF4LQ_o)iHX=pYa3;MIZAjv%1)x}x+RJT zdM!$=g>p}2lmqKg_7J7vwoxLLQKIWn_7bJ(wozIuqqMC@*-w=4ZKK3+keL(I`G!^Y zaqMXM1@{iOwO+@eYpC*m+tT_Ajzq;f9{mZ8E7&ZCmeyq?ys-2`zHhnC=EyyyHE@8w zMEJ)dN|LsbE$w94L2}?;w4#G;xYP18YU7po(}7{6=?#6rNjyTnRFTjl{PJRy+8TIn zqAq~322Sz9v>lhWJB}~W@$uod707MNI4$8CeBWQkIXa$c|C-Ble8lF0gb_ZSeB#b? zg5xBgOxrfhEJO3+E5!MI(fRJ=x9NOGT;Gjtn;mU^X=R&t8J9d*txr2o9`GQed5D?r zrsGE#Uk@JRzlB-!B2PD-Wk9cS=3N|f*~v`^H8-&}zzgJH zEq^t2OcAeTr?!7m5^d;;J0FxU@ez8F5^=j6<|A||KId5G@CuS*Xj#US9;T$5!hscZ zilL}$rVw4hU1BKewozaqHi^O3t!864djxQtOh_^IG@J1Vvv3NFyqQIRYO*~oMSi6e z`4xv1f(rpuwbs|yheFljiglRaJuM9EhaKA=#V`IthLJu~?up81X*h1gLWa21W@f0Sbjd3=cD zVe}!v@hGDm;W*05pXGQC8g!2K$#M5+(S1df_o0q|->&^l+DIJ5>nc*>HMI8260H{# K@Htm{@WnqCv}HE{ diff --git a/bin/main/dev/loki/state/StateMachine.class b/bin/main/dev/loki/state/StateMachine.class deleted file mode 100644 index 38bf1583d8c42ade2cf20cd094737b90b46020e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4046 zcmbtW>r)%o9X$(@7UTs9;@FsAo5aKhVOwtEwvI*I@DLV8fP(~txUI9S*04tGs=E@2 z`*7N{P5OR6)Az&8OeY^)w;@j2$;Wo4(@*_-GHuVjyR4Q#>`wb-@7}%lp5OVM-{bDz z|Mm7e07mg!6)g%Ls+gPEs!wjx zpswk5rE0ng4j1=2UhtQ53c72iU9s%dva8#kRks}5Q;;f3$VT0&W@q#ox3!n7Ra>t& zTvNe?ovR~}>B7R)M6PMER@HBqZuYVqB=6h>f(;FnmZr+%g{$S!v0{FJ1P6qF1OE1b z$aV!SSEdvsMl9Q^Ur^9GIJBrBHttl+BwEp>p#z;N9(W&>0ymTBMpru&9MBL)LPd{) zuBL|t-CLuVNgVWdJ)}WJTax<^YdC^V1)ZK*Z`8*1YIQ|7)}=rcf3~r)V!CC0rAkq{ zi;kgJ7j@SX^WbBwzGiXv-Z2P5nCoV&2Q)m2<8)Lv470`nUKnhuxI65*p@`E?vTgBpgAVS14KoGsNKXIiY1>?4EsIWJV!>S0Qh9R(v1MnPQ1bkFpI zb?=xDJuCQ}){wQUpFTtbp`#qDM#T2YX##P_F;lmF*tN(Dv3!HR9uV}MBql` zq=qS6VwZ4SmcCwzX$6y4^Nk*jBHDDjMsoyr5bVHOp9Es0o|TYPceKjE~OGPvwPo z71yb8SaY0p5v!{jo|C0%*@kOw5WK(@PaIy+U`WD+xw&a^Heq^(UNgnoH4Up0IA0nc zy(|{nJ>77vYnCC`uWMKr>#>Ras5ohP6Q*8aF<9PWqiUP3U+qceK+s$i?8t&hc!Le} zKWV$_=1KT_$2Lb>eYtH6a5VCE`=iz%?al| zt>H7$xk7%lSS~E9cu_%b^LChZN)2Oe(lV=+yz4ry3XL(W>KiK+ec;UhSK^CFd;u@3 z_#!QaxgKO*vrlMv1z%!5P`-tRMP0jDK}|8_^&w>XiiWS^YxJL?bvD_tjt3npa?5Qu z!RRMSEd!t+S#lb#VNP12Id?JB!aMV{u*bGI<~VhaJ+3xm*4Lbhm&AAQJr&<&du&Q( z*_+O~nJr3Mn2J z=$9P_%QtG~|F-Cxy!Y8adr2fPD=xW`RX1~~1ir1{MARk!?;;8rd>L9y<42+~{6xd& z@KQ>}t7*K%s+qD`GUHX<^Gr|0FBLqxOWM5zQt@lH%zJNTa`;RQ$xX+FEqOG8KS0Q&h=^Px!Q5zbn~e?wqqgfn5LGxH~6zl~$S7EUx# zlUx_r9XJ$0>I{$+(P;yu0tpL8lLBe@$PWNb2V))FR(nu|)I-k$6}90Ztx{$DiWxuK2y1CR&?{c1v|eu%G`GJ=E=C>ef%!eD23W?#BY|LZKL1_KW1Kgr;{0V(#I^Lf%=Ou_4qPaw~+GR%v&P4VoeqNs1+l~Jt4`Si07>C19W`j z{Y=b;CZ_i`arwVBVZ)&z(NnS<6^?OHqPO`HO|-Ja^E*X6psa|?KRA3YI4tVB_bq%v z!F#*JGi+(g5tO8ll5P{ffIf;MdW4|h-9cmduZZ1Vx{K%E`Ac#-Bhx?MHpiM>;)LhP$q z{sqqXici!T<3qvDbbRu`zsYg@?rtQTPMR_fOm6nO=bm%E@1AoufBp0OO8_YpLhuP( z-qxNb3~NtMlx)@35;^&qFRErqw{^=5At2DXt3Fi|hHCC4vRk`a!4`ux#r_Vo^Ov3WRg|j;Y$^q9*XDes^l&Eb@V&9%{wJva>h|Bt5n{&2DZxot$Q< z)~SM_o4P$M;2#}Z69~*$+gb?i0$sJV=G4*?rWS#MsDe&J1X`w?V_}e$f*@ML=s{ly zy#kk-q^RI6^b3UMGO309+=jqlQ$o_|MFp3fGxJLiR#!4ER&l_EoagZT*GJx*Xzh-%j_QMXK&S#g&w@yr!p-C8wBo+*6bTKd6V`^j%~^+TTrlwC6?5V#*(U|_WA+} zVY#j{*%NKZVnsm?c}|LgW!kE4l25N!tN$EslJ4W8wa*r^Ep~Wy)YZ>7`Xt%Ddch74 zT+sw3JzaB-0mgJW_X>OLq3Tsc^ip0c?(3#%Q1<3Jjxpn)b054yy_8n>)g8|ar}Khp z=G8sT-4Tf7ta7oS&Fb>fdl=a}@+W0Wa{^Ixz9$4O%9+SD#3vtG`MnikM2NI;yU)Ra zUtU1jc#e+W&{dKD-4$G@V4#Ab3Pw(F^%QYG)}1Zl+-c*Fgs}YBy;2#hie~#H&Xelaa zB#$Vr0Y1eXpTd~O10oa{-%)gV5hUL=eu{@a{DJJ^#Gi;x#82^=4?iLpIQAdYBml`M z!UMnv+Hu8kJ?tJQgMQ+4gf)I+QIO#}KBx5tQJH{?Y!dl`NGrtO7!0v-!gz!)tLbF8 zE7OjRQ}iP!TtN-ea3KyE@jHY^ws?{B5{_^ z5xV(w!F?KdH9&_$DbA~!;DyDVKz*){Gn&IynlfY%{to^Q2;-ZEJi1*T4BCjtjb=Oq JRQmT}>tAN~G`9c% diff --git a/bin/main/dev/loki/survivor/SurvivorController.class b/bin/main/dev/loki/survivor/SurvivorController.class deleted file mode 100644 index 20d29e6fba066570ddec481784dc9d779350ee47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2907 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 aet$p{{%br>8_zQ=Z;(R5ChWq2{Qm*zY@yfy diff --git a/bin/main/dev/loki/survivor/SurvivorMovement.class b/bin/main/dev/loki/survivor/SurvivorMovement.class deleted file mode 100644 index f1429e972f4ce92af7f5cc343887d16b3bb46e2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2948 zcma)8+fx&F6#g~|NeCP6HxUsrAS9J|qeZz?8e*jeLJ1c^t6h>6R$?|yHc%e=+{Zq{ zjJ8kp#nI|i9ov~c^rbVM_CInu{eHh)Nbt@K`@5g>o$q|-z~BG<_6L9o)M2n@urm<-jqA6!GZEos!^ql2`M?w8fqe zB7X0vku$7u1q1ybM#;dU0#D4$=mEIVrJ@5z6}bBc7OSD)n2IWR#q78WAN*q0tD@ST zolp^kpPVI(oIX>!v#J;7wbiVypfO>lwd|r+FvQx~^jPZ#`3$`S*Iv$G zf)&6ZPWce!^AAb1iqklwz;6^MnJST2M#NkPX)L`lt>qm^HG59txr~VIV-*3^kPwTx z7aQkQsHh2WHlkuwP*Y#ZXEaNfNvAc7yeSx0@u@gewR}Fi9lv#p3M~rE6DmGKOhNUU zZp~)3ZK2i9{(*#9Sc|TfHZ}|^N{JiRcGNx{sX-i{`#|lqzwM5S%b+G}in^7`>Dq>r zo~M6BWYU{=oOHb1g?PGdma-WcgAX$bx+;9-O^f1>&dR|Kr5dxC^WjU@>$@+`Z|8Lt zDa@1mRD!CEr&1#0?|(HCz%&+x{FW3%`ak5w)YJ-N7KAOUSiv<4QOjg1aZ|SMvos=P zQOE4WN`(Sbk;?0iTtxX&9wNoDbv7Q#y1SyLY@(gC$y+0$W;CRISXFR%U#72LRFMI# zc}3ZZPI07M5wBlnDfn~xmh?a!r8TE46f_gH)47WaV@0KrQO{x?b)zaNSt3 zZsNMRV%@@ZE8p+kZ{xbXVtt6krf}~tzn!$G5r>Q8q40AY2}hoyJM4an9`Ol@Pv2wd zwx8b)3A+s*8mz`4!sch(%JsG;YPj>4$8I~O1M>B5>-y;>gF)VHjho9jBf5*ze2BjiSQZa)h zCQ1rUk@(Z3a+7}s9Q5DGOMu8V z^IAqvpzV?0F}?f*Nq?2w{TvG~aMgvSGT2tC6VlBzT_jmVvjjCKf!Rvl%d?*W*uVsw zYPf7TqJpmDD+kIq97Wng4tG27Hnu$Ef*SBPHi%h|m^D4*g7<8ZcQK>D0(n~`h^qv# zOtD|1@UAnrHzXKa^r3@!3|5Ojoi}jPaX&|1L>UJoPw@56@JrE`gSCrkmEO`UBE2HW zpkr6?e2XWFNwbyT;+M-7B+1{Z9w@7o1GQJF{}=nTZh4~kpB!DhzP4m7^k>7 k41M2>+vcO%NBcHy@+`7ZLIbucY&RXW-9TGeK6ByD|35c6g#Z8m diff --git a/bin/main/dev/loki/ui/ActionBar.class b/bin/main/dev/loki/ui/ActionBar.class deleted file mode 100644 index fba075c05640e3ee9ec84b61dfd0ae68d6b01cc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6705 zcma)A33waD75>MTv@3a&ILawVK%ox!NFqWxp>%dA6&g*2BFRE3n`tt08e9U^d(AO3lr}R1p^iO!tz*B?=mLupsf^V=I=siqb(?$A6!RytNi*GR=2Eg<>~s|dQ+a_EiCL{}6sXEu znf`57K5q_CN2oTD%?*V1j1CQ@3Lz^~NEOCIwsDP#5~{93E|nQ*tn0195-iiORN#b+ zRR|4@XLG5L**`|f(VP`3SeF+<(d_U@Hp3nR%dvt`WUs)c+F2AP=G4+nAxBeV6#_U` z!!ZIY=d#zpDy$Y*An`fj5jd%K?lnsKrOQ2bYy^&(+b06r@RaZTN8%|i@8}hX%;(@a z!8;1*ash90%A*1`M}tPd$PZ>O+n&n~#&}*Oy(?-xGz;0OqhGDw7^-j#JRcd=*)JfZ5`T(l}nOA0-~82vB%7j?h;a`HDac6 zQ)UPpKM%0xoi>is44jTL7+>2|Nr|JgN5@$LK6^>hKj=jx&epI=V8fh|yCj<%HVdJ4 zbJ*&)DV)yISLa}}fV;0X-W_8!=61%c;$(jWQ4LK3C(gO>w0tqp3@+qOX1Th+dGq8z zaYe`0#-j?Aw5Y{ED`e#|M@E=)0$b-)>K$QWy+*eNg%vT2TIfnC6=o*dd{jub0$wd8H9Wu~WC ztK$MDsO*uX%3JA6bX-){W2V#Neh6GF@tchKED1FWY(FZ{CZJ1&Qn?1&UbZvYHQdRg zd~(#9vPj^#`SPf)S4WCvsMDg5wAs&niAyb1$g*+m2mKLtUe}vD8>L z*H{`Eq(rEd4;D8cG8oa2WnFjb%nV5bmx3Jj4p;?yV-i?ZTQ_%!mRkk4o>7d^8L50n zhHj=OxUKH=;c{G|VVq8IR&%T|a3!u{LE}2n(Oizzhp^-xc`R2ua=IF9lp3!wa4oJQ zPbsN-r`)=Is)%vzW-o5QO&V@2uc*%2O3c6;a5FcUuI@-nZ1+Ziz?{o^aSPt8;Z5br zcq*Y9#vz_$h8TDY&L{s{J388Qyj7}|Xo4H19d9%6_Ohi;k(qFZfp^GEsO*e2>v*TY z5?kPu;QC-!cV|yaOCrXUxdrbwaFq#V}f_(<=kqY$YNN3w_rRBYJ zbXO$W8Q&6*#)9!}+v4r9_HMbi+-u-I+)oPGHM!FovvPThHKew-nK?aYl`B;UspSD# z+3)wmg^T6Eq(#Smfu+G{XGc%8HCV_7^M%~#z(CqsBlDujM7h5^;he!Wrmsr|g<48; zoG5YBowqrmk2rg)S9M9JbF)z2QM>Be19B&jWkv4C&Y@2xOXEB#S6aMiU`fFaW_?qPKg4S3h(cQXZH{YGzI=(@k1ZD9o430}qf6KtPC8ymjov~QE zl>DxN?+kd`j{MQZk;|%TsW_jvtX^FWmRU3y<9uY|dVmvHF=r8H=w$D?PGC z$4}HcL}vA~^)u2<&OUrcu*s73HEHH@DXHfd0z|G3b5ZtKXZOJ+UG;GB6m zeG~N3=s(MFd1RdaYT$49J53rh)1wxdA7ljQ<%5?}|1j`R9A@yMk&w{M*2P zWS@(rM|J$qz{|43)7;V5ZqIquz-vk_))kFxSA9YlqC)i*!%bbnWeB$tl@-#SrWrz4 z(~7axgpYA79go|yU8BjtEh#JAAIs&ky!&|=imvP^&#GHe@=CVQxp-`lV$A!dY_`BE zWR7gJ3WM4HyiZgMza|#*BwtdT%8Zc;EZ_2$WuJ7mn8`vmH_jt~SR!y&`4ONv+g8|W zX8O}sz9zx2kB-c8XDd4&O%v=MAF*bczN>7$eV65d@CZwzJfn1_3RdGHk65IO<;<+0 zSgVVbyv&NAE_hF4N097`XEIhUnl|%!E3XOO&(G-vPJ-jya>18X#H!}(D`p4mWgdY_!`1GhwgOkCwnt+8^#1;dG#e7QPZJaHY zS2e7gg#RE`R-mN9$3alUM**oOXiqJwp%9M4@k(_S$JTH*Z_apKQT5iMYQ16Ita_Ia z!_qRnx}#Tj^y;X=TBY|yoK)1imsUtGRIjU>L~YpJ5OB}Xzfjq^g8Em|`hZ&FRQirG z&KlLu8r9gKY?q@UoJ?7buGz?S-CXe$yuP^ZOKJp2)=uKou-kto9X5gRL7ZEG&mtnN z*rL8_Z##sofEsRB!&4(+&obBDSQYU2&r_paGe#Q%9tTRLief#T58nMfSgqW>oDL82 zf0*q}basU9-iZ^jhwhOfI!C!C>A*}nFp~^Vze5<5du^ zV5f#98r2J`pYp)-^nlI@JrafP-?blZ|Ak?<@`oqjK7`#x)Fr17Psu5Jj&w>`YY1pF zFrTQHSx*cNB*;1ky?VH5=_QPj?y+7;=XaVmbd_Z|7pcg6s z!3qR?2fRQVsAmKSPteV}RvL2^t8;B4mSIXoDj%M6b&Em}z8R?;I*e{7{6 z+c=Uyj3sU>+WEf&=keOy%jYh1lBzw7a4)Z4eZ1xL;0hApDsue}j^54hdzc&#;36Iq zO?-~&C8O~XmQ8xniN=%o5FVnRW#7a2Fzb{XpH>m7q)iWT{>_Zb@znECQr1n|417$H zE#`dnGE#QmM$+%&*i2?@b-s4dM!WAc#_<5_l$S`RzIKz?cHb35E?MBC-7=Nel2ww> z4bWePU!ygzphm+Dl`CJx0+rc~r1|14{CoxHs*WWD@(3nu+TebIk(t#{PkKBWcCDVo z<6(Ee?f(=5q{0>;?`3>E!cR?*BR42e_i0iD6;~hRKEub2v-xX842F2>E*{V>W^dkRvDZ94X*>zHj1f z|4xjNmBY$|%Wb5N2lpwz2^DYtoW5?wibX3HH8Z9}{!3@0zn81Kxb9~EbILlWM9Y1j z`CdZ6z0Ch>)mgTAwKuSAOgkJLr}%LtU3(Qb&a3I(YgovxWC^>LX?dM8wccLRF?BP3 zTRbpq#_!aodj{z)=~_u+pU3a*aH5G2WjK8ella4ob?rmRjikX%W$y4fYxrzJRqM3u zDO;bYRQiGZ1YX?nG+YPzCh?cUPx#vEC-4&KqIc|vtB;L;u~F@rYW_H`y~G8>?OZXVZlj_kjwrKuG=t e;bztdu}nQzlzrPh0dXv6@oFkoiQ_~Nf&T-vdpmdl diff --git a/bin/main/dev/loki/ui/BossBarManager$1.class b/bin/main/dev/loki/ui/BossBarManager$1.class deleted file mode 100644 index cec8d5a9019f5375ab47ae5ba6c6d65905abfcbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 625 zcmaJ;O-~y!5PeRT?6Pb_pg@792@*L_Ds_P(E}%*Tfv6O6Xsg_vjg`1rY{~ZWzbf$| zao`8=qbkNBQriO@Jo9Gs{QPG8_~-rsz%e#Llo;v*ah2wJEYm`!ZEbCvn+vY^P?*+k zh=5^Jn_=27#$)MHn~lVv$c0JUlg9T#Dc;WoL&c4xZS9a?=Vir1;vGpP-B*U@)@#I% zJ%->!55z1O<`T@H5~GYa2|`pE%3Gc=-;qjmi_5++Kc8JJc67$`9yik0(`MkUF*IIz zueD3o%BD~;mhmpc3d8!#V;R*=!CE37-$)?tH&FVknSTFq~OP>D{6i2AdH_Nn%r zc>B{0g*zm_C!BeT72*IXY7~mg(Q-uS{o)>LjBfiDb-}~`Id5>QE@{dL| d)d;Xgw@O&Yd&&WAt&Rqvc&bMbO*$nkKLJ5{gF^rS diff --git a/bin/main/dev/loki/ui/BossBarManager.class b/bin/main/dev/loki/ui/BossBarManager.class deleted file mode 100644 index ea4be78da7fc56a6c76a87c8e0bc37427971b26e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7318 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 xa<|+gZ-9~UHgxL)?Lwb-5`Q5AW%{U5Lkg((04 diff --git a/bin/main/dev/loki/ui/ProgressBar.class b/bin/main/dev/loki/ui/ProgressBar.class deleted file mode 100644 index 85ab360d81e758e38023625a512bd3099f35d607..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3358 zcmbtWU2_vv7=BK^+bpzJKm#qJ&^9eXM6qg9OKF<6DQSysrPPABO_p})CL1=JDt@D= z_$}%M%y7e%!;BZo1tQKkUi)kG)^Wt=?50Vf33kStJ?FgV{e0f%oU_0GbNg2Shw)7i z9)X9l+DgnYm-Sdlj~%tlMN2Cd2URNwpFr~&bw!OCYJM>`xo}3y*aFIMDxFRaof=F} zCXNV*guteRnJ?OE-ae)pCCv-8Ula%@$B)j;xoT2$NnrC(a`^Cz>6ugMNZRXmlvGAtQlcL9;TnXOTmJfjO2bE5)PO9mHdVq6+M|YA-3+gLVPGWtQ?; z*3aC=q;jW%D7v_jG1Odv*+<7xsjgHId)c_Ei)q`^^NWKe-NBtDR}A49hCCSB(6sI-(#gMgEbgWO72*J)vL{M+HK*=|U{9CAuDgco3R2JYa^FU$mDvIjtLpM!xyAT){rahAya#8L7)OvPb7-GHt7w<#Dx8KGRL^ft}Uu zrL?-B83NDMfNbMuc~Lr$rfHmMd_a0*&1cO>yEOtSyAw+%loOrbCMCZ>$Br-&I;_QuUbuk4@mh2b^UL4X)vX&XjW0Os&U#Z@rE7N zR>Dw=MXeabmjdnUs;!lO5PYC_-d~kx+AWq` zVmuPvi|z0uz*Ued4?AUd|3+2YNXsSa1qE`7*WP z1a|S#+YN)i8E4UsH_?If=)`CIySRide9O1)3idgG71%J~dKoY|JINk+80#ut=1jKy zOPu1&M~@%k6{zgae&(@2SpdV#$DN&}?mP}rcD^#ZRGD3258d4i<2{1V9i|@e3L%2% zX3N9j@L$;3)buxeLEdN$EI=zazK@|L`$FBFvh%0!?fe0!kZle*LeO!By3}?`5{{>( zvZo*DM>2P``!<#VVtoUq1NLt?-s|gZBd>b>onPFBRo*RCb^{S##Q!s1^MJatMVwVL zX-!gtfWi=?WM(&c!MqS(QYr{eT(oOr0v_31(^Li zY_M|xL_2k4_ND*HV27!-C@iVH%HUNplEL?|v4`9M`uKgGEa)dc2FQ%VOn#6pO^}U) z{0mEBjNF*!c!H&7xss=Q)GeUGwo-*{OAf~*+vXkKNw!T@*tW{CkqYl5i?+abFN>5g iA$^y79UKVJ6N@P^_OT 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ⓈEl8k>^ony{eQC;j)kMEj~)A zQGBc(UXoS$;Yt(t$p%BPE=#KEB{IoVQ*eIUqabWq62>K#G;T=Km2rs7jm7PxIF~W# z;V#;wcLR3jK=;g&4v+mpoy{oTTqlr zWg)(oQL3^8MzK_WE|Z@%@^iWTTp>T}<>xA8EoQeW>y-7fv_aXZT%=qKD)`x*@(JY< PrIXx>1CN$nj@17J5lnq_ diff --git a/bin/main/dev/loki/ui/StatusIcons.class b/bin/main/dev/loki/ui/StatusIcons.class deleted file mode 100644 index f373cb7661066914bf28edf65317afa51e49d6c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2337 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 D998Ur diff --git a/bin/main/dev/loki/util/LocationUtil.class b/bin/main/dev/loki/util/LocationUtil.class deleted file mode 100644 index 681f3efde4ccf9ab3cbf5885d7b0a8f3bfa49db6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5507 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 H4gUFGN_V`V diff --git a/bin/main/dev/loki/util/MathUtil.class b/bin/main/dev/loki/util/MathUtil.class deleted file mode 100644 index 511e2d2d1a96055b188b1689f67118f624ddd552..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4573 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 diff --git a/bin/main/dev/loki/util/ParticleUtil.class b/bin/main/dev/loki/util/ParticleUtil.class deleted file mode 100644 index 2a909a304d4d534c2ff84aefd2a101d99ea7e26b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5937 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 diff --git a/bin/main/dev/loki/util/PlayerUtil.class b/bin/main/dev/loki/util/PlayerUtil.class deleted file mode 100644 index 86472fdf562fc62356d371e726a1597213eaf084..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7267 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 m!_YQ20M2{+r+c diff --git a/bin/main/dev/loki/util/TextUtil.class b/bin/main/dev/loki/util/TextUtil.class deleted file mode 100644 index 1bedf31b25c148a9c787acac3d22f42d29549758..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1068 zcmb7D+iuf95IvilKbAUOFc2>j&~sWD3A`{6>oy) z6lh2= zLvd#kHyF}Q+o43T$q+A<_ZSjeUQc9^g{i?{sGSwlz&R{1WEEvZ!|>NUO6>KmqwBD#X{*tt@@-@-L|T)UcP_$p`1pE{Ad=| z>YEujY>I+iV3jx!@OGH;%@Jf9+*9dG2@Vq2e7yo`GVXh3S-FAGZntbVlm99EKNgH#A#J!$;vle zoGmfK5@YfKE@7EI)Nz^kCyb8>N)?-*k*geG;582l0d diff --git a/bin/main/dev/loki/util/TimeUtil.class b/bin/main/dev/loki/util/TimeUtil.class deleted file mode 100644 index 07f1a3148dfe037eb6969490d8ee15920874045f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4581 zcmbVPYj+dZ72Tt^W!cEWHdvM&lVV~Mz~b3}u?rTah}hu758{x9jHSUEENO%^c0!)z zk(QLCZTd*lHl&5LrOl%?ZFtlveCz63{bcu7boG0`m9+cb8OxHTrfbzK-MMq`J?HGR z&*Kh%{e0m*fP?s>7Y+r@No}qtZOrIBv!$xb81go%})0mpE{!@ zOfHSZV~>xX8X0`@)aYRB__0F@l(>Srn2{}*YSx@k)3chB`Wws64#$s;j}3C&HLsvy zI6gEKU!~-zn?n3^{=NKwC24Q|<2ePM{d!h6`xQ95x+fI4Vn$N)!-?hqLRhO{&5)ke zj?HGKwEUPlmDUu5hKz)oo>23;c()f_W=bz8SU*(V|6clZ+Q?^Ab5u(h*(8rPb;Y}f zRu~yI^Llo=*N1k3i0+Fqi$hd(mAM2+M2$k75hCuplbf+f|9|WXX~hzTT?%w^2`2f>sbP4O2}Q zUG`@5?5wHLd2eBvhPqKxP0S3dIh)AFGMYy6T0$>qKJ2E9U_}!1WoovGu?@LX#%!K? zZIWX~CZ{G$AIQ5STJWJyQkm)KO!DO`3^peUYHeF7BX5S7ECT_=5K*u$qt0kd!Gvm_ z(9P6xG8RHmFc5+R0}5=M!6qQ&e17Q#>)Or_&j~%;L%A4X%h2W!8=gYaVNZ$zwS@k~gOFTA?tY<`uMb z#pCf)()S+UJsv1)ni$4Pw6i)Si2z_4njLPT}jT_1yThkW1E=G=d~>1xn;&N2vcf)NXt%}DcU+sUbG}z zONH`C_dOE4){V?&oXh<(u;hzu-F9z@uUZ#6$E~jPbUZkr^ z6m1QxeiN?-@EX3Zz-JnkeWr0&RYH}72$eA_D0LJVoR$jg%Zf>>PT!_A^I$HQH(t=$ znkv#@k=@!sO6KJb7awJ@S=?beOI>`IxDaOiJ$&=>%>f_ZYf9eze6K~IxL?QjH6`ys zG*F6P8a&ZR4Ly7+e7ZN^LDNmCaveuu0PtfyN1==d&_Y$9u~tO5B81=PssPm=eh;2d z+k7~a=S_Yqa=O{$=&vU(tn_c^(=!U(kLqFmsqdEA6~#gK*r)a>O}f1;E=t*=^&>? zVny=<>F_eBjo8JH(A_2J8MVn23BaWE27-+K;iCDM?M&^i$kfnRtJAc~?q1sMB`f>M zN?!>Z-Nj^VD<gJ3{@3Q ztri|E6BhL#s&%+19JMWb!VRwZ3h8)>v`4xkq>tgaje9%k7XkE!UvEU6{>duj!zJQg z>Aw&ksV*L@5PzafTvW9Xe*#aISa%5P?KGabyxR5gGVxKyNr>~i$QJ*I#VPt_wDl_d zO`;V|%!ebX*0ht;r}wxcP446#Pg|3l8%?ez4<8G7t}^>3*;`LCUeBxv@9nTr})pmWzvJ!^4>Gmk8EW=k!B&me6Bzse)xKaV@Z zt&xV#%MG1x-$mva`&1wtOcMVMxSV@jA;Zeyt!%SRuH{xmF{>rjOWRXyM+w?XO5D3F zwME=Ji@0~%xa+V9XOX9D8=F{x2wf7RAC7+^%pP%opBLg|-G=%GPl^iN@EOd>);pLR zcJ|*uU`zNm&YigARN7jv{rjI=ZsV1el5UnDQuJ6yJ!xp1m11=DP z=;`Zm5tm48Elcrru30^jupXe^3zJuR4ZcyV{I~3^XNPaU&Rgo6Y?Dum$s24tct^~x zh}qx7>@CieEn@Z^&KysP+1vA>@2^0%+Ix;B&hm1~(@cRpnT+u)_F+y!w=T>+y9%r; z$y4L2;UDFGScLW$LKD~LcsS_K@!m}4`Xa&FYY0YyYd?_9@g1gM>xaVqD1RcW1jFt8 zJ+k~`3;hvr10hb{6_XlHeq5Tmn`jhxkzBvTfW5+CzRHlEXDhqF4ttR`eu<@WUP8BS z*m23VXrv?fiDcc+X7p3etQ)o-?gwa7ly;wQP+S&HyhjTTT;&&mXwg3Wf?$6s#~X6| djT}Fc<0o?bog8o4D}SJz_}|Q@xQ)AL`42dQ%@+Uw diff --git a/bin/main/dev/loki/window/Window$PlayerContext.class b/bin/main/dev/loki/window/Window$PlayerContext.class deleted file mode 100644 index 44f0b33a465dccea6a13e87759f51c2a0161655b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1643 zcma)6T~pIQ6g^v@0U9V20RaU+_-G3fzZHrgpbm@`8DVe+pVD@xgobQQwjlq>2bqy^ zh6jIuKg#iLlG;q^Fgzr?dvnjZch9{yfBs(l2C#~C4Kaqv5m*Il5@jyy!5N0rnU-0pL~iKN&`DR2Vn@1`QzjF+H?AC5b19PUrj9|3Ff698 zmq!a43Upw42TBHClTF2YTgNEI88X-9-DHUKuQk&qO$O7EWIq-Tc~Ryv`-=9SjtSgn z$X%1R6%PekvK&h;GmND7TdJ7Z>qZ-9bW9@c-)WCp<^z`pqO@(g<`I|Nr98WLM9nSo zca|!0B51aGB{O-i2_Ze{n$-a2bz>e6H5d#NjY7CJM_NbR2<{kq>Uf053|)mf1H)NV z5X(6h6>bFH8>UmTxi^^?qEf5oBKHl89I=GJ-P0<6!@Z(wRi$vFkagSiyr?1M_;Q&f z8a)?nim+VCI39H38AE@4ta9~%N|ILe4A8`EIu6aHipo6=iwr}phk>D|X@*}hOf_`8 zLJ|!t4C7b3Qbz>(Q7dn8Pi_cLk}dc%P&KFpsP|$>sR5^5O3fFo8hz=28o6#d8MHE5 zJF-8K_)eP`dgvYZjjQOTy&gCqi9R}!I7D?BJn*9l{I(@n`wyNXl6vGz;1wSnBg%dn z^`S7{3}vSvTJ{3NKyySE0gYm;1?U#ge8(tg0(U}Cnj)#_o!Qw7+`S4#KX6QuZy;vO z7d@H%h3V|rITG2qa}1m{Dbomi6Iu(Vir16mNKbQ`!z71Zo_+Br z*v|Oq8#7i%aP&dn{T2No>bUlI5)7Em$iVrod+)W^+WX^=zkmG=z*XFdphsc2YTeH{ zZq3d;uW!l{DW*vXam zYBk%-wYL`)dOdfyy;O*l9k)`mstRgbA-rVQZEr>4bf&BIR7oMY=2opZ0!SE$qhBGA znJUGgFkm2ra2$g;6~U0gV3+s?hB2ZLsyJ@lQW(ihb&VrV&KNk0QMxy)M0Ylm&*!^e zme}VEL=cwQ3kITyDfAcYy0x))uWU88%(BB^DaqO?nGIXkt<9i!$8Iv;LU*>w*T9bD zt)AdE!M&|c8fBwo?m6C;+2B+N-0qGx{QEPC%%AY(XL=;&-kR+=Rzo{b=-c$nO08(_ zwjjpr=4x9ca!r}yO+spK1sRF5MC@kCbnL27H*erIysi)x=yFf^I|fIqp3`TGy;#6o z5xmKg>rkxYhJi&aF@hxhX!pOe6;00~sm@{?E4UKD<>T77j}4Y~P6OR^2{gvbYX6nkK#+qCAtcTv>)OH*N zY(!90NO!M;;}!;PNG4Icd0h(^r-ttvcojKuv}s^VioBP6Ny$k&%8inN+xXDm&)ZGU ztXIh8^Exdbz7lNLN1)<8RG9pK*(k(zb$W~~#qha-FC=WVdK5FtnrOWep@zj`Vo7bf zdyR^9&6ZB-^`Dwqd1Vxg^?IFTIcBqIu~qtxk;ls$R?{n5(r8V*$UFmt9Y9JR1I|*? zm>hegEjbDkarE+QaAk70hvT{I&*;leA0U~XK13?fpE$(n1B_(@2N?fBn@{jNOsAk> z5Pfu(zzF&=h9twvnRbNpc!?{z)ByOdA7zW;m?0MmuV^bZ#OW*~Q3>0b@c2GAIukzM74t=0Y8kKawqOotM~|rx*SnMC z_d*Av@DZZ0mRgu*N3?u>MH?xM89(>Af}itTarzg$p>T-hCm8VOKVtPegaZ3P!Q070 zmVT$H_Kc1?;rnYvjZ)=nc!$xFTV@F7aWQ}k1UI^GQ64Tj@=o=aBCtSNX4Z!?_87O&-& zt``^b`Ng&CrSjq`110~U_a!*vpQmZ^&li9HBa95*3t)E8q;#iX4)c^3(RA_}!}Q@% zJnNuPNLE5LuekuS3}^R~e|S48$YYU)#O77YuE`OmOaIyT$;t>mU?~0aebxKAdpF*_ z)4kQb?cMVpdJp1%e*R6odyCYzw@U|Kb-(Z)c%8U+-+SUc?B0%hJKa0puGbdoBLR}o z$KK=aUGLG9sK`|XA7Y6pIozx*bH~x@G|A(M;-}h{rW%@AS4*y~n{_!aO7CI$r+Wt4 za-c7$c_SrPt2UOk=H3*9D7AK#7j*Idocz~AHY40IC|6CB+c`sX98MDx8F=2PZC1GB zUa=e(ahk#*QCdXBppq69V=5&LsgyLLBz^Qn@EqYsN&Av+1xUtHKjC;P-NsmIx{dKv zvW?TJ$>BC8cjTSt1xDJ{$VZh1zeYAV#_$OyQO6lNpOfb?ynq*JCGdg?lbYZnJjcY7 zA(_U+lR*fvcb51I)@%n*I1b!*Ci?JVZu9*H6{+%?f#yd#(u%7NLdpa8gapghwXN zX$eb0MSpiJerBwDG#Wn>9~e3!LF$vRsW+W6Ej2~iWL66v`WG$nACJePBjcXq!9)Mf zZ*6vz^p1=~`$oox&kV(=YcSw!m*14|NHXtCT%XrWDvR3wWGy`z9#S(A31u;TCZ$?g zLzD1S@$Lc7baZr}FXGJYV4~^NOynTt%NInfz3FVqqW)bT5$fMa!$8W?W;DZA5SU6kRYlVYH94jlx|rt{{no5br<gI9D7DsiT{{v#P15W=K2g z-W0Rc#2hnY!z&_G^5lJIc2Fq~-M`iTWbb%eTuizL4c!X9ZJkjEzty6=MoDZI|jL3MF^-`!- zLGTa;F{EHv_)wPQf?b=!>Tv}pgo&V`&8HX0)fh%)#Pc+@73T=9U<~7gU_sRN$h3s5 zEdyTr`8p74PbrwdX@_kiMxQnynPhgmSW$OS@D+TO7`Rdz#q~>Tt4(X~tleF^y?&v&6t6PJ z_pa_)dwuQt+O@UY{N7o+Q*@}StE(KB@l6@8(bU5NQt&N&n+!Fz)YOn>nyTPIjh6>8 z%V1NBw2sNRBBAraA-b8`>5k&6ITykbzALV+*Ck{&&Y;IZ7l*!w|q z@TP+A;rr|%Mm8lJimH~lK@PS&T#yCl@x@HcYExNWJK-LiMnZ|W5gcQ@xV(ppJ)l*G zdU;|Moh_yn8E8KpoC`Hz>4`bE^`MnwN{!cw3y+MS7iYG}zKmt|4^Jq0IT^nyzFq7D zO9;i%StFtK>*9$}Jzo5N>k>VeVm;}!Wm<-s8PcrT^pqLGZ*g75H9j{AU0F{pr02A7 zRGpukQh89FRufj*SX8ir8zkF&VM)S2y=2QtI?9i!si~x9?u@3>bJ>jd!Ik5rr#BS| z#uqc1_xK0jbWCn6>uqp3&An7B) z5+dG+^EaL+mi&^}P=2ivzbCH-QYp>o<)vhbckCv&9t1mO{8_@|_a);&kjnV0gzXz2 zB?}$=nYUrhw1zbCkTlWEM(AS$44|I>gPh5nm7tXKkY`@b`6fK#?pL5nJWx5`VxO<( zn9o#qzLk0;@zCYBjwepgip1ZBwi~E#yN$+EH?aLWb`*xqzp)j4h~Fys`K{r1D=Mg@ zo@#b-MR8Q%aXi79B-(dQ{R>ntWa`^j(0T=OHOk*^YkzbF;VTGKye+2O^+9Og%0TG| z9c)B7cAy$fTzky6(B^2#S)e{Vja|0YdVCbS35;0VgT2(Xk7GYd%0pb`1J?0G;!B_4 z0cYvS{^6TAxX0gi4Ldql(N}^$U~qr1F8D42{^hOyy5I_;S~V(OdlQvB)XYO8B^dWF z+Y{eSoLt3oK1#(_@ceGMMh?7%vPMSaU-m82h7(U469pm?ARZwiQpXE%JK7ml7sCA8 zk0<$JeHteji9qp~o#L}@jAz{#&)SidP}6Cgg-ZP)zF#Jpc0aWqMFLZ##7WLIOjC ztRm~jc!3E{uJ%&JK9nIs9vnaip7G?W(~YAu7e{~?2=7ZMvD5ZmP;b$7X_`Aey3}a9 zWV_?wZoA?P3m!OJJWLO|QOT!!1A1-iO^y!NdZTN7Th6+KPr39zLJtJ}w+M5q__PFJ z%pMd>Jz}fur`tza0>^AK4&}Gx%t-hwKIb4S9U;v`;^PeC#r=W009oZ*ZfozT@vqYJ73-mEENsz7>3Fe_36iHdwLr21=`5xr#v5*H`h465PhpsrI_E+F)Df4Sc7w zru5sgxFxmFLA&inOG(`PC>3?8*of22o4n2?(0Qb@S0_pN-HpF z+O$cVq)pnSuSwkW{e^a>AKIBV9y>Fge(Hx#zxHc?K&QWSpu1D(`WOI_sgB*i_K?k*Y?i| z^bXXP6+Cy*UdraZg7j_AEsyEvTzXz0G3FJm6yj(zk;EQ>_&|EzK!?BsHBc8yCAp!H zrO=MHBsgiJ3C$_qJ!oPdQUa}xCyPPiOsPF@yVi7NWx*=V$pwd5bgJE*d0Dd6b9FG` z->|v*NDXQu1{EL97IuM$YpZuiEQP~3YTyVXhg3CQYT{uW6G$yteu%wuAia(8Tq}BU z+(4heo*FBP5EK0v5NNS|t0aA|B(SgU?aAsmBV;gW-~@@NMcA4(@hDDG3)i|uV{~mr zh}b1(;1pT+N=w;=%JQ=9hhiFdjGKmO*729Z5Kb#y9~bBz$TxVK9#FYGVd5hgq4=^` zq@)8u{?Yx@*Hs2N6KC;JdiRDbPiwHW%XPj-dH7z#9R%8DeOXwZlB-qKliVd>Ti{^C zrghl0JDYO?Su5U}6$DhtJZ0jtN~SrO;Qmzig5v}$Xt%*Fg2Rg2rKFVQ z^NPbMfu1Tc`n@sFaahQ#Ck=J)B8z_7k|nELwUWT8#+;9*cgjWycE!ZAm}Nl`^*Aji z-2%&JC;7%{zOC9|nXJfL&&r}*VU~hZh8qB4v=!T}MN1SJn0`{2=Vit5RZRx`2wd1n zlHM6dZdfID51-oSc2DEeCO(7Da$~z3?jVr2CBqo&) zJrk=~VOf{$=Lk)?a9%ogQ7=;q$|ihNXwn3htgAsk2 zOyFqU^2Lg)-I$#zSw))^SZq39z!wcXPbO+jr!K6CFX06uShO8>DuI!x!y815cE-9u zdatjTco8p=nL^0K(=5<}Ll;iEYbyCp9vSN@`BzN5imz*GRryXXvax^I=Ik^rj$BzN z%HE+}TL;}Ugm0SomTp$cf!vxUvCdXM>s3kx>yoVxrNHymllr70iO2Cp&-0m_T%EG~ z8(y)T!uRk41K$@orfJlD(RSCoWhXqfxZt=*@zGWn*xV-UrPH1 z?C~sT^|4NP$g0m1UJX9Q&;pb9NhqML9Qim`#dv)%a|dSTeY9V@gS~%3XXeCv==y_x zWk3Hrk>J0{|27^1d(g%IZjS5=UPccN@QGn?5DzhQOnnJew|I+hsket2^3Yv8A~3y) zBahxiTHr6pPG$ax&i65NZSW3;@8V1hS2;H-aQps06@WNu06Ka90Mdl>7`IXYj_NFj zLjc270Q0T&Z|46`B(Pj9U6BJ=aaf zdLn6?;jSjeFwRH<6FWw{#Kg8oe25VbeMrPf9OLeRdQWT3&M;@8uqwF}-aGi%@A(|l zOew8FUKBe@YxN(OnU2$1U`vamkEZJ&0Hf1IGt zV35f_fe|J$O1I?j6vwa7qe`cMin)-AIV@sHQ!y7(aV4Z;I;5gs`_5q8C>56wuTdc* zRNSXQ0)m23lB7%FKC3r69uUXL-1nQ>HetcW}!md78xLlXk?vx0mfj z?mNbUyGUnDMC{&IO?W>=2@2>ux7ZsLD{-r)#Y%1Cjf0gclGD5@lcWM9{I>ZWpQ7Hs z9PxfC^#13=2&&dqgabhYp7r;z2HeGSG5&p7;MMIB^O1-L!iZlD**RB@*r6ic!`D=> zmmAdk4BO_FNUV+^R!2&m7{sJ1QgtMSt}XK(UVjHhd=rU;0u)qOP~J0Vq^#EN3 zO^CIgS4zFfff&Ax@9?Uc^gA58jUVD&efJ~$6hFhyIoHWK$uERo5Xmp`Yy1X1{{=27 BjKcr` diff --git a/bin/main/dev/loki/window/WindowVault$VaultTask.class b/bin/main/dev/loki/window/WindowVault$VaultTask.class deleted file mode 100644 index 68491dc05ba934eadc03a4ac63de6ae526e47fd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 960 zcma)4T~8B16g|@|lr9U@rS$_)P>Qtc$NJzKhD1n=CJiA%>hrW6+p*i(W_K3i&oXH> z@xdS9k22nwlD0|J_^>l`?>&3ZnKSq2ukSwqyhgo%9K%6JT!m5Gm*KTko%lNZV7DgE zB3-rXB~SYWl$5v~gdw>+%EXK-rurm2)YEMeK4ZhI(Tg|H2ΘI ziR5zPmv62dHF+XUe3Q&;x;w++O!DH*XRl*CnCN5J`nzb-m1N4rE*=)J$FMzppT*`L z9$}whtsM`BkjHWhyT+=W0iXmXGvSUk!Cr#MI7Dm=oi(WyuA67A*S$r$UwH zV{8V`#;AO;=sUFf$kY0fI&`s4|7=3yE@c9nFXJAzD55Tw(=e1Rt5H(MHg*U{BT9WH ztjDB}QLPk=h;&4JBUHZP!Hm(hItSQ*vP?!V;cu86R4K~g0FP;RsmAER4k=T!`Q6{L C0qL*+ diff --git a/bin/main/dev/loki/window/WindowVault.class b/bin/main/dev/loki/window/WindowVault.class deleted file mode 100644 index 8d7d31c1ca5e20a52b53b7f6e598ede034847f33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4343 zcmbVP`*Rc575=VXYs>2=Ho=61caUT|N(zC&q8R)t1{u4^*tJ4{MPAHeS#qV7fu@gy zHffu<>H9(3(0A#BmOz7zp&_0A!c3=~5&ul5Kct<0_pXpvV3SPzgZA#-d(S!FcfND( z^*{c1`!0a}_?rfgz>^c^Y&4ynvZCj#%tZEFbWA-)jY8Vi;1g&#Ys?zaw2_&N4xKt{ zrfh*)XX&7kF(%EN!20;|MoJ4}0`;@fo|Ty#P8%1@T%I#=Ww&5k>1e{Vxu!Z{O=b+c zkTV4~R({>%dOdn{pf|Rc>jQhNjAic?*cAE@|KU*qUr%oJup)rg%1Gq(_aMCErVv zKKqPCkWZ};m|~X@s_fhaH5SPKL|i~Yy25bF)EAd*-W_6dakekE0WyLj{d#SO)~ z#oNXAitlVFzR%(H;+^8H;zIH6{a5c_EZ*8EIqTNZgI={nI*T6OF08@K2zT-?4Zf&S=lq41PCUzHenm7sX=2#^%xB=39MdTp0ct|=r{>O zKx0Oa7OV+2Di+65gHvs^1}T^t__22B3)`NK(_jOsO0iN6E5lA!p&{oSD779-$5~8K zI##~l$lEHt`)3U+?X<^_DIL|-rgdbH6{tI77kH>lML5M^#I{C zEQd6&!7Nm-;M|BKZf%pap(hdXY8%^zlosh8;9)G;Tc4jw!@IDDdeXecov z4Zo%1oA?&Nki)TTF3o&2S2kuf8>_~5@I4LRWx8AhC9;LggpTjy2Rx9w<3l}%PQ>^3 z_Vyh)kr?S4R_E=~S*RArd|k|C4KCp)8h%`9O?lGsQ@qWBlKN0P1llVgmhJ%L8?91=Pxo2P@>APn|I*3Ot3Q-Ri0#jj$1Ed6SJ`f?dFGTd65N z#Qq(j1#uw0X6RWSQEo=DO1RsB!`P)K6 zt2ufCt(;lyY{ptV$v2u&PMKS*!&8n6v5sNLJJDpMZ5~fwg5P_UgH4A!?#baDgvR+A z=~%?G0t?vD>5IIJ##Uc5cFkjVr@z&I549alU5nW7f!Z3mgz9GWT|qF?*6N?fr*;SA zU`?QX9*2Ba>BH*mC(XWM#S=eA%cwj##cX%Duc4-veG zHkiClN^l3r9K$Yyo5T=?2};g=8b=7d9-l!1BlH(S7r7iIK|Aq0#yIb%Egj=X68?+a zLu!H_AgCewUqm&8G#u0Wy)?%=x5E^=X;LPmjts0ODaRLa$^!|=qW}ez^XFX5*Oh~- zD+T9~cd(MZ;|xrSp+3?^YR-`Q`fDWa8mAnF>eS~QOz8{kHoKJJ4bGOb;rcS_dWFlQ z&@k{CM#V$B8nv@`S?82m!NsCz~{<`6MoF)rLpX#vFxSM<;4$A{XRj!qi(k zwRWk^d7SI4Y7N}M%i}ljg%+(L==Cn(%ZqrOD<90i!TEnz%rD{_{7)gEgna|wZu+6V zh#&cJ2bagG*Q!?k0)F1=Z_!?x$FIg@tvN~QMgzw^lua)M)K4S_u!&i1$07c^631RX zdwCr`NIau_9-}DFQjjxz7AVIzDM%^bBdY4=%1q3aDV{4)Oa^d;0+o52Q<9b~<8>wJ z0DYdt@9=vTK|4<35BMYPNg=bDd;py~W*)BMPo=!vqTpqZ=wIUT&tyk3EGyl2y`y~* z*Ez#NCoS!Ykfxi8kq)xDhIQHNKi}s{K z8*#js(e{_o_N&-E+`YY2tYs8yBnmHXGj0#_@>f2aI116nd$f9)*zWTEea`zhzWjgo C_fSUw diff --git a/bin/main/dev/loki/world/LobbyManager.class b/bin/main/dev/loki/world/LobbyManager.class deleted file mode 100644 index 911bfa7b368df18b7beec2ba5c30cfd1589373b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5324 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 diff --git a/bin/main/game.yml b/bin/main/game.yml deleted file mode 100644 index c2e91e1..0000000 --- a/bin/main/game.yml +++ /dev/null @@ -1,260 +0,0 @@ -# ============================================ -# Mdbd Plugin - Игровой баланс -# ============================================ - -# Лобби -lobby: - # Минимум игроков для старта - min-players: 4 - - # Максимум игроков - max-players: 5 - - # Обратный отсчёт при 4 игроках (секунд) - countdown-4-players: 45 - - # Обратный отсчёт при 5 игроках (секунд) - countdown-5-players: 15 - - # Задержка перед назначением ролей (секунд) - role-assign-delay: 5 - - # Количество серверных лобби (0 = только пользовательские) - server-lobby-count: 3 - - # Сохранять лобби между перезапусками - persist-lobbies: true - -# Размеры игроков (1.0 = стандарт) -players: - survivor-scale: 1.0 - killer-scale: 1.5 - -# Генераторы -generators: - # Всего генераторов на карте - total-count: 7 - - # Сколько нужно починить для ворот - required-count: 5 - - # Время починки одного генератора (секунд) [90 сек по ТЗ] - repair-seconds: 90 - - # Скорость отката без чинильщика (%/сек) - regression-rate: 0.25 - - # Скорость отката после удара (%/сек) - kick-regression-rate: 2.5 - - # Потеря прогресса после удара (%) - kick-regression-percent: 20.0 - - # Длительность отката после удара (секунд) - kick-duration-seconds: 30 - - # Кулдаун удара по генератору (секунд, общий для всех генераторов) - kick-cooldown-seconds: 30 - - # Время зажатия Shift для удара (секунд) - kick-charge-seconds: 3 - - # Расстояние для взаимодействия с генератором (блоков) - interaction-range: 3.0 - -# Крюки -hooks: - # Длительность Фазы 1 (секунд) - stage1-seconds: 60 - - # Длительность Фазы 2 (секунд) - stage2-seconds: 60 - - # Интервал борьбы на Фазе 2 (секунд) - struggle-interval: 2 - - # Максимум крюков на одного выжившего (= жизни) - max-hooks: 3 - - # Расстояние для взаимодействия с крюком (блоков) - interaction-range: 3.0 - - # Время спасения (секунд) - rescue-seconds: 3 - - # Время саботажа крюка (секунд) - sabotage-seconds: 10 - - # Время восстановления крюка (секунд) - sabotage-recovery-seconds: 60 - -# Скорости (% от нормальной) -movement: - # Киллер - killer: 115 - - # Киллер с выжившим - killer-carry: 92 - - # Выживший шагом - survivor-walk: 100 - - # Выживший спринт - survivor-sprint: 150 - - # Выживший в нокдауне (ползком) - survivor-crawl: 30 - - # Длительность истощения (секунд) - exhaustion-duration: 3 - - # Кулдаун истощения (секунд) - exhaustion-cooldown: 5 - -# Лечение -healing: - # Лечение другого (секунд) - other-heal-seconds: 15 - - # Самолечение аптечкой (секунд) - self-heal-seconds: 30 - - # Бонус аптечки (0.5 = в 2 раза быстрее) - medkit-bonus: 0.5 - - # Прерывание при движении - interrupt-on-move: true - - # Максимум лечений за матч - max-heals-per-match: 4 - - # Расстояние лечения (блоков) - heal-range: 3.0 - -# Переноска выжившего -carry: - # Количество прыжков для заполнения шкалы побега - escape-jumps: 15 - - # Speed I после побега (секунд) - escape-speed-seconds: 3 - - # Приращение шкалы за прыжок (%) - jump-fill-percent: 6.67 - -# Киллер -killer: - # Кулдаун атаки (секунд) — базовый (swing animation) - attack-cooldown: 2.5 - - # Кулдаун после ПОПАДАНИЯ по выжившему (секунд) — 3–5 сек - post-hit-cooldown: 4.0 - - # Дальность атаки (блоков) - attack-range: 3.0 - - # Длительность оглушения паллетом (секунд) - pallet-stun-seconds: 2.0 - - # Время ломания паллета (секунд) - pallet-break-seconds: 3.0 - - # Радиус страха (блоков) - terror-radius: 32 - - # Расстояние для взаимодействия с паллетом (блоков) - pallet-interaction-range: 3.0 - -# BossBar радиуса страха -bossbar: - # Включить BossBar - enabled: true - - # Название (поддерживает MiniMessage) - title: "☠ МАНЬЯК РЯДОМ ☠" - - # Цвет: PINK, BLUE, RED, GREEN, YELLOW, PURPLE, WHITE - color: RED - - # Стиль: SOLID, SEGMENTED_6, SEGMENTED_10, SEGMENTED_12, SEGMENTED_20 - style: SOLID - - # Расстояние начала появления (блоков) - appear-range: 32 - - # Расстояние полного заполнения (блоков) - full-range: 8 - -# Окна -window: - # Быстрый волт выжившего (секунд) - vault-survivor-fast: 1.0 - - # Медленный волт выжившего (секунд) - vault-survivor-slow: 1.5 - - # Волт киллера (секунд) - vault-killer: 1.5 - - # Блокировка после 3 волтов подряд (секунд) - vault-block-seconds: 15 - -# Эндгейм -endgame: - # Время открытия ворот (секунд) - gate-open-seconds: 20 - - # Время до конца после открытия ворот (секунд) - collapse-seconds: 120 - - # Открытие сундуков (секунд) - chest-open-seconds: 3 - - # Расстояние для взаимодействия с воротами (блоков) - gate-interaction-range: 3.0 - -# Уведомление маньяка о генераторе -killer-notification: - # Время действия компаса (секунд) - compass-duration-seconds: 5 - -# Скорборд -scoreboard: - # Показывать сердца (жизни) - show-hearts: true - - # Символ сердца - heart-symbol: "♥" - - # Цвет ника: HEALTHY, INJURED (красный), HEALING (зелёный), HOOKED (тёмно-красный) - color-healthy: "WHITE" - color-injured: "RED" - color-healing: "GREEN" - color-hooked: "DARK_RED" - -# Люк -hatch: - # Минимум живых для открытия люка - min-survivors-for-open: 1 - - # Условие: живых < починенных генераторов - require-more-gens-than-survivors: true - -# Лут сундуков -loot: - medkit: - weight: 55 - min-charges: 12 - max-charges: 16 - flashlight: - weight: 45 - min-charges: 6 - max-charges: 8 - -# Custom Model Data для ресурспака -# Задайте числа соответствующие overrides в вашем ресурспаке. -# 0 = не применять (использовать ванильную модель) -items: - model-data: - medkit: 1001 - flashlight: 1002 diff --git a/bin/main/locations.yml b/bin/main/locations.yml deleted file mode 100644 index d52f930..0000000 --- a/bin/main/locations.yml +++ /dev/null @@ -1,58 +0,0 @@ -# ============================================ -# Mdbd Plugin - Координаты объектов -# Устанавливайте через /dbdsetup set <тип> -# ============================================ - -# Лобби (спавн перед игрой) -lobby: - world: "world" - x: 0.0 - y: 100.0 - z: 0.0 - yaw: 0.0 - pitch: 0.0 - -# Генераторы — настраиваются через /dbdadmin create generator -# и сохраняются в data/generators.yml - -# Крюки (обычно 4-6) -hooks: [] -# Пример: -# - "world,120.5,65.0,180.5,0.0,0.0" - -# Паллеты (много) -pallets: [] -# Пример: -# - "world,110.5,64.0,190.5,0.0,0.0" - -# Окна (много) -windows: [] - -# Сундуки с лутом (3-4) -chests: [] - -# Тотемы (5) -totems: [] - -# Ворота выхода (2) -exitgates: [] - -# Спавн киллера (1 точка) -killer-spawn: [] - -# Спавны выживших (4 точки) -survivor-spawns: [] - -# ============================================ -# Команды для настройки: -# /dbdadmin create generator - Войти в режим выбора генератора (сломайте блок) -# /dbdadmin list - Список всех генераторов -# /dbdadmin remove - Удалить генератор по ID -# /dbdadmin clear - Очистить все генераторы -# /dbdsetup set hook - Установить крюк -# /dbdsetup set pallet - Установить паллет -# /dbdsetup set chest - Установить сундук -# /dbdsetup set totem - Установить тотем -# /dbdsetup set gate - Установить ворота -# /dbdsetup set lobby - Установить лобби -# ============================================ diff --git a/bin/main/messages.yml b/bin/main/messages.yml deleted file mode 100644 index d866caf..0000000 --- a/bin/main/messages.yml +++ /dev/null @@ -1,119 +0,0 @@ -# ============================================ -# Mdbd Plugin - Сообщения -# Поддерживаются цвета в формате &#rrggbb -# ============================================ - -# Префикс всех сообщений плагина -prefix: "&#FF6B00&l[DBD]&r " - -# Сообщения игры -game: - # Старт/конец - start: "�FF00Игра началась! Бегите от Киллера!" - end-victory-escape: "&#FFD700Выжившие сбежали! Победа!" - end-victory-killer: "&#DC143CКиллер победил!" - - # Ожидание - waiting: "&#FFFF00Ожидание игроков... (%s/%s)" - countdown: "&#FFA500До начала: %s секунд" - countdown-short: "&#FF0000%s..." - - # Роли - role-killer: "&#DC143CВы Киллер! Поймайте всех выживших." - role-survivor: "�CED1Вы Выживший! Почините генераторы и сбегите." - -# Генераторы -generator: - repair-start: "�CED1Вы начали чинить генератор..." - repair-stop: "WCEEBВы остановились." - repair-complete: "�FF00✓ Генератор активирован! (%s/%s)" - repair-progress: "&#FFD700Прогресс: %s%%" - - skillcheck-success: "�FF00Отлично! +%s%%" - skillcheck-super: "&#FFD700Великолепно! +%s%%" - skillcheck-fail: "&#FF0000✗ Провал! -%s%%" - - explosion: "&#FF4500⚠ Взрыв генератора!" - regression: "&#FF6347Генератор откатывается..." - kicked: "&#FF4500Киллер пнул генератор!" - -# Киллер -killer: - terror-near: "B0000Сердце колотится..." - terror-medium: "&#FF4500Опасно рядом..." - terror-far: "&#FFA500Киллер где-то рядом" - - chase-start: "&#FF0000⚠ Киллер преследует вас!" - chase-stop: "�FF00Вы ушли от погони." - - hit: "&#DC143CВы ранены! Ищите укрытие!" - down: "B0000Вы в нокдауне! Ползите!" - pickup: "󃕐Киллер поднял вас..." - hook: "B0082Вас повесили на крюк!" - -# Выжившие -survivor: - heal-self-start: "�FA9AЛечите себя..." - heal-self-complete: "�FF00Вылечены!" - heal-other-start: "�FA9AЛечите союзника..." - heal-other-complete: "�FF00Союзник вылечен!" - heal-interrupt: "&#FFD700Лечение прервано!" - - sprint-exhausted: "&#FF8C00Вы устали... (Истощение)" - sprint-ready: "�FF00Можно бежать!" - - pallet-drop: "&#DEB887Вы бросили паллет!" - pallet-stun: "&#FFD700Киллер оглушён! Уходите!" - - vault-fast: "�CED1Быстрый прыжок!" - vault-slow: "WCEEBМедленный прыжок..." - - rescue-start: "�CED1Спасаете с крюка..." - rescue-complete: "�FF00Союзник спасён!" - -# Крюки -hook: - stage1: "&#FFFF00Крюк: Фаза 1 — Не двигайтесь" - stage2: "&#FFA500Крюк: Фаза 2 — БОРИТЕСЬ!" - struggle-success: "�FF00Успех! Держитесь!" - struggle-fail: "&#FF0000Провал! Этап ускорен!" - sacrifice: "B0000☠ Вы жертвованы..." - -# Предметы -item: - found: "&#FFD700Найдено: %s" - - medkit-use: "�FA9AИспользуете аптечку..." - medkit-depleted: "&#FF6347Аптечка закончилась" - - flashlight-blind: "&#FFFF00Ослепили киллера! Уходите!" - flashlight-depleted: "&#FF6347Батарейка села" - - key-hatch: "�CED1Ключ открывает люк!" - map-reveal: "WCEEBОбъекты показаны на карте" - - chest-opening: "&#FFD700Открываете сундук..." - chest-found: "�FF00Нашли: %s" - -# Эндгейм -endgame: - gates-powered: "�FF00Ворота запитаны! Бегите!" - gates-opening: "&#FFD700Открываете ворота..." - - hatch-open: "B0082Люк открыт! Сбегите!" - hatch-escape: "�FF00✓ Вы сбежали через люк!" - - collapse-warning: "&#FF0000⚠ КОЛЛАПС ЧЕРЕЗ %s СЕК!" - collapse-start: "B0000КОЛЛАПС НАЧАЛСЯ! БЕГИТЕ!" - - escape: "�FF00✓ ПОБЕГ!" - -# Ошибки -error: - no-permission: "&#FF0000У вас нет прав!" - not-in-game: "&#FF6347Вы не в игре!" - already-in-game: "&#FF6347Вы уже в игре!" - game-full: "&#FF6347Игра заполнена!" - no-game: "&#FF6347Нет активной игры!" - not-survivor: "&#FF6347Только для выживших!" - not-killer: "&#FF6347Только для киллера!" diff --git a/bin/main/plugin.yml b/bin/main/plugin.yml deleted file mode 100644 index deb1a7d..0000000 --- a/bin/main/plugin.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Mdbd -version: '${version}' -main: dev.loki.mdbd -api-version: '1.21' - -commands: - dbd: - description: "Main DBD command" - usage: "/dbd " - permission: mdbd.player - dbdsetup: - description: "Map setup commands" - usage: "/dbdsetup " - permission: mdbd.admin - dbdadmin: - description: "Admin commands for generators and objects" - usage: "/dbdadmin " - permission: mdbd.admin - -permissions: - mdbd.admin: - description: "Full access to admin commands" - default: op - mdbd.player: - description: "Basic player commands" - default: true diff --git a/bin/main/skillcheck.yml b/bin/main/skillcheck.yml deleted file mode 100644 index 74cde8e..0000000 --- a/bin/main/skillcheck.yml +++ /dev/null @@ -1,120 +0,0 @@ -# ============================================ -# Mdbd Plugin - Настройки Skill Check (QTE) -# ============================================ - -# Цвета в формате &#rrggbb -colors: - # Зона успеха (зелёная) - zone-success: "�FF00" - - # Зона супер-успеха (золотая, бонус) - zone-super: "&#FFD700" - - # Стрелка (белая) - arrow: "&#FFFFFF" - - # Фон трека (тёмно-серый) - background: "񑘕" - - # Текст титра (жёлтый) - text-title: "&#FFFF00" - - # Подзаголовок (белый) - text-subtitle: "&#FFFFFF" - - # Цвет провала (красный) - fail: "&#FF0000" - -# Размеры зон (в градусах) -zones: - # Зона обычного успеха (±градусов от цели) - success-size: 15 - - # Зона супер-успеха (меньше = сложнее) - super-size: 5 - -# Вращение -rotation: - # Скорость вращения (оборотов в секунду) - speed: 3.0 - - # Направление: CLOCKWISE или COUNTER_CLOCKWISE - direction: "CLOCKWISE" - - # Случайное направление для каждого скиллчека - variation: true - - # Случайная начальная позиция - random-start: true - -# Тайминги -timing: - # Минимальный интервал между скиллчеками (в тиках, 20 = 1 сек) - min-interval: 80 - - # Максимальный интервал (в тиках) - max-interval: 200 - - # Время на реакцию (тиков после входа в зону) - reaction-window: 20 - - # Задержка перед показом скиллчека (тиков) - pre-delay: 5 - -# Награды и штрафы (в процентах от прогресса) -rewards: - # Обычный успех: +% к прогрессу - success-bonus: 5.0 - - # Супер-успех: +% к прогрессу - super-bonus: 10.0 - -penalties: - # Провал: -% от прогресса - fail-penalty: 10.0 - - # Радиус алерта киллера при провале (блоков) - fail-alert-range: 16 - - # Визуальный взрыв при провале - fail-explosion: true - - # Громкость звука взрыва (0.0 - 1.0) - explosion-volume: 0.8 - -# Визуальные эффекты -visual: - # Показывать трек движения - show-track: true - - # Показывать стрелку - show-arrow: true - - # Анимация при успехе - flash-on-success: true - - # Тряска экрана при провале - screenshake-on-fail: true - - # Альтернативный режим через BossBar (вместо Title) - use-boss-bar: false - -# Звуки -sounds: - # Звук при появлении скиллчека - appear: "BLOCK_NOTE_BLOCK_PLING" - appear-volume: 0.5 - - # Звук успеха - success: "ENTITY_PLAYER_LEVELUP" - success-volume: 0.6 - - # Звук супер-успеха - super: "ENTITY_PLAYER_LEVELUP" - super-volume: 1.0 - super-pitch: 1.5 - - # Звук провала - fail: "BLOCK_ANVIL_LAND" - fail-volume: 0.8 - fail-pitch: 0.8 From 17388f97e7fb5044b65a6425cb227414004612db Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Mon, 15 Jun 2026 11:55:44 +0200 Subject: [PATCH 05/10] =?UTF-8?q?fix:=2010=20bugs=20=E2=80=94=20timer,=20c?= =?UTF-8?q?ompass,=20escape=20teleport,=20win=20conditions,=20results,=20t?= =?UTF-8?q?ests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dev/loki/objective/GeneratorRepair.java | 47 +++++++++++++++--- .../java/dev/loki/phase/EndgamePhase.java | 48 +++++++++++++++---- .../java/dev/loki/phase/GameplayPhase.java | 8 +++- .../dev/loki/phase/GameplayWinConditions.java | 25 +++++----- src/test/java/dev/loki/gate/ExitGateTest.java | 14 ++++-- .../loki/phase/GameplayWinConditionsTest.java | 11 +++-- 6 files changed, 113 insertions(+), 40 deletions(-) diff --git a/src/main/java/dev/loki/objective/GeneratorRepair.java b/src/main/java/dev/loki/objective/GeneratorRepair.java index e51f5b4..49cd7c7 100644 --- a/src/main/java/dev/loki/objective/GeneratorRepair.java +++ b/src/main/java/dev/loki/objective/GeneratorRepair.java @@ -20,6 +20,8 @@ public class GeneratorRepair { private final GeneratorManager manager; private final Map sessions; private final GeneratorMinigame minigame; + private final Map compassTaskIds = new HashMap<>(); + private final Map compassPrevItems = new HashMap<>(); private static final double REPAIR_PER_TICK = 100.0 / 1600.0; private static final double REPAIR_RANGE = 3.0; @@ -201,14 +203,47 @@ public class GeneratorRepair { compass.setItemMeta(meta); } - ItemStack prev = online.getInventory().getItemInOffHand(); + UUID killerId = online.getUniqueId(); + + Integer prevTaskId = compassTaskIds.remove(killerId); + if (prevTaskId != null) { + Bukkit.getScheduler().cancelTask(prevTaskId); + } + + compassPrevItems.put(killerId, online.getInventory().getItemInOffHand()); online.getInventory().setItemInOffHand(compass); - plugin.getServer().getScheduler().runTaskLater(plugin, () -> { - ItemStack current = online.getInventory().getItemInOffHand(); - if (current.getType() == Material.COMPASS) { - online.getInventory().setItemInOffHand(prev); + + int taskId = Bukkit.getScheduler().runTaskLater(plugin, () -> { + if (!online.isOnline()) return; + + ItemStack offHand = online.getInventory().getItemInOffHand(); + if (offHand.getType() == Material.COMPASS) { + online.getInventory().setItemInOffHand(compassPrevItems.get(killerId)); + compassTaskIds.remove(killerId); + compassPrevItems.remove(killerId); + return; } - }, durationTicks); + + ItemStack mainHand = online.getInventory().getItemInMainHand(); + if (mainHand.getType() == Material.COMPASS) { + online.getInventory().setItemInMainHand(compassPrevItems.get(killerId)); + compassTaskIds.remove(killerId); + compassPrevItems.remove(killerId); + return; + } + + for (int i = 0; i < online.getInventory().getSize(); i++) { + ItemStack item = online.getInventory().getItem(i); + if (item != null && item.getType() == Material.COMPASS) { + online.getInventory().setItem(i, null); + break; + } + } + compassTaskIds.remove(killerId); + compassPrevItems.remove(killerId); + }, durationTicks).getTaskId(); + + compassTaskIds.put(killerId, taskId); } } diff --git a/src/main/java/dev/loki/phase/EndgamePhase.java b/src/main/java/dev/loki/phase/EndgamePhase.java index 65b8624..d131f39 100644 --- a/src/main/java/dev/loki/phase/EndgamePhase.java +++ b/src/main/java/dev/loki/phase/EndgamePhase.java @@ -31,6 +31,7 @@ public class EndgamePhase implements Phase { private HatchCondition hatchCondition; private HatchEscape hatchEscape; private Sidebar sidebar; + private int endgameTimer = -1; // секунд до конца эндгейма (-1 = не активно) public EndgamePhase() { this.openTicks = 20 * 20; @@ -100,6 +101,15 @@ public class EndgamePhase implements Phase { @Override public void tick(GameSession session) { + updateGates(session); + + if (endgameTimer > 0 && session.getTicksElapsed() % 20 == 0) { + endgameTimer--; + if (sidebar != null) { + sidebar.setEndgameTimer(endgameTimer); + } + } + // Update sidebar stats every 40 ticks if (session.getTicksElapsed() % 40 == 0 && sidebar != null) { for (BasePlayer bp : session.getPlayers().values()) { @@ -198,6 +208,12 @@ public class EndgamePhase implements Phase { // ------------------------------------------------------------------------- private void activateEndgame(GameSession session) { + if (endgameTimer < 0) { + endgameTimer = session.getConfig().getPostgameSeconds(); + } + if (sidebar != null) { + sidebar.setEndgameTimer(endgameTimer); + } if (gateManager != null && !gatesActivated) { gateManager.activateEndgame(); gatesActivated = true; @@ -268,26 +284,40 @@ public class EndgamePhase implements Phase { } if (survivorsAlive == 0) { complete = true; + announceEndgameEnd(session); + teleportAllToLobby(session); } } private void announceEndgameEnd(GameSession session) { List results = new ArrayList<>(); - results.add("§6§l=== РЕЗУЛЬТАТЫ ==="); - int escaped = 0, died = 0; + int escaped = 0, died = 0, sacrificed = 0, leftBehind = 0; for (BasePlayer player : session.getPlayers().values()) { if (player.isKiller()) continue; Player p = player.getPlayer(); String name = p != null ? p.getName() : "Unknown"; - if (player.getState() == PlayerState.ESCAPED) { - results.add("§a✔ " + name + " — Сбежал"); - escaped++; - } else { - results.add("§c✘ " + name + " — Погиб"); - died++; + switch (player.getState()) { + case ESCAPED: + results.add("§a✔ " + name + " — Сбежал"); + escaped++; + break; + case DEAD: + results.add("§c✘ " + name + " — Погиб"); + died++; + break; + case HOOKED: + case CARRIED: + results.add("§4✘ " + name + " — Принесён в жертву"); + sacrificed++; + break; + default: + results.add("§7✘ " + name + " — Оставлен"); + leftBehind++; + break; } } - results.add("§7Выживших: §a" + escaped + " §7/ Погибших: §c" + died); + results.add("§7Выживших: §a" + escaped + " §7/ Погибших: §c" + died + + " §7/ В жертву: §4" + sacrificed + " §7/ Оставлено: §7" + leftBehind); String msg = String.join("\n", results); for (BasePlayer player : session.getPlayers().values()) { Player p = player.getPlayer(); diff --git a/src/main/java/dev/loki/phase/GameplayPhase.java b/src/main/java/dev/loki/phase/GameplayPhase.java index 44ce48f..21c51a0 100644 --- a/src/main/java/dev/loki/phase/GameplayPhase.java +++ b/src/main/java/dev/loki/phase/GameplayPhase.java @@ -113,6 +113,9 @@ public class GameplayPhase implements Phase { if (generatorRepair != null) generatorRepair.tick(); if (interaction != null) interaction.tickSurvivors(); hookHandler.tick(); + if (ui.tickMatchTimer(session)) { + shouldEnd = true; + } // Particle effects around generators (every 10 ticks) if (tickCounter % 10 == 0 && generatorManager != null) { @@ -161,8 +164,6 @@ public class GameplayPhase implements Phase { ui.resetPlayers(session); damageSystem.clear(); damageSystem.clearManagers(); - - Bukkit.broadcast(session.getPlugin().getConfigManager().getMessages().get("game.end")); } @Override @@ -371,6 +372,9 @@ public class GameplayPhase implements Phase { p.playSound(p.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.2f); Bukkit.broadcast(Component.text( "§6[DBD] §a" + p.getName() + " §6сбежал через ворота!")); + p.setGameMode(GameMode.SPECTATOR); + p.getInventory().clear(); + session.getPlugin().getLobbyManager().teleportToLobby(p); } } } diff --git a/src/main/java/dev/loki/phase/GameplayWinConditions.java b/src/main/java/dev/loki/phase/GameplayWinConditions.java index 2f91504..a2d96c7 100644 --- a/src/main/java/dev/loki/phase/GameplayWinConditions.java +++ b/src/main/java/dev/loki/phase/GameplayWinConditions.java @@ -57,24 +57,24 @@ public class GameplayWinConditions { return; } - // Killer wins: all survivors are downed/hooked/carried/dead - if (allSurvivorsIncapacitated(session)) { - winReason = "killer_win"; - Bukkit.broadcast(session.getPlugin().getConfigManager().getMessages().get("game.all-incapacitated")); - announceKillerWin(session); - shouldEnd = true; - return; - } - // Survivors win: all generators done and at least one escaped if (hasEscapedSurvivor(session)) { winReason = "survivors_win"; announceSurvivorsWin(session); shouldEnd = true; + return; + } + + // Killer wins: all survivors are downed/hooked/carried/dead (ESCAPED excluded) + if (allSurvivorsIncapacitated(session)) { + winReason = "killer_win"; + Bukkit.broadcast(session.getPlugin().getConfigManager().getMessages().get("game.all-incapacitated")); + announceKillerWin(session); + shouldEnd = true; } } - /** True if NO survivor can act (all are DOWNED, HOOKED, CARRIED, DEAD, or ESCAPED). */ + /** True if NO survivor can act (all are DOWNED, HOOKED, CARRIED, DEAD). */ private boolean allSurvivorsIncapacitated(GameSession session) { boolean hasSurvivors = false; for (BasePlayer bp : session.getPlayers().values()) { @@ -82,8 +82,7 @@ public class GameplayWinConditions { hasSurvivors = true; PlayerState st = bp.getState(); if (st != PlayerState.DOWNED && st != PlayerState.HOOKED - && st != PlayerState.CARRIED && st != PlayerState.DEAD - && st != PlayerState.ESCAPED) { + && st != PlayerState.CARRIED && st != PlayerState.DEAD) { return false; // at least one survivor can still act } } @@ -121,7 +120,7 @@ public class GameplayWinConditions { for (BasePlayer bp : session.getPlayers().values()) { Player p = bp.getPlayer(); if (p == null || !p.isOnline()) continue; - if (!bp.isKiller() && bp.getState() == PlayerState.DEAD) { + if (!bp.isKiller() && (bp.getState() == PlayerState.DEAD || bp.getState() == PlayerState.ESCAPED)) { p.setGameMode(GameMode.SPECTATOR); } else { p.setGameMode(GameMode.SURVIVAL); diff --git a/src/test/java/dev/loki/gate/ExitGateTest.java b/src/test/java/dev/loki/gate/ExitGateTest.java index 55e4242..81c288e 100644 --- a/src/test/java/dev/loki/gate/ExitGateTest.java +++ b/src/test/java/dev/loki/gate/ExitGateTest.java @@ -26,18 +26,17 @@ class ExitGateTest { } @Test - void setPowered_shouldTransitionToOpening() { + void setPowered_shouldStayClosed() { gate.setPowered(true); - assertEquals(ExitGate.GateState.OPENING, gate.getState()); + assertEquals(ExitGate.GateState.CLOSED, gate.getState()); assertTrue(gate.isPowered()); - assertTrue(gate.isOpening()); - assertFalse(gate.isClosed()); - assertFalse(gate.isOpen()); + assertTrue(gate.isClosed()); } @Test void setProgressDirect_shouldIncreaseProgress() { gate.setPowered(true); + gate.startOpening(); gate.setProgressDirect(0.5); assertEquals(0.5, gate.getProgress()); assertEquals(50, gate.getProgressPercent()); @@ -47,6 +46,7 @@ class ExitGateTest { @Test void setProgressDirect_shouldCompleteWhenReachingOne() { gate.setPowered(true); + gate.startOpening(); gate.setProgressDirect(1.0); assertEquals(1.0, gate.getProgress()); assertEquals(ExitGate.GateState.OPEN, gate.getState()); @@ -56,6 +56,7 @@ class ExitGateTest { @Test void setProgressDirect_shouldClampToMax() { gate.setPowered(true); + gate.startOpening(); gate.setProgressDirect(2.0); assertEquals(1.0, gate.getProgress()); assertTrue(gate.isOpen()); @@ -64,6 +65,7 @@ class ExitGateTest { @Test void setProgressDirect_shouldNotExceedMin() { gate.setPowered(true); + gate.startOpening(); gate.setProgressDirect(-0.5); assertEquals(0.0, gate.getProgress()); } @@ -79,6 +81,7 @@ class ExitGateTest { @Test void updateProgress_shouldWorkIncrementally() { gate.setPowered(true); + gate.startOpening(); gate.updateProgress(0.3); assertEquals(0.3, gate.getProgress()); gate.updateProgress(0.3); @@ -101,6 +104,7 @@ class ExitGateTest { @Test void saveAndRestoreProgress_shouldPersist() { gate.setPowered(true); + gate.startOpening(); gate.setProgressDirect(0.4); assertEquals(0.4, gate.getProgress()); diff --git a/src/test/java/dev/loki/phase/GameplayWinConditionsTest.java b/src/test/java/dev/loki/phase/GameplayWinConditionsTest.java index 2b0cbac..bf89cf8 100644 --- a/src/test/java/dev/loki/phase/GameplayWinConditionsTest.java +++ b/src/test/java/dev/loki/phase/GameplayWinConditionsTest.java @@ -98,14 +98,14 @@ class GameplayWinConditionsTest { // ========================================================================= @Test - void incapacitated_withEscapedAndRestDisabled_shouldReturnTrue() { + void incapacitated_withEscapedAndRestDisabled_shouldReturnFalse() { Map players = new HashMap<>(); players.put(UUID.randomUUID(), onlineKiller()); players.put(UUID.randomUUID(), survivorWithState(PlayerState.ESCAPED)); players.put(UUID.randomUUID(), survivorWithState(PlayerState.DOWNED)); - assertTrue(allIncapacitated(sessionWith(players)), - "ESCAPED survivors should be counted as incapacitated (bug #3)"); + assertFalse(allIncapacitated(sessionWith(players)), + "ESCAPED survivors should NOT count as incapacitated for killer win"); } @Test @@ -120,13 +120,14 @@ class GameplayWinConditionsTest { } @Test - void incapacitated_withAllTerminalStates_shouldReturnTrue() { + void incapacitated_withEscapedAndDead_shouldReturnFalse() { Map players = new HashMap<>(); players.put(UUID.randomUUID(), onlineKiller()); players.put(UUID.randomUUID(), survivorWithState(PlayerState.DEAD)); players.put(UUID.randomUUID(), survivorWithState(PlayerState.ESCAPED)); - assertTrue(allIncapacitated(sessionWith(players))); + assertFalse(allIncapacitated(sessionWith(players)), + "ESCAPED should not count as incapacitated"); } // ========================================================================= From be86fe5960d7d3910a9eefc90a2be98c3c56bf4c Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Mon, 15 Jun 2026 12:31:52 +0200 Subject: [PATCH 06/10] fix: gates double results teleport guard missing message --- src/main/java/dev/loki/gate/ExitGate.java | 1 - .../java/dev/loki/phase/EndgamePhase.java | 22 ++++++++++++++----- src/main/resources/messages.yml | 1 - 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/main/java/dev/loki/gate/ExitGate.java b/src/main/java/dev/loki/gate/ExitGate.java index 9df9e1e..7f6b238 100644 --- a/src/main/java/dev/loki/gate/ExitGate.java +++ b/src/main/java/dev/loki/gate/ExitGate.java @@ -204,7 +204,6 @@ public class ExitGate { public void restoreProgress() { progress = savedProgress; } public void reset() { - removeGateBlock(); this.state = GateState.CLOSED; this.progress = 0.0; this.savedProgress = 0.0; diff --git a/src/main/java/dev/loki/phase/EndgamePhase.java b/src/main/java/dev/loki/phase/EndgamePhase.java index d131f39..521b58c 100644 --- a/src/main/java/dev/loki/phase/EndgamePhase.java +++ b/src/main/java/dev/loki/phase/EndgamePhase.java @@ -70,7 +70,7 @@ public class EndgamePhase implements Phase { this.complete = true; // Показываем результаты и телепортируем всех в лобби announceEndgameEnd(session); - teleportAllToLobby(session); + teleportAllToLobbyDelayed(session); return; } @@ -84,7 +84,7 @@ public class EndgamePhase implements Phase { if (gateManager != null && gateManager.getOpenGateCount() > 0) { this.complete = true; announceEndgameEnd(session); - teleportAllToLobby(session); + teleportAllToLobbyDelayed(session); return; } @@ -150,11 +150,23 @@ public class EndgamePhase implements Phase { } /** - * Телепортирует всех игроков в лобби, сбрасывает атрибуты и останавливает сессию. + * Телепортирует всех игроков в лобби и сбрасывает атрибуты (синхронно). */ private void teleportAllToLobby(GameSession session) { - List playersToTeleport = new ArrayList<>(session.getPlayers().values()); + for (BasePlayer bp : session.getPlayers().values()) { + Player p = bp.getPlayer(); + if (p != null && p.isOnline()) { + resetPlayerAttributes(p); + session.getPlugin().getLobbyManager().teleportToLobby(p); + } + } + } + /** + * Отложенный телепорт в лобби (для красивого перехода из enter). + */ + private void teleportAllToLobbyDelayed(GameSession session) { + List playersToTeleport = new ArrayList<>(session.getPlayers().values()); new BukkitRunnable() { @Override public void run() { @@ -165,7 +177,6 @@ public class EndgamePhase implements Phase { session.getPlugin().getLobbyManager().teleportToLobby(p); } } - session.stop(); } }.runTaskLater(session.getPlugin(), 60L); } @@ -273,6 +284,7 @@ public class EndgamePhase implements Phase { } private void checkWinConditions(GameSession session) { + if (complete) return; int survivorsAlive = 0; for (BasePlayer player : session.getPlayers().values()) { if (player.isKiller()) continue; diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 289728c..f244ec6 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -176,7 +176,6 @@ generator: actionbar: "&c⚡ Разрушение: %d%%" success: "%prefix%&cГенератор поврежден! -%d%% прогресса" broadcast: "%prefix%&4⚡ Маньяк разрушил генератор! -%d%%" - complete: "&aГенератор починен!\n%e" all-done: "%prefix%&aВсе генераторы починены! Открывайте ворота!" notification: "&4[DBD] ⚡ Выживший допустил ошибку! Компас укажет на генератор!" From bb293c5d032da938f78c7c2bd126569591cc2b46 Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Mon, 15 Jun 2026 12:45:56 +0200 Subject: [PATCH 07/10] =?UTF-8?q?remove:=20hatch=20(=D0=BB=D1=8E=D0=BA)=20?= =?UTF-8?q?and=20windows=20(=D0=BE=D0=BA=D0=BD=D0=B0)=20from=20code=20and?= =?UTF-8?q?=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/dev/loki/config/GameConfig.java | 4 - .../java/dev/loki/config/LocationsConfig.java | 7 - src/main/java/dev/loki/core/GameSession.java | 2 +- src/main/java/dev/loki/gate/ExitGate.java | 16 +++ src/main/java/dev/loki/hatch/Hatch.java | 125 ------------------ .../java/dev/loki/hatch/HatchCondition.java | 76 ----------- src/main/java/dev/loki/hatch/HatchEscape.java | 117 ---------------- .../loki/listener/PlayerInteractListener.java | 8 +- src/main/java/dev/loki/map/MapConfig.java | 1 - .../java/dev/loki/map/TemplateManager.java | 4 - .../java/dev/loki/phase/EndgamePhase.java | 51 +------ .../dev/loki/phase/GameplayInteraction.java | 6 +- src/main/resources/game.yml | 22 --- src/main/resources/locations.yml | 3 - src/main/resources/messages.yml | 73 +++++----- 15 files changed, 57 insertions(+), 458 deletions(-) delete mode 100644 src/main/java/dev/loki/hatch/Hatch.java delete mode 100644 src/main/java/dev/loki/hatch/HatchCondition.java delete mode 100644 src/main/java/dev/loki/hatch/HatchEscape.java diff --git a/src/main/java/dev/loki/config/GameConfig.java b/src/main/java/dev/loki/config/GameConfig.java index 3fa6634..64787e4 100644 --- a/src/main/java/dev/loki/config/GameConfig.java +++ b/src/main/java/dev/loki/config/GameConfig.java @@ -109,10 +109,6 @@ public class GameConfig { setDefault("colors.progress-bar-incomplete", "&#FF0000"); setDefault("colors.progress-bar-background", "񑘕"); - // Hatch - setDefault("hatch.min-survivors-for-open", 1); - setDefault("hatch.require-more-gens-than-survivors", true); - // Block types for spawning setDefault("blocks.generator", "BLAST_FURNACE"); setDefault("blocks.chest", "CHEST"); diff --git a/src/main/java/dev/loki/config/LocationsConfig.java b/src/main/java/dev/loki/config/LocationsConfig.java index 6cc3176..dbca2e8 100644 --- a/src/main/java/dev/loki/config/LocationsConfig.java +++ b/src/main/java/dev/loki/config/LocationsConfig.java @@ -34,9 +34,6 @@ public class LocationsConfig { if (!config.contains("hooks") || config.getList("hooks") == null) { config.set("hooks", new ArrayList<>()); } - if (!config.contains("windows") || config.getList("windows") == null) { - config.set("windows", new ArrayList<>()); - } if (!config.contains("chests") || config.getList("chests") == null) { config.set("chests", new ArrayList<>()); } @@ -79,10 +76,6 @@ public class LocationsConfig { return loadLocationList("hooks"); } - public List getWindows() { - return loadLocationList("windows"); - } - public List getChests() { return loadLocationList("chests"); } diff --git a/src/main/java/dev/loki/core/GameSession.java b/src/main/java/dev/loki/core/GameSession.java index dfaed5c..46e2a57 100644 --- a/src/main/java/dev/loki/core/GameSession.java +++ b/src/main/java/dev/loki/core/GameSession.java @@ -115,7 +115,7 @@ public class GameSession { if (currentPhase instanceof GameplayPhase gp) { // Всегда переходим в EndgamePhase для корректного завершения игры // (очистка скорборда, телепорт в лобби, показ результатов) - return new EndgamePhase(gateManager, null, null); + return new EndgamePhase(gateManager); } return null; } diff --git a/src/main/java/dev/loki/gate/ExitGate.java b/src/main/java/dev/loki/gate/ExitGate.java index 7f6b238..0f57794 100644 --- a/src/main/java/dev/loki/gate/ExitGate.java +++ b/src/main/java/dev/loki/gate/ExitGate.java @@ -60,6 +60,7 @@ public class ExitGate { World world = location.getWorld(); if (world == null) return; + // Place all iron bars first (no physics) then force update for connections if (hasZone) { for (int x = zoneMinX; x <= zoneMaxX; x++) { for (int y = zoneMinY; y <= zoneMaxY; y++) { @@ -68,6 +69,14 @@ public class ExitGate { } } } + // Force update all iron bars so they connect to neighbors + for (int x = zoneMinX; x <= zoneMaxX; x++) { + for (int y = zoneMinY; y <= zoneMaxY; y++) { + for (int z = zoneMinZ; z <= zoneMaxZ; z++) { + world.getBlockAt(x, y, z).getState().update(true, true); + } + } + } } else { // Fallback: 3x3x3 zone around gate location int cx = location.getBlockX(), cy = location.getBlockY(), cz = location.getBlockZ(); @@ -78,6 +87,13 @@ public class ExitGate { } } } + for (int x = cx - 1; x <= cx + 1; x++) { + for (int y = cy; y <= cy + 2; y++) { + for (int z = cz - 1; z <= cz + 1; z++) { + world.getBlockAt(x, y, z).getState().update(true, true); + } + } + } } // Button at gate center + (1, 1, 1) diff --git a/src/main/java/dev/loki/hatch/Hatch.java b/src/main/java/dev/loki/hatch/Hatch.java deleted file mode 100644 index 806b299..0000000 --- a/src/main/java/dev/loki/hatch/Hatch.java +++ /dev/null @@ -1,125 +0,0 @@ -package dev.loki.hatch; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.World; -import org.bukkit.block.Block; - -public class Hatch { - private final Location location; - private HatchState state; - private Block hatchBlock; - - public enum HatchState { - HIDDEN, - CLOSED, - OPEN - } - - public Hatch(Location location) { - this.location = location; - this.state = HatchState.HIDDEN; - this.hatchBlock = location.getBlock(); - } - - public Location getLocation() { - return location; - } - - public Location getJumpTarget() { - return location.clone().add(0.5, -2, 0.5); - } - - public HatchState getState() { - return state; - } - - public boolean isHidden() { - return state == HatchState.HIDDEN; - } - - public boolean isClosed() { - return state == HatchState.CLOSED; - } - - public boolean isOpen() { - return state == HatchState.OPEN; - } - - public void reveal() { - if (state == HatchState.HIDDEN) { - state = HatchState.CLOSED; - updateVisuals(); - playRevealEffect(); - } - } - - public void open() { - if (state == HatchState.CLOSED) { - state = HatchState.OPEN; - updateVisuals(); - playOpenEffect(); - } - } - - public void hide() { - state = HatchState.HIDDEN; - clearVisuals(); - } - - public void reset() { - state = HatchState.HIDDEN; - clearVisuals(); - } - - private void updateVisuals() { - switch (state) { - case CLOSED -> hatchBlock.setType(Material.IRON_TRAPDOOR); - case OPEN -> hatchBlock.setType(Material.AIR); - default -> hatchBlock.setType(Material.AIR); - } - } - - private void clearVisuals() { - hatchBlock.setType(Material.AIR); - } - - public boolean isInRange(Location playerLoc, double radius) { - return location.distance(playerLoc) <= radius; - } - - public boolean canEscape(Location playerLoc) { - return isOpen() && isInRange(playerLoc, 1.5); - } - - private void playRevealEffect() { - World world = location.getWorld(); - if (world == null) return; - - world.playSound(location, Sound.BLOCK_METAL_PLACE, 1.0f, 0.8f); - world.spawnParticle(org.bukkit.Particle.SMOKE, - location.clone().add(0.5, 0.5, 0.5), - 30, 0.3, 0.3, 0.3, 0.05); - } - - private void playOpenEffect() { - World world = location.getWorld(); - if (world == null) return; - - world.playSound(location, Sound.BLOCK_IRON_TRAPDOOR_OPEN, 1.0f, 1.0f); - world.spawnParticle(org.bukkit.Particle.END_ROD, - location.clone().add(0.5, 0.5, 0.5), - 20, 0.2, 0.2, 0.2, 0.02); - } - - public void playEscapeEffect() { - World world = location.getWorld(); - if (world == null) return; - - world.playSound(location, Sound.ENTITY_PLAYER_SPLASH, 1.0f, 1.0f); - world.spawnParticle(org.bukkit.Particle.PORTAL, - location.clone().add(0.5, 0, 0.5), - 100, 0.5, 0.5, 0.5, 0.5); - } -} diff --git a/src/main/java/dev/loki/hatch/HatchCondition.java b/src/main/java/dev/loki/hatch/HatchCondition.java deleted file mode 100644 index 1e9406d..0000000 --- a/src/main/java/dev/loki/hatch/HatchCondition.java +++ /dev/null @@ -1,76 +0,0 @@ -package dev.loki.hatch; - -import dev.loki.player.BasePlayer; -import dev.loki.player.PlayerState; - -import java.util.Collection; - -public class HatchCondition { - private final int minSurvivorsForOpen; - - public HatchCondition(int minSurvivorsForOpen) { - this.minSurvivorsForOpen = minSurvivorsForOpen; - } - - public boolean shouldSpawn(Collection players, int repairedGenerators) { - int aliveSurvivors = countAliveSurvivors(players); - return aliveSurvivors <= repairedGenerators; - } - - public boolean shouldOpen(Hatch hatch, Collection players, int repairedGenerators) { - if (hatch.isOpen()) return false; - if (!hatch.isClosed() && !hatch.isHidden()) return false; - - return shouldSpawn(players, repairedGenerators); - } - - public boolean canOpen(Hatch hatch, Collection players, int repairedGenerators) { - if (!hatch.isHidden() && !hatch.isClosed()) return false; - - int aliveSurvivors = countAliveSurvivors(players); - int requiredGens = Math.max(minSurvivorsForOpen, aliveSurvivors); - - return repairedGenerators >= requiredGens; - } - - public int countAliveSurvivors(Collection players) { - return (int) players.stream() - .filter(p -> !p.isKiller()) - .filter(this::isAlive) - .count(); - } - - private boolean isAlive(BasePlayer player) { - PlayerState state = player.getState(); - return state != PlayerState.DEAD - && state != PlayerState.ESCAPED - && state != PlayerState.HOOKED; - } - - public int getRemainingAlive(Collection players) { - return countAliveSurvivors(players); - } - - public boolean isLastSurvivor(Collection players) { - return countAliveSurvivors(players) == 1; - } - - public boolean checkAndReveal(Hatch hatch, Collection players, int repairedGenerators) { - if (hatch.isHidden() && shouldSpawn(players, repairedGenerators)) { - hatch.reveal(); - return true; - } - return false; - } - - public boolean checkAndOpen(Hatch hatch, Collection players, int repairedGenerators) { - if (canOpen(hatch, players, repairedGenerators)) { - if (hatch.isHidden()) { - hatch.reveal(); - } - hatch.open(); - return true; - } - return false; - } -} diff --git a/src/main/java/dev/loki/hatch/HatchEscape.java b/src/main/java/dev/loki/hatch/HatchEscape.java deleted file mode 100644 index 0dca00f..0000000 --- a/src/main/java/dev/loki/hatch/HatchEscape.java +++ /dev/null @@ -1,117 +0,0 @@ -package dev.loki.hatch; - -import dev.loki.config.MessagesConfig; -import dev.loki.mdbd; -import dev.loki.player.PlayerState; -import dev.loki.player.Survivor; -import org.bukkit.Location; -import org.bukkit.Sound; -import org.bukkit.World; -import org.bukkit.entity.Player; - -public class HatchEscape { - private static final double ESCAPE_RADIUS = 1.5; - - private final Hatch hatch; - private final MessagesConfig messages; - - public HatchEscape(Hatch hatch) { - this.hatch = hatch; - this.messages = mdbd.getInstance().getConfigManager().getMessages(); - } - - public boolean tryEscape(Survivor survivor) { - if (!hatch.isOpen()) { - return tryRevealAndCheck(survivor); - } - - Player player = survivor.getPlayer(); - if (player == null) return false; - - if (!isAtHatch(player.getLocation())) { - player.sendMessage(messages.get("hatch.too-far")); - return false; - } - - performEscape(survivor); - return true; - } - - public boolean canEscape(Survivor survivor) { - if (!hatch.isOpen()) return false; - - Player player = survivor.getPlayer(); - if (player == null) return false; - - return isAtHatch(player.getLocation()); - } - - private boolean tryRevealAndCheck(Survivor survivor) { - Player player = survivor.getPlayer(); - if (player == null) return false; - - if (hatch.isHidden()) { - player.sendMessage(messages.get("hatch.hidden")); - return false; - } - - if (hatch.isClosed()) { - player.sendMessage(messages.get("hatch.closed")); - return false; - } - - return false; - } - - private boolean isAtHatch(Location location) { - return hatch.isInRange(location, ESCAPE_RADIUS); - } - - private void performEscape(Survivor survivor) { - Player player = survivor.getPlayer(); - if (player == null) return; - - player.teleport(hatch.getJumpTarget()); - hatch.playEscapeEffect(); - - player.getWorld().playSound(player.getLocation(), - Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.0f); - player.sendTitle( - messages.getString("hatch.escape-title"), - messages.getString("hatch.escape-subtitle"), - 10, 60, 10); - - survivor.setState(PlayerState.ESCAPED); - - giveEscapeReward(survivor); - } - - private void giveEscapeReward(Survivor survivor) { - Player player = survivor.getPlayer(); - if (player == null) return; - - player.sendMessage(messages.get("hatch.reward")); - } - - public void forceOpenForEscape() { - if (hatch.isHidden()) { - hatch.reveal(); - } - if (!hatch.isOpen()) { - hatch.open(); - } - } - - public void notifyNearbyPlayers() { - Location hatchLoc = hatch.getLocation(); - World world = hatchLoc.getWorld(); - if (world == null) return; - - for (Player player : world.getPlayers()) { - if (player.getLocation().distance(hatchLoc) < 30) { - player.sendMessage(messages.get("hatch.open-notify")); - player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1.0f, 2.0f); - } - } - } -} diff --git a/src/main/java/dev/loki/listener/PlayerInteractListener.java b/src/main/java/dev/loki/listener/PlayerInteractListener.java index 27f81b0..0985957 100644 --- a/src/main/java/dev/loki/listener/PlayerInteractListener.java +++ b/src/main/java/dev/loki/listener/PlayerInteractListener.java @@ -32,7 +32,7 @@ public class PlayerInteractListener implements Listener { private BiConsumer onAttack; private BiConsumer onRescueAttempt; private BiConsumer onChestInteract; - private BiConsumer onHatchInteract; + private BiConsumer onGateInteract; /** Called when killer toggles sneak: (player, isSneaking) */ private BiConsumer onKillerSneak; /** Called when a survivor sneaks near another injured/downed survivor: (healer, target) */ @@ -56,7 +56,7 @@ public class PlayerInteractListener implements Listener { public void setOnAttack(BiConsumer h) { this.onAttack = h; } public void setOnRescueAttempt(BiConsumer h) { this.onRescueAttempt = h; } public void setOnChestInteract(BiConsumer h) { this.onChestInteract = h; } - public void setOnHatchInteract(BiConsumer h) { this.onHatchInteract = h; } + public void setOnGateInteract(BiConsumer h) { this.onGateInteract = h; } public void setOnKillerSneak(BiConsumer h) { this.onKillerSneak = h; } public void setOnHealSneak(BiConsumer h) { this.onHealSneak = h; } private BiConsumer onCarriedShift; @@ -245,12 +245,12 @@ public class PlayerInteractListener implements Listener { } // Gate opening — проверяем ДО генератора, чтобы ворота можно было открыть рядом с геной - if (!bp.isKiller() && onHatchInteract != null) { + if (!bp.isKiller() && onGateInteract != null) { var s = gameManager.getPlayerSession(player.getUniqueId()); if (s != null && s.getGateManager() != null) { var gate = s.getGateManager().getGateAt(player.getLocation(), 3.0); if (gate != null && !gate.isOpen()) { - onHatchInteract.accept(player, true); + onGateInteract.accept(player, true); return; } } diff --git a/src/main/java/dev/loki/map/MapConfig.java b/src/main/java/dev/loki/map/MapConfig.java index 7c2780b..1dea06e 100644 --- a/src/main/java/dev/loki/map/MapConfig.java +++ b/src/main/java/dev/loki/map/MapConfig.java @@ -95,7 +95,6 @@ public class MapConfig { applyList("generators", locs); applyList("hooks", locs); applyList("chests", locs); - applyList("windows", locs); } // ------------------------------------------------------------------------- diff --git a/src/main/java/dev/loki/map/TemplateManager.java b/src/main/java/dev/loki/map/TemplateManager.java index b5fe9f5..1666a32 100644 --- a/src/main/java/dev/loki/map/TemplateManager.java +++ b/src/main/java/dev/loki/map/TemplateManager.java @@ -83,10 +83,6 @@ public class TemplateManager { // Chest preset (1x1x1) presets.put("chest_default", new PresetMap("chest_default", "chest", new Location(null, 0, 0, 0))); - - // Hatch preset (2x1x2) - presets.put("hatch_default", new PresetMap("hatch_default", - "hatch", new Location(null, 1, 0, 1))); } public boolean placeObject(String templateName, Location location) { diff --git a/src/main/java/dev/loki/phase/EndgamePhase.java b/src/main/java/dev/loki/phase/EndgamePhase.java index 521b58c..c8e76cf 100644 --- a/src/main/java/dev/loki/phase/EndgamePhase.java +++ b/src/main/java/dev/loki/phase/EndgamePhase.java @@ -2,12 +2,8 @@ package dev.loki.phase; import dev.loki.core.GameSession; import dev.loki.gate.GateManager; -import dev.loki.hatch.Hatch; -import dev.loki.hatch.HatchCondition; -import dev.loki.hatch.HatchEscape; import dev.loki.player.BasePlayer; import dev.loki.player.PlayerState; -import dev.loki.player.Survivor; import dev.loki.ui.Sidebar; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -27,9 +23,6 @@ public class EndgamePhase implements Phase { private boolean gatesActivated; private boolean killerWin; // true если маньяк убил всех — пропускаем геймплей эндгейма private GateManager gateManager; - private Hatch hatch; - private HatchCondition hatchCondition; - private HatchEscape hatchEscape; private Sidebar sidebar; private int endgameTimer = -1; // секунд до конца эндгейма (-1 = не активно) @@ -37,13 +30,9 @@ public class EndgamePhase implements Phase { this.openTicks = 20 * 20; } - public EndgamePhase(GateManager gateManager, - Hatch hatch, HatchCondition hatchCondition) { + public EndgamePhase(GateManager gateManager) { this.openTicks = 20 * 20; this.gateManager = gateManager; - this.hatch = hatch; - this.hatchCondition = hatchCondition; - this.hatchEscape = new HatchEscape(hatch); } // ------------------------------------------------------------------------- @@ -120,7 +109,7 @@ public class EndgamePhase implements Phase { } } - updateHatch(session); + updateGates(session); checkWinConditions(session); } @@ -137,10 +126,6 @@ public class EndgamePhase implements Phase { sidebar = null; } - if (hatch != null) { - hatch.reset(); - } - if (gateManager != null) { gateManager.resetAll(); } @@ -229,29 +214,9 @@ public class EndgamePhase implements Phase { gateManager.activateEndgame(); gatesActivated = true; } - checkHatchConditions(session); session.getPlugin().getLogger().info("Endgame started!"); } - private void checkHatchConditions(GameSession session) { - if (hatch == null || hatchCondition == null) return; - int repairedGens = countRepairedGenerators(session); - hatchCondition.checkAndReveal(hatch, session.getPlayers().values(), repairedGens); - if (hatchCondition.isLastSurvivor(session.getPlayers().values())) { - hatchCondition.checkAndOpen(hatch, session.getPlayers().values(), repairedGens); - if (hatch.isOpen() && hatchEscape != null) { - hatchEscape.notifyNearbyPlayers(); - } - } - } - - private int countRepairedGenerators(GameSession session) { - if (session.getGeneratorManager() != null) { - return session.getGeneratorManager().getCompletedCount(); - } - return 0; - } - private void announceEndgameStart(GameSession session) { for (BasePlayer bp : session.getPlayers().values()) { Player p = bp.getPlayer(); @@ -271,18 +236,6 @@ public class EndgamePhase implements Phase { gateManager.updateAllGates(1.0 / openTicks); } - private void updateHatch(GameSession session) { - if (hatch == null || !hatch.isOpen() || hatchEscape == null) return; - for (BasePlayer player : session.getPlayers().values()) { - if (player.isKiller()) continue; - PlayerState st = player.getState(); - if (st != PlayerState.HEALTHY && st != PlayerState.INJURED) continue; - if (hatchEscape.canEscape((Survivor) player)) { - hatchEscape.tryEscape((Survivor) player); - } - } - } - private void checkWinConditions(GameSession session) { if (complete) return; int survivorsAlive = 0; diff --git a/src/main/java/dev/loki/phase/GameplayInteraction.java b/src/main/java/dev/loki/phase/GameplayInteraction.java index bf03269..a077b94 100644 --- a/src/main/java/dev/loki/phase/GameplayInteraction.java +++ b/src/main/java/dev/loki/phase/GameplayInteraction.java @@ -301,8 +301,8 @@ public class GameplayInteraction { damageSystem.getKillerController().getCarry().onSurvivorShift(survivor.getUuid()); }); - // Gate (uses hatch callback - triggered on PORTAL/HOPPER interaction) - interactListener.setOnHatchInteract((player, ignored) -> { + // Gate - triggered on HOPPER interaction + interactListener.setOnGateInteract((player, ignored) -> { BasePlayer bp = session.getPlayer(player.getUniqueId()); if (bp == null || bp.isKiller()) return; Survivor survivor = (Survivor) bp; @@ -337,7 +337,7 @@ public class GameplayInteraction { interactListener.setOnCarriedShift(null); interactListener.setOnGeneratorSkillCheckSneak(null); interactListener.setOnGeneratorInteract(null); - interactListener.setOnHatchInteract(null); + interactListener.setOnGateInteract(null); } } } diff --git a/src/main/resources/game.yml b/src/main/resources/game.yml index 8c843b7..5902cc1 100644 --- a/src/main/resources/game.yml +++ b/src/main/resources/game.yml @@ -176,20 +176,6 @@ bossbar: # Расстояние полного заполнения (блоков) full-range: 8 -# Окна -window: - # Быстрый волт выжившего (секунд) - vault-survivor-fast: 1.0 - - # Медленный волт выжившего (секунд) - vault-survivor-slow: 1.5 - - # Волт киллера (секунд) - vault-killer: 1.5 - - # Блокировка после 3 волтов подряд (секунд) - vault-block-seconds: 15 - # Эндгейм endgame: # Время открытия ворот (секунд) @@ -229,14 +215,6 @@ scoreboard: color-healing: "GREEN" color-hooked: "DARK_RED" -# Люк -hatch: - # Минимум живых для открытия люка - min-survivors-for-open: 1 - - # Условие: живых < починенных генераторов - require-more-gens-than-survivors: true - # Блоки для объектов (спавнятся на местах при старте игры) blocks: # Блок на месте генератора diff --git a/src/main/resources/locations.yml b/src/main/resources/locations.yml index 5d9f037..c981cf4 100644 --- a/src/main/resources/locations.yml +++ b/src/main/resources/locations.yml @@ -20,9 +20,6 @@ hooks: [] # Пример: # - "world,120.5,65.0,180.5,0.0,0.0" -# Окна (много) -windows: [] - # Сундуки с лутом (3-4) chests: [] diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index f244ec6..c2eb1c7 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -64,7 +64,7 @@ dbdadmin: hooks: usage: "%admin-prefix%&c/dbd admin hooks <игрок> <0-3>" sender: "%admin-prefix%&a%s hooks=%d" - invalid: "%admin-prefix%&cЧисло 0–3." + invalid: "%admin-prefix%&cЧисло 0-3." kill: sender: "%admin-prefix%&c%s → DEAD" resolve: @@ -152,8 +152,8 @@ lobby: # ── Роли ─────────────────────────────────────── role: - killer: "%prefix%&4Вы — Маньяк! Поймайте всех выживших!" - survivor: "%prefix%&bВы — Выживший! Почините генераторы и сбегите!" + killer: "%prefix%&4Вы - Маньяк! Поймайте всех выживших!" + survivor: "%prefix%&bВы - Выживший! Почините генераторы и сбегите!" # ── Генераторы ───────────────────────────────── @@ -256,17 +256,6 @@ gate: door-interrupted: "&7Открытие прервано!" door-actionbar: "&aОткрываем ворота... (зажмите ПКМ)" -# ── Люк ──────────────────────────────────────── - -hatch: - too-far: "&cПодойдите ближе к люку!" - hidden: "&7Люк скрыт..." - closed: "&cЛюк закрыт!" - open-notify: "&e&lЛюк открыт!" - escape-title: "&a&lПОБЕГ!" - escape-subtitle: "&7Вы сбежали через люк!" - reward: "&a+5000 Очков — Побег через люк!" - # ── Игрок вышел ──────────────────────────────── quit: @@ -286,19 +275,19 @@ minigames: usage: dbd-header: "&6=== DBD Команды ===" - dbd-join: "&7/dbd join [name] — присоединиться к игре/лобби" - dbd-leave: "&7/dbd leave — покинуть игру" - dbd-lobby: "&7/dbd lobby — телепорт в лобби" - dbd-create: "&7/dbd create — создать лобби" - dbd-list: "&7/dbd list — список лобби" - dbd-delete: "&7/dbd delete — удалить лобби" - dbd-admin: "&e/dbd admin — управление игроками в матче" - dbd-forcestart: "&e/dbd forcestart — форс старт" - dbd-stop: "&e/dbd stop — остановить игру" - dbd-reload: "&e/dbd reload — перезагрузить конфиги" - dbd-setlobby: "&e/dbd setlobby — установить точку лобби" - dbd-save: "&e/dbd save — сохранить карту" - dbd-load: "&e/dbd load — загрузить карту" + dbd-join: "&7/dbd join [name] - присоединиться к игре/лобби" + dbd-leave: "&7/dbd leave - покинуть игру" + dbd-lobby: "&7/dbd lobby - телепорт в лобби" + dbd-create: "&7/dbd create - создать лобби" + dbd-list: "&7/dbd list - список лобби" + dbd-delete: "&7/dbd delete - удалить лобби" + dbd-admin: "&e/dbd admin - управление игроками в матче" + dbd-forcestart: "&e/dbd forcestart - форс старт" + dbd-stop: "&e/dbd stop - остановить игру" + dbd-reload: "&e/dbd reload - перезагрузить конфиги" + dbd-setlobby: "&e/dbd setlobby - установить точку лобби" + dbd-save: "&e/dbd save - сохранить карту" + dbd-load: "&e/dbd load - загрузить карту" admin-header: "&6=== /dbd admin ===" admin-heal: "&6/dbd admin heal [игрок]" admin-down: "&6/dbd admin down [игрок]" @@ -306,20 +295,20 @@ usage: admin-state: "&6/dbd admin state <игрок> <статус>" admin-hooks: "&6/dbd admin hooks <игрок> <0-3>" admin-kill: "&6/dbd admin kill [игрок]" - admin-jump: "&6/dbd admin jump [on/off] — вкл/выкл прыжки" + admin-jump: "&6/dbd admin jump [on/off] - вкл/выкл прыжки" setup-header: "&6=== DBD Setup ===" - setup-wand: "&6/dbdsetup wand — Получить ванд (ЛКМ/ПКМ для ворот)" - setup-hook: "&6/dbdsetup set hook — Установить крюк (ломай блок)" - setup-chest: "&6/dbdsetup set chest — Установить сундук" - setup-generator: "&6/dbdsetup set generator — Установить генератор" - setup-killer-spawn: "&6/dbdsetup set killer-spawn — Спавн киллера (только 1)" - setup-survivor-spawn: "&6/dbdsetup set survivor-spawn — Спавн выжившего (до 4)" - setup-gate: "&6/dbdsetup set gate A|B — Установить ворота (из точек ванда)" - setup-clear: "&6/dbdsetup clear [тип] — Очистить объекты (без разрушения блоков)" - setup-delete: "&6/dbdsetup delete <тип> <#> — Удалить конкретный объект" - setup-clear-spawns: "&6/dbdsetup clear-spawns — Очистить все спавны" - setup-lobby: "&6/dbdsetup lobby — Установить точку лобби" + setup-wand: "&6/dbdsetup wand - Получить ванд (ЛКМ/ПКМ для ворот)" + setup-hook: "&6/dbdsetup set hook - Установить крюк (ломай блок)" + setup-chest: "&6/dbdsetup set chest - Установить сундук" + setup-generator: "&6/dbdsetup set generator - Установить генератор" + setup-killer-spawn: "&6/dbdsetup set killer-spawn - Спавн киллера (только 1)" + setup-survivor-spawn: "&6/dbdsetup set survivor-spawn - Спавн выжившего (до 4)" + setup-gate: "&6/dbdsetup set gate A|B - Установить ворота (из точек ванда)" + setup-clear: "&6/dbdsetup clear [тип] - Очистить объекты (без разрушения блоков)" + setup-delete: "&6/dbdsetup delete <тип> <#> - Удалить конкретный объект" + setup-clear-spawns: "&6/dbdsetup clear-spawns - Очистить все спавны" + setup-lobby: "&6/dbdsetup lobby - Установить точку лобби" admin-list-header: "&6=== DBD Admin ===" - admin-list-list: "&6/dbdadmin list — Список всех объектов" - admin-list-type: "&6/dbdadmin list <тип> — Список по типу" - admin-world: "&6/dbdadmin world — Телепорт в мир" + admin-list-list: "&6/dbdadmin list - Список всех объектов" + admin-list-type: "&6/dbdadmin list <тип> - Список по типу" + admin-world: "&6/dbdadmin world - Телепорт в мир" From 4482b3a0ea76952034e6d351486629916a170cde Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Mon, 15 Jun 2026 14:00:38 +0200 Subject: [PATCH 08/10] cleanup: remove md/txt files, add README, various fixes --- COMMANDS_GUIDE.md | 489 ---------------- DBD_Plugin_TZ.md | 523 ------------------ PLAN.md | 392 ------------- README.md | 65 +++ .../java/dev/loki/command/SetupCommand.java | 44 +- .../java/dev/loki/config/LocationsConfig.java | 4 - src/main/java/dev/loki/gate/ExitGate.java | 12 +- .../dev/loki/listener/SkillCheckListener.java | 14 +- src/main/java/dev/loki/map/MapBuilder.java | 4 - .../generator/GuiRouletteMinigame.java | 2 +- src/main/resources/game.yml | 6 - src/main/resources/locations.yml | 4 - src/main/resources/messages.yml | 10 +- 13 files changed, 110 insertions(+), 1459 deletions(-) delete mode 100644 COMMANDS_GUIDE.md delete mode 100644 DBD_Plugin_TZ.md delete mode 100644 PLAN.md create mode 100644 README.md diff --git a/COMMANDS_GUIDE.md b/COMMANDS_GUIDE.md deleted file mode 100644 index 6b94582..0000000 --- a/COMMANDS_GUIDE.md +++ /dev/null @@ -1,489 +0,0 @@ -# Dead by Daylight Plugin — Руководство команд - -**Версия:** 1.2 -**Обновлено:** Июнь 2026 -**Платформа:** Minecraft 1.21.5 (Paper) - ---- - -## Содержание - -1. [Фазы игры](#фазы-игры) -2. [Команды игроков — /dbd](#команды-игроков--dbd) -3. [Команды администратора — /dbdadmin](#команды-администратора--dbdadmin) -4. [Команды настройки карты — /dbdsetup](#команды-настройки-карты--dbdsetup) -5. [Права доступа](#права-доступа) -6. [Порядок настройки сервера](#порядок-настройки-сервера) -7. [Таблица всех команд](#таблица-всех-команд) - ---- - -## Фазы игры - -``` -LOBBY - Игроки делают /dbd join → телепорт в мир lobby - Action bar показывает: ▶ Старт через: 45с ████████░░ (3/5) - Когда набралось минимум игроков — идёт отсчёт 60 сек - При нехватке игроков — таймер сбрасывается - ↓ -ROLE ASSIGN (5 сек) - Случайно выбирается 1 киллер, остальные — выжившие - Показывается тайтл с ролью - Все телепортируются на свои спавны в мире game - ↓ -GAMEPLAY - Выжившие чинят генераторы (нужно 5 из 7) - Киллер охотится - При починке всех нужных генераторов — открываются ворота - ↓ -ENDGAME (2 минуты) - Выжившие открывают ворота и убегают - Или используют люк (если остался 1 выживший) - Коллапс через 120 сек убивает всех оставшихся -``` - ---- - -## Команды игроков — /dbd - -Все команды ниже доступны любому игроку (`mdbd.player`, по умолчанию `true`). - ---- - -### /dbd join - -Присоединиться к игровой очереди. - -``` -/dbd join -``` - -- Добавляет игрока в текущую сессию как выжившего (роль назначится позже) -- Телепортирует в мир `lobby` -- В action bar начинает отображаться счётчик и таймер -- Если игра не создана — сообщение об ошибке - -``` -→ [DBD] Вы присоединились к игре! -→ [DBD] PlayerName присоединился к очереди! (1/5) -``` - ---- - -### /dbd leave - -Покинуть сессию. - -``` -/dbd leave -``` - -- В лобби: просто убирает из очереди, таймер может сброситься -- В игре: выживший считается мёртвым, киллер завершает игру -- Игрок телепортируется обратно в `lobby` - -``` -→ [DBD] Вы покинули игру -``` - ---- - -### /dbd lobby - -Телепортироваться в лобби-мир. - -``` -/dbd lobby -``` - -- Работает в любой момент, не убирает из сессии -- Телепортирует на точку спавна лобби (из `locations.yml`) или на спавн мира `lobby` - -``` -→ [DBD] Вы телепортированы в лобби! -``` - ---- - -## Команды администратора — /dbd (admin) - -Требуют право `mdbd.admin` (по умолчанию только OP). - ---- - -### /dbd create - -Создать новую игровую сессию. - -``` -/dbd create -``` - -- Создаёт сессию и открывает лобби -- Нельзя создать вторую сессию пока первая активна - -``` -→ [DBD] Игра создана! -→ [DBD] Игра уже существует (если уже есть) -``` - ---- - -### /dbd forcestart - -Принудительно запустить игру, пропустив таймер. - -``` -/dbd forcestart -``` - -- Работает только если сессия в фазе LOBBY -- Игроков в очереди может быть меньше минимума - -``` -→ [DBD] Игра форсирована! -``` - ---- - -### /dbd stop - -Немедленно завершить текущую сессию. - -``` -/dbd stop -``` - -- Все игроки телепортируются в `lobby` -- Сессия уничтожается, можно создавать новую - -``` -→ [DBD] Игра остановлена -``` - ---- - -### /dbd reload - -Перезагрузить все конфиги без перезапуска сервера. - -``` -/dbd reload -``` - -Перезагружает: `config.yml`, `game.yml`, `messages.yml`, `skillcheck.yml`, `locations.yml`, `generators.yml` - -``` -→ [DBD] Конфиги перезагружены! -``` - -> Если игра в процессе — сначала `/dbd stop`, иначе новые настройки применятся только к следующей сессии. - ---- - -### /dbd setlobby - -Установить текущую позицию игрока как точку спавна лобби. - -``` -/dbd setlobby -``` - -- Сохраняется в `locations.yml` -- Эквивалентно `/dbdsetup lobby` - -``` -→ [DBD] Лобби установлено! -``` - ---- - -## Команды администратора — /dbdadmin - -Требуют право `mdbd.admin`. Все команды только для игроков (не консоли). - ---- - -### /dbdadmin create generator - -Режим расстановки генераторов. - -``` -/dbdadmin create generator -``` - -- Включает режим: в action bar оранжевая подсказка -- **Сломай блок** — координаты сохранятся, блок не разрушится -- Повторная команда — отключает режим -- Режим остаётся активным для нескольких генераторов подряд - -``` -→ Режим выбора генератора включен! -→ Сломайте блок, чтобы установить генератор -(сломал блок) -→ Генератор установлен! Всего: 1 -``` - -**Tab complete:** `generator` - ---- - -### /dbdadmin list - -Список всех установленных генераторов. - -``` -/dbdadmin list -``` - -``` -=== Генераторы (3) === -[0] game:100.00,64.00,200.00 -[1] game:150.00,64.00,150.00 -[2] game:200.00,64.00,100.00 -``` - ---- - -### /dbdadmin remove \ - -Удалить генератор по ID из списка. - -``` -/dbdadmin remove 0 -``` - -**Tab complete:** подсказывает существующие ID (0, 1, 2...) - -``` -→ Генератор удален: game:100.00,64.00,200.00 -→ Генератор с ID 5 не найден (если нет такого) -``` - ---- - -### /dbdadmin clear - -Удалить все генераторы. - -``` -/dbdadmin clear -``` - -> Необратимо. - -``` -→ Все генераторы удалены -``` - ---- - -### /dbdadmin world \<мир\> - -Телепортироваться в указанный мир для настройки карты. - -``` -/dbdadmin world lobby -/dbdadmin world game -/dbdadmin world <любое_название_мира> -``` - -- `lobby` — телепорт в мир-лобби (void, платформа 7x7) -- `game` — телепорт в игровой мир -- Любое другое название — телепорт в мир с таким именем (если загружен) - -``` -→ Телепортирован в мир: lobby -→ Мир не найден: abc (если мир не существует) -``` - -**Tab complete:** `lobby`, `game` - ---- - -## Команды настройки карты — /dbdsetup - -Требуют право `mdbd.admin`. - ---- - -### /dbdsetup wand - -Выдать топорик для расстановки ворот. - -``` -/dbdsetup wand -``` - -- Выдаёт деревянный топорик (WOODEN_AXE) с подписью DBD Setup Wand -- **ЛКМ** по блоку = точка 1 (pos1) -- **ПКМ** по блоку = точка 2 (pos2) -- Только для ворот. Для остальных объектов ванд не нужен. - ---- - -### /dbdsetup set \<тип\> - -Войти в режим установки объекта. **Сломай блок** — объект установится на его месте, блок восстановится. - -``` -/dbdsetup set generator -/dbdsetup set hook -/dbdsetup set pallet -/dbdsetup set chest -/dbdsetup set killer-spawn -/dbdsetup set survivor-spawn -``` - -| Тип | Описание | Рекомендуемое кол-во | -|-----|----------|---------------------| -| `generator` | Генератор | 7 | -| `hook` | Крюк | 7–10 | -| `pallet` | Паллет | 15–20 | -| `chest` | Сундук | 5–10 | -| `killer-spawn` | Спавн киллера | 1 | -| `survivor-spawn` | Спавн выжившего | 4 | - -``` -→ Режим установки: hook -→ Сломай блок чтобы установить (блок восстановится) -(ломаешь блок) -→ Крюк установлен: [game, 150, 65, 200] -``` - ---- - -### /dbdsetup set gate A|B - -Установить ворота через две точки топориком. - -``` -/dbdsetup wand — получить топорик -ЛКМ по блоку → точка 1 — нижний левый угол -ПКМ по блоку → точка 2 — верхний правый угол -/dbdsetup set gate A — установить ворота A в центре между точками -/dbdsetup set gate B — установить ворота B -``` - -Центр ворот вычисляется: X = средняя точка, Y = минимальная из двух. - -``` -→ [Wand] Точка 1: [game, 100, 64, 200] -→ [Wand] Точка 2: [game, 110, 64, 210] -→ Ворота A установлены: [game, 105, 64, 205] -``` - ---- - -### /dbdsetup build - -Построить карту по шаблону и `locations.yml`. - -``` -/dbdsetup build -``` - -``` -→ Строительство карты... -→ Карта построена! -``` - ---- - -### /dbdsetup clear - -Очистить карту. - -``` -/dbdsetup clear -``` - -``` -→ Очистка карты... -→ Карта очищена! -``` - ---- - -### /dbdsetup lobby - -Установить спавн лобби на текущую позицию. - -``` -/dbdsetup lobby -``` - -Аналог `/dbd setlobby`. Сохраняется в `locations.yml`. - ---- - -## Права доступа - -| Право | Кому | Что даёт | -|-------|------|----------| -| `mdbd.player` | Все (`default: true`) | `/dbd join`, `leave`, `lobby` | -| `mdbd.admin` | OP (`default: op`) | Все остальные команды | - ---- - -## Порядок настройки сервера - -### Первый запуск - -1. Запустить сервер — плагин создаст миры `lobby` и `game` автоматически -2. `/dbdadmin world lobby` — войти в лобби-мир и осмотреться (платформа 7x7) -3. `/dbd setlobby` — встать на нужную точку и сохранить спавн лобби - -### Настройка игровой карты - -4. `/dbdadmin world game` — перейти в игровой мир -5. Построить или загрузить карту -6. Расставить объекты: - - `/dbdsetup set generator` → ломать блоки для генераторов - - `/dbdsetup set hook` → ломать блоки для крюков - - `/dbdsetup set pallet` → ломать блоки для паллетов - - `/dbdsetup set chest` → ломать блоки для сундуков -7. Установить спавны: - - `/dbdsetup set killer-spawn` → спавн киллера - - `/dbdsetup set survivor-spawn` → 4 раза для выживших -8. Установить ворота: - - `/dbdsetup wand` → получить топорик - - ЛКМ/ПКМ по блокам → отметить углы ворот - - `/dbdsetup set gate A` и `/dbdsetup set gate B` - -### Тест - -8. `/dbd create` — создать сессию -9. `/dbd join` (5 игроков или меньше с форс-стартом) -10. `/dbd forcestart` — запустить не дожидаясь таймера - ---- - -## Таблица всех команд - -| Команда | Право | Описание | -|---------|-------|----------| -| `/dbd join` | player | Войти в очередь | -| `/dbd leave` | player | Покинуть сессию | -| `/dbd lobby` | player | Телепорт в лобби | -| `/dbd create` | admin | Создать сессию | -| `/dbd forcestart` | admin | Принудительный старт | -| `/dbd stop` | admin | Остановить игру | -| `/dbd reload` | admin | Перезагрузить конфиги | -| `/dbd setlobby` | admin | Сохранить спавн лобби | -| `/dbdadmin create generator` | admin | Режим расстановки генераторов | -| `/dbdadmin list` | admin | Список генераторов | -| `/dbdadmin remove ` | admin | Удалить генератор | -| `/dbdadmin clear` | admin | Очистить все генераторы | -| `/dbdadmin world ` | admin | Телепорт в мир | -| `/dbdsetup wand` | admin | Топорик для ворот (ЛКМ/ПКМ) | -| `/dbdsetup set <тип>` | admin | Установить объект (сломать блок) | -| `/dbdsetup set gate A\|B` | admin | Установить ворота (из точек ванда) | -| `/dbdsetup build` | admin | Построить карту | -| `/dbdsetup clear` | admin | Очистить карту | -| `/dbdsetup lobby` | admin | Сохранить спавн лобби | - ---- - -*Dead by Daylight Minecraft Plugin — актуально для версии 1.1+* diff --git a/DBD_Plugin_TZ.md b/DBD_Plugin_TZ.md deleted file mode 100644 index 4424aa9..0000000 --- a/DBD_Plugin_TZ.md +++ /dev/null @@ -1,523 +0,0 @@ -# DEAD BY DAYLIGHT — Minecraft Plugin -## Техническое Задание (ТЗ) -> Полная реализация механик оригинальной игры 4v1 - ---- - -## Содержание - -1. [Общее описание проекта](#1-общее-описание-проекта) -2. [Распределение ролей и старт игры](#2-распределение-ролей-и-старт-игры) -3. [Механики выжившего](#3-механики-выжившего-survivor) -4. [Генераторы](#4-генераторы-generators) -5. [Механики киллера](#5-механики-киллера-killer) -6. [Паллеты и окна](#6-паллеты-pallets-и-окна-windows) -7. [Выходные ворота и люк](#7-выходные-ворота-exit-gates-и-люк-hatch) -8. [Предметы для выживших](#8-предметы-items-для-выживших) -9. [Bloodpoints и прогрессия](#9-bloodpoints-и-прогрессия) -10. [Система перков](#10-система-перков-perks) -11. [Эндгейм и итоги матча](#11-эндгейм-и-итоги-матча) -12. [Пользовательский интерфейс](#12-пользовательский-интерфейс-hud) -13. [Конфигурация](#13-конфигурация-configyml) -14. [Команды и права](#14-команды-и-права) -15. [Архитектура плагина](#15-архитектура-плагина) -16. [Приоритет разработки](#16-приоритет-разработки) - ---- - -## 1. Общее описание проекта - -### 1.1 Цель плагина - -Плагин реализует полноценную мини-игру Dead by Daylight (4v1) на Minecraft-сервере. Используется готовая карта, предоставленная заказчиком. Плагин управляет всем игровым процессом: распределением ролей, механиками выживших и киллера, победными условиями, интерфейсом и звуками. - -### 1.2 Технические требования - -| Параметр | Значение | -|---|---| -| Платформа | Paper / Spigot 1.20.x+ | -| Язык | Java 17+ | -| Зависимости | ProtocolLib, Citizens2 (опционально), PacketEvents | -| Кол-во игроков | 5 (1 киллер + 4 выживших) | -| Карта | Предоставляется отдельно (worldname задаётся в `config.yml`) | -| Gamemode | Adventure mode на протяжении всей игры | - ---- - -## 2. Распределение ролей и старт игры - -### 2.1 Лобби и ожидание - -- Лобби-мир отдельный от игровой карты. -- Минимум для старта: 5 игроков (настраивается: `min_players`, `max_players`). -- Таймер ожидания: 60 секунд после набора минимума (`countdown_seconds`). -- Если игроков < минимума — таймер сбрасывается. -- В лобби показывается статус: сколько игроков зашло / нужно. - -### 2.2 Назначение ролей - -- Один игрок случайно становится **Киллером (Killer)**. -- Остальные 4 становятся **Выжившими (Survivors)**. -- Реализовать систему очереди: если игрок давно не был киллером — шанс повышается. -- Роли объявляются через Title + Subtitle (красный текст для киллера, белый для выжившего). -- Роль киллера не раскрывается другим выжившим до спавна (5-секундная задержка перед телепортом киллера). - -### 2.3 Спавн - -- Спавн-точки прописаны в `config.yml` (4 точки для выживших + 1 для киллера). -- Выжившие телепортируются одновременно. -- Киллер телепортируется через **5 секунд** после выживших (grace period). -- Во время grace period киллер видит таймер в ActionBar. -- Генераторы, хуки, выходы и другие объекты расставляются при старте игры по координатам из `config.yml`. - -> ⚠ Все координаты (спавны, хуки, генераторы, выходы, подвал) задаются в `config.yml` — не хардкодятся в коде. - ---- - -## 3. Механики выжившего (Survivor) - -### 3.1 Состояния здоровья - -Выживший имеет три состояния — переходы строго последовательные: - -| Состояние | Описание | Визуал в Minecraft | -|---|---|---| -| **Healthy** (здоров) | Может бежать, прыгать, взаимодействовать | Полное здоровье, без эффектов | -| **Injured** (ранен) | Оставляет следы крови, издаёт стоны, скорость чуть снижена | Частицы крови, звук боли каждые 3 сек | -| **Downed** (повален) | Ползёт по полу, не может бежать или взаимодействовать | Crawl-анимация (Sneak + замедление), скорость 30% | -| **Hooked** (на крюке) | Привязан к крюку, ждёт спасения | Заморожен, анимация качания на крюке | -| **Dead** (мёртв) | Выбывает из игры | Spectator mode | - -### 3.2 Переходы состояний - -- **Healthy → Injured:** одно попадание от киллера. -- **Injured → Downed:** второе попадание от киллера. -- **Downed → Hooked:** киллер подбирает (ПКМ) и несёт к крюку. -- **Hooked → Dead:** истекло 2 стадии крюка, никто не спас. -- **Injured → Healthy:** использование аптечки или спасение с крюка. - -### 3.3 Передвижение - -- **Healthy:** обычная скорость + возможность спринта. -- **Injured:** скорость снижена на 5% (speed effect). -- **Downed:** только ползти — отрицательный Speed, принудительный Sneak, без прыжков. -- **Спринт (Exhaustion):** можно спринтовать конечное время (`exhaustion_seconds`, по умолчанию 3 сек спринта, затем 5 сек кулдауна). - -> ⚠ Спринт — ключевая механика для чейса. Реализовать через `isSprinting()` + кастомный кулдаун. - -### 3.4 Исцеление (Healing) - -- **Аптечка (Med-Kit):** зажать ПКМ 10 секунд, прогресс-бар в ActionBar. -- **Исцеление другим выжившим:** подойти вплотную, зажать ПКМ 16 секунд (медленнее, чем аптечкой). -- Если движение прервалось (игрок отошёл, получил удар) — прогресс сбрасывается. -- Иконка прогресса в ActionBar: `[████░░░░░░] Исцеление 40%` - -### 3.5 Механика крюка (Hook) - -После того как киллер повесил выжившего на крюк: - -| Стадия | Длительность | Событие | -|---|---|---| -| Stage 1 | 60 секунд | Выживший висит. Можно спасти. В ActionBar — таймер. | -| Stage 1 → 2 | Автоматически | Если не спасли за 60 сек — переход на Stage 2. | -| Stage 2 | 60 секунд | Выживший борется с Сущностью. Каждые 2 сек — Skill Check (QTE). | -| Stage 2 провален | Мгновенно | Выживший умирает — переход в Spectator. | -| Спасение с крюка | 2 секунды | Другой выживший снимает с крюка (прогресс-бар). Стадия запоминается. | - -- Один и тот же выживший может быть повешен максимум **3 раза** (`hook_count`). На 3-й раз — мгновенная смерть. -- Крюки в подвале (Basement) не уничтожаются и дают бонусные Bloodpoints. - -> ⚠ Skill Check на Stage 2 — случайное появление индикатора в Title. Игрок должен нажать Shift или Drop в нужный момент. Промах — мгновенная смерть. - -### 3.6 Спасение с крюка - -- Выживший подходит к крюку с союзником на расстояние 2 блока. -- Зажимает ПКМ (или Sneak) в течение 2 секунд — прогресс в ActionBar. -- Спасённый получает статус Injured (или остаётся Injured). -- Спасатель не получает защиты — может быть немедленно атакован. -- **Borrowed Time:** если киллер стоит рядом с крюком в момент спасения — спасённый получает 10 сек защиты Endurance (не переходит в Downed с первого удара). - -### 3.7 Ползание (Dying State) - -- Повалённый выживший ползёт со скоростью 30% от нормальной. -- Может ползти к другому выжившему — тот может его поднять (Recovery, 4 секунды). -- После Recovery выживший встаёт в статусе Injured. -- Самовосстановление невозможно без специального перка. -- Повалённый выживший издаёт стоны (слышимые киллеру). - ---- - -## 4. Генераторы (Generators) - -### 4.1 Общие правила - -- На карте спавнится **7 генераторов**, нужно починить **5**. -- Количество настраивается: `total_generators`, `required_generators` в `config.yml`. -- Починённые генераторы светятся (частицы + звук). -- Киллер видит ауру всех непочиненных генераторов (через частицы или Sidebar). - -### 4.2 Процесс починки - -- Выживший подходит к генератору и зажимает ПКМ — начинается починка. -- Прогресс отображается в ActionBar. -- Базовое время починки: **80 секунд** (один выживший). -- Два выжившего на генераторе: скорость ×1.5 (`gen_coop_multiplier`). -- Три и более: скорость ×2.0 (ограничено). -- Если выживший отошёл или получил удар — прогресс частично откатывается (regression). - -### 4.3 Skill Checks (Проверки навыка) - -- В Title показывается круговой индикатор (симулируется через Title-анимации). -- Игрок должен нажать **Drop (Q)** в нужный момент (попасть в зелёную зону). -- **Успешный Skill Check:** +5% к прогрессу генератора + бонусные Bloodpoints. -- **Провальный Skill Check:** взрыв — генератор теряет 10% прогресса, громкий звук (слышен киллеру в радиусе 40 блоков). -- Частота skill check: раз в 20–40 секунд (рандомно). - -> ⚠ Звук провального skill check — важнейший инструмент для киллера. Реализовать через `playSound()` с большим радиусом. - -### 4.4 Регрессия генератора - -- Если все выжившие отошли от работающего генератора — он начинает откатываться (0.25% в секунду). -- Киллер может ударить по генератору (ПКМ) — **Kick:** мощная регрессия 2.5% в секунду на 30 секунд. -- Регрессию можно остановить — выживший подходит и нажимает ПКМ. -- Взорванный генератор издаёт звук и выбрасывает частицы взрыва. - ---- - -## 5. Механики киллера (Killer) - -### 5.1 Базовые характеристики - -| Параметр | Значение | Настройка | -|---|---|---| -| Скорость | 115% от скорости выжившего | `killer_speed` | -| Terror Radius | 32 блока | `terror_radius` | -| Урон атаки | Переводит в Injured / Downed | Не числовой — по состоянию | -| Кулдаун атаки | 2.5 секунды | `attack_cooldown` | -| Перенос выжившего | 92% скорости | `carry_speed` | - -### 5.2 Terror Radius и Red Stain - -- **Terror Radius** — зона 32 блока вокруг киллера. Выжившие в этой зоне слышат сердцебиение. -- Интенсивность звука увеличивается при сближении (3 уровня: далеко / близко / рядом). -- **Red Stain** — красное свечение на земле за киллером (частицы). Показывает направление взгляда. -- Реализация Red Stain: каждые 0.5 сек спавнить Dust-частицы красного цвета позади головы киллера. - -### 5.3 Атака и удар - -- **Базовая атака:** ЛКМ по выжившему. Урон по состояниям (Healthy→Injured или Injured→Downed). -- После удара — кулдаун 2.5 сек (замедление на 0.5 сек). -- Нельзя атаковать сквозь окна / паллеты (проверка LineOfSight). -- **Bloodlust:** если киллер преследует выжившего >15 секунд без попадания — бонус скорости: - - Тир 1: +3% - - Тир 2: +5% - - Тир 3: +8% - - Тиры сбрасываются при ударе или смене цели. - -### 5.4 Подъём и перенос выжившего - -- Когда выживший Downed — киллер нажимает ПКМ для подъёма (2.5 сек анимации). -- Во время переноса: киллер замедлен до 92% скорости, не может атаковать. -- Выживший сидит на киллере (через ArmorStand или Mount). -- Чтобы повесить: киллер подходит к хуку и нажимает ПКМ. -- **Wiggle (вырывание):** выживший нажимает Sneak/Jump быстро — прогресс побега в ActionBar. При 100% — выживший падает рядом в Downed статусе. -- Время вырывания: **16 секунд** (`wiggle_duration`). - -### 5.5 Взаимодействие с генераторами - -- Киллер нажимает ПКМ на генератор — **Kick** (регрессия, см. раздел 4.4). -- Киллер видит ауру всех незаконченных генераторов в Sidebar (иконки + расстояние). - -### 5.6 Подвал (Basement) - -- Специальная зона на карте с 4 крюками. -- Крюки в подвале **нельзя саботировать**. -- Перевод выжившего в подвал засчитывается быстрее + бонус Bloodpoints. - ---- - -## 6. Паллеты (Pallets) и Окна (Windows) - -### 6.1 Паллеты - -- Паллеты — деревянные барьеры на карте (блоки, отмеченные в конфиге). -- Выживший подходит к паллете и нажимает ПКМ — паллета падает (standing → dropped). -- Если киллер коснулся упавшей паллеты — **Stun 2.5 сек** (звук, частицы). -- Киллер может **сломать паллету**: зажать ПКМ на 3 секунды. Паллета исчезает навсегда. -- Количество паллет на карте конечно. Статус каждой хранится в памяти. -- Выживший может пробежать через упавшую паллету (Vault, 0.6 сек). - -### 6.2 Окна (Windows) - -- Окна — прыжковые зоны в стенах карты (координаты в конфиге). -- Выживший запрыгивает в окно: **1 секунда** анимации Vault (замедление → ускорение). -- Киллер тоже может прыгнуть в окно, но медленнее (1.5 сек). -- **Fake Vault (Mindgame):** игрок может зайти в начало вота и выйти обратно. - -> ⚠ Паллеты и окна — основа loop-механики чейса. Без правильного расположения на карте игра будет несбалансированной. - ---- - -## 7. Выходные ворота (Exit Gates) и Люк (Hatch) - -### 7.1 Выходные ворота - -- После починки 5 генераторов активируются **2 выходных ворот** (`gate_locations`). -- Рубильник ворот загорается (смена блока, звук). -- Выживший взаимодействует с рубильником **20 секунд** (прогресс в ActionBar). -- Если прервать — прогресс **не откатывается** (в отличие от генераторов). -- Открытые ворота остаются открытыми навсегда. -- Выживший пересекает границу выхода → **ESCAPED!** (Title). -- **Эндгейм-коллапс:** через 2 минуты после открытия первых ворот — все оставшиеся выжившие умирают. - -### 7.2 Люк (Hatch) - -- Люк появляется, когда выживших меньше, чем непочиненных генераторов. -- Правило: если X выживших живы и < X генераторов починено — люк открыт. -- Последний выживший **всегда** видит открытый люк. -- Координата люка — `hatch_location` в конфиге. -- Прыжок в люк = Escape (побег через люк). -- Киллер может **закрыть люк** (ПКМ). После этого активируется End Game Collapse. -- Закрытый люк можно открыть выжившим с **Ключом (Key)** за 2.5 секунды. - ---- - -## 8. Предметы (Items) для выживших - -Предметы выдаются игрокам перед игрой или находятся в Сундуках (Chests) на карте. Максимум **1 предмет** в руках. - -| Предмет | Действие | MC-предмет | Ограничение | -|---|---|---|---| -| **Med-Kit** | Лечит Injured → Healthy за 10 сек | Red Dye / Custom | 1 заряд | -| **Flashlight** | Слепит киллера (Blindness 2 сек) | Glowstone Dust / Custom | 8 использований | -| **Toolbox** | Ускоряет починку гена на 30% | Iron Pickaxe / Custom | 1 генератор | -| **Key** | Открывает закрытый люк | Gold Nugget / Custom | 1 использование | -| **Map** | Показывает ауру генераторов выжившим | Paper / Custom | Пассивно | - -### 8.1 Сундуки - -- На карте расставлено N сундуков (`chest_locations` в конфиге). -- Каждый сундук при открытии выдаёт случайный предмет (весовая таблица в `loot_table.yml`). -- Открытие: **3 секунды** (прогресс-бар). Один сундук — один предмет навсегда. -- Киллер может видеть ауры сундуков (опционально, через перк). - ---- - -## 9. Bloodpoints и прогрессия - -Bloodpoints — внутриигровая валюта, начисляется за действия в раунде. Хранятся в базе данных (SQLite или YAML). - -| Действие | Выживший (BP) | Киллер (BP) | -|---|---|---| -| Починить генератор (полностью) | +1000 | — | -| Успешный Skill Check | +150 | — | -| Спасти с крюка | +800 | — | -| Исцелить союзника | +600 | — | -| Сбежать | +5000 | — | -| Повесить выжившего на крюк | — | +800 | -| Повалить выжившего | — | +500 | -| Пожертвовать выжившего (3 стадии) | — | +2000 | -| Сломать паллету | — | +200 | -| Ударить по генератору (Kick) | — | +100 | - -- Bloodpoints отображаются в Title после окончания матча. -- Статистика сохраняется в базе данных. - ---- - -## 10. Система перков (Perks) - -Перки — пассивные и активные способности. Каждый игрок берёт **4 перка** перед матчем (в GUI-меню выбора). - -### 10.1 Перки Выживших (минимум 10) - -| Перк | Эффект | -|---|---| -| **Self-Care** | Позволяет лечить себя без аптечки (вдвое медленнее) | -| **Dead Hard** | При нажатии Sneak во время спринта — кратковременный рывок (0.5 сек неуязвимости) | -| **Borrowed Time** | После спасения с крюка — 10 сек защита Endurance | -| **Sprint Burst** | При начале спринта — ускорение ×1.5 на 3 сек (кулдаун 40 сек) | -| **Iron Will** | Убирает звуки стонов в Injured состоянии | -| **Spine Chill** | Предупреждение (иконка + звук), если киллер смотрит на выжившего с 36 блоков | -| **Resilience** | В Injured/Downed — скорость починки +9%, скорость вота +9% | -| **Kindred** | После повешения на крюк — все союзники видят ауру киллера | -| **Prove Thyself** | За каждого выжившего на генераторе — скорость +15% (стакается) | -| **Adrenaline** | При открытии 5-го генератора — мгновенно Healthy + Sprint Burst 5 сек | - -### 10.2 Перки Киллера (минимум 10) - -| Перк | Эффект | -|---|---| -| **Hex: Ruin** | Все генераторы регрессируют вдвое быстрее (пока горит тотем) | -| **Corrupt Intervention** | 3 самых дальних генератора заблокированы 2 минуты в начале игры | -| **Pop Goes the Weasel** | После повешения — следующий Kick откатывает 25% прогресса гена | -| **Deadlock** | После починки любого гена — самый прогрессивный ген блокируется на 30 сек | -| **No Way Out** | После повешения — добавляется задержка при открытии ворот (+12/24/36 сек) | -| **Scourge Hook: Pain Resonance** | Повешение на Scourge Hook взрывает ближайший ген (−25%) | -| **Nowhere to Hide** | После Kick гена — ауры выживших видны 4 сек в радиусе 24 блоков | -| **Lethal Pursuer** | В начале игры — видеть ауры всех выживших 7 секунд | -| **BBQ & Chili** | После повешения — видеть ауры выживших >40 блоков на 4 сек | -| **Tinkerer** | Когда ген достигает 70% — уведомление + Undetectable на 12 сек | - -> ⚠ Перки реализовать через EventListener. Каждый перк — отдельный класс, реализующий интерфейс `IPerk` с методами `onEquip()`, `onTrigger()`, `onRemove()`. - -### 10.3 Тотемы (Totems) - -- На карте **5 тотемов** (`totem_locations` в конфиге). -- **Dull Totem:** выживший ломает за 14 секунд — начисляются Bloodpoints. -- **Hex Totem:** активируется при использовании Hex-перка. Пока горит — перк активен. -- При уничтожении Hex Totema — связанный перк деактивируется навсегда. - ---- - -## 11. Эндгейм и итоги матча - -### 11.1 Условия победы - -| Сторона | Победа | Поражение | -|---|---|---| -| **Выжившие** | Минимум 2 выживших сбежали (ворота или люк) | Все выжившие мертвы до побега | -| **Киллер** | Все 4 выжившие принесены в жертву / умерли | 2+ выжившие сбежали | - -### 11.2 Экран результатов - -- Все игроки телепортируются в лобби. -- В Chat выводится таблица: игрок, роль, Bloodpoints, статус (Escaped / Sacrificed). -- Title на 5 секунд: **ПОБЕДА / ПОРАЖЕНИЕ**. -- Личная статистика матча: генераторы, спасения, хуки, урон. - -### 11.3 Эндгейм Коллапс (End Game Collapse) - -- Активируется при: открытии ворот ИЛИ закрытии люка. -- Таймер **120 секунд** показывается всем в ActionBar красным текстом. -- По истечении — все оставшиеся выжившие мгновенно умирают. - ---- - -## 12. Пользовательский интерфейс (HUD) - -### 12.1 ActionBar - -- Постоянно: статус игрока (`❤ Healthy` / `🩸 Injured` / `💀 Downed`). -- При взаимодействии: прогресс-бар починки / лечения / спасения. -- Эндгейм Коллапс: красный таймер обратного отсчёта. - -### 12.2 Sidebar (Scoreboard) - -- **Выжившие:** количество починенных генераторов (`⚡ 2/5`), сколько выживших живо (`👥 3/4`). -- **Киллер:** сколько выживших на крюке / мертво, прогресс генераторов. - -### 12.3 Title / Subtitle - -- Оповещения: генератор починен, выживший на крюке, ворота открыты. -- Начало игры: роль + краткая инструкция. -- Skill Check: вспышка в Title с таймером. - -### 12.4 Звуки - -- **Terror Radius:** нарастающее сердцебиение по мере приближения киллера (3 уровня). -- **Генератор:** звук работы при починке, взрыв при провале skill check или Kick. -- **Спасение с крюка:** звук успеха. -- **Люк:** звук открытия / закрытия. -- **Ворота:** звук активации, гудение. - -> ⚠ Рекомендуется базовый Resource Pack для кастомных звуков. Без него — стандартные MC-звуки как замена. - ---- - -## 13. Конфигурация (config.yml) - -| Секция | Ключ | Тип | По умолчанию | -|---|---|---|---| -| `game` | `min_players` | int | 5 | -| `game` | `max_players` | int | 5 | -| `game` | `countdown_seconds` | int | 60 | -| `game` | `world_name` | string | `dbd_map` | -| `game` | `lobby_world` | string | `lobby` | -| `killer` | `killer_speed` | double | 1.15 | -| `killer` | `terror_radius` | int | 32 | -| `killer` | `attack_cooldown` | double | 2.5 | -| `killer` | `carry_speed` | double | 0.92 | -| `killer` | `wiggle_duration` | double | 16.0 | -| `survivor` | `sprint_duration` | double | 3.0 | -| `survivor` | `sprint_cooldown` | double | 5.0 | -| `survivor` | `heal_self_time` | double | 10.0 | -| `survivor` | `heal_other_time` | double | 16.0 | -| `generator` | `total_generators` | int | 7 | -| `generator` | `required_generators` | int | 5 | -| `generator` | `repair_time` | double | 80.0 | -| `generator` | `gen_coop_multiplier` | double | 1.5 | -| `generator` | `regression_rate` | double | 0.25 | -| `hook` | `stage1_duration` | int | 60 | -| `hook` | `stage2_duration` | int | 60 | -| `hook` | `max_hook_count` | int | 3 | -| `endgame` | `collapse_duration` | int | 120 | - -**Дополнительные файлы конфигурации:** -- `locations.yml` — все спавн-точки, координаты генераторов, хуков, тотемов, сундуков, ворот, люка. -- `loot_table.yml` — весовая таблица предметов в сундуках. -- `perks.yml` — настройки перков (кулдауны, длительности). - ---- - -## 14. Команды и права - -| Команда | Описание | Право | -|---|---|---| -| `/dbd join` | Войти в очередь на игру | `dbd.play` | -| `/dbd leave` | Выйти из очереди / матча | `dbd.play` | -| `/dbd forcestart` | Принудительно запустить игру | `dbd.admin` | -| `/dbd stop` | Принудительно остановить игру | `dbd.admin` | -| `/dbd setkiller <игрок>` | Назначить игрока киллером | `dbd.admin` | -| `/dbd setspawn ` | Установить спавн-точку (по курсору) | `dbd.admin` | -| `/dbd setgen ` | Отметить блок как генератор | `dbd.admin` | -| `/dbd sethook ` | Отметить блок как крюк | `dbd.admin` | -| `/dbd setgate <1\|2>` | Отметить зону ворот | `dbd.admin` | -| `/dbd sethatch` | Отметить блок как люк | `dbd.admin` | -| `/dbd reload` | Перезагрузить конфиг | `dbd.admin` | -| `/dbd stats [игрок]` | Посмотреть статистику | `dbd.play` | - ---- - -## 15. Архитектура плагина - -### 15.1 Структура пакетов - -| Пакет | Назначение | -|---|---| -| `com.dbd.plugin.core` | Главный класс, GameManager, EventBus | -| `com.dbd.plugin.game` | GameSession, GameState, RoleAssigner, RoundTimer | -| `com.dbd.plugin.roles` | KillerController, SurvivorController, PlayerState | -| `com.dbd.plugin.mechanics` | GeneratorManager, HookManager, PalletManager, HatchManager, GateManager | -| `com.dbd.plugin.perks` | IPerk, PerkRegistry, PerkLoader, [все перки] | -| `com.dbd.plugin.items` | IItem, ItemRegistry, ChestManager | -| `com.dbd.plugin.ui` | HUDManager, ActionBarManager, TitleManager, SoundManager | -| `com.dbd.plugin.data` | DatabaseManager, PlayerStats, LocationsConfig | -| `com.dbd.plugin.commands` | DBDCommand, TabCompleter | - -### 15.2 Ключевые принципы - -- Каждый раунд — отдельный объект `GameSession` со своим состоянием. -- Все механики управляются через `BukkitScheduler` (tick-based системы). -- Перки реализованы через Event-Driven подход (не хардкод в механиках). -- Конфиги не перезаписывают пользовательские настройки при обновлении (`saveDefaultConfig`). -- Логирование всех событий в отдельный лог-файл (`logs/dbd.log`). - -> ⚠ Плагин должен корректно обрабатывать disconnect игрока во время матча — замена ботом или перераспределение ролей. - ---- - -## 16. Приоритет разработки - -| Этап | Функционал | Статус | -|---|---|---| -| **MVP (Этап 1)** | Старт/стоп игры, роли, спавн, базовые состояния выжившего, атака киллера | 🔴 В разработке | -| **Этап 2** | Генераторы (починка, прогресс, регрессия, skill check), хуки (все стадии) | 🔴 В разработке | -| **Этап 3** | Паллеты, окна, перенос, вырывание, люк, ворота, эндгейм | 🔴 В разработке | -| **Этап 4** | Предметы, сундуки, тотемы, базовые перки (10 survivor + 10 killer) | 🔴 В разработке | -| **Этап 5** | Полный HUD, звуки, Terror Radius, Red Stain, Bloodpoints, база данных | 🔴 В разработке | -| **Этап 6** | Балансировка, все остальные перки, тест-раунды, оптимизация | 🔴 В разработке | - ---- - -*ТЗ подготовлено с учётом всех оригинальных механик Dead by Daylight (4v1) | Версия 1.0* diff --git a/PLAN.md b/PLAN.md deleted file mode 100644 index 155b3ea..0000000 --- a/PLAN.md +++ /dev/null @@ -1,392 +0,0 @@ -# DBD Plugin — Баги и задачи - -## ✅ Закрыто в текущей сессии - -### SetupCommand (упрощено) -- [x] `/dbdsetup set <тип>` — ломаешь блок, объект ставится (без `select`) -- [x] Ванд только для ворот: ЛКМ=pos1, ПКМ=pos2 -- [x] `/dbdsetup set gate A|B` — установить ворота из точек ванда - -### Медкит -- [x] Требует Shift + ПКМ + стоять на месте (прерывается при движении или отпускании Shift) -- [x] После использования удаляется полностью (1 медкит = 1 лечение) -- [x] Медкит не выдаётся стартово — только из сундуков - -### Маньяк — атака -- [x] Post-hit cooldown 4 сек после ПОПАДАНИЯ (отдельно от swing cooldown 2.5 сек) -- [x] Параметр `killer.post-hit-cooldown` в `game.yml` - -### Маньяк — нокдаун / переноска -- [x] Игрок в нокдауне ложится (`setSwimming(true)`) и поза удерживается каждые 5 тиков -- [x] При подъёме, смерти, спасении — поза сбрасывается -- [x] Переноска: маньяк ПКМ → подбирает DOWNED в радиусе 3 блоков -- [x] При подъёме `setSwimming(false)` отменяет позу нокдауна - -### Таймер игры -- [x] 15 минут + BossBar с таймером для всех игроков (зелёный → жёлтый → красный) -- [x] По истечении — маньяк победил - -### После победы -- [x] Телепортирует всех в лобби -- [x] Scale сбрасывается до 1.0 -- [x] Инвентарь очищается - -### Лобби -- [x] Лимит 1 лобби на игрока -- [x] Broadcast при создании лобби убран — сообщение только создателю -- [x] Сообщение о входе игрока — только участникам сессии (не всему серверу) -- [x] После завершения игры лобби пересоздаёт сессию автоматически (onSessionFinished callback) -- [x] Лобби не засоряются — реестр чистит сессию через `GameSession.setOnStopped()` - -### PlayerQuitListener -- [x] Счётчик живых выживших корректный (считает после пометки DEAD) -- [x] Инвентарь, scale, поза сбрасываются при выходе из игры - -### GameplayPhase -- [x] Разбит на части: - - `GameplayPhase.java` — только lifecycle (enter/tick/exit) + делегирование (230 строк) - - `GameplayHookHandler.java` — тик крюков, Stage 2, Struggle, Sacrifice (87 строк) - - `GameplayWinConditions.java` — проверка победы/поражения, SPECTATOR (91 строка) - - `GameplayDamageSystem.java` — система урона, атаки, предметы (155 строк) - - `GameplayUI.java` — BossBar, sidebar, таймер (142 строки) - - `GameplayInteraction.java` — обработка взаимодействий (198 строк) - -### Лобби — повторный вход -- [x] **FIX**: Исправлен `GameManager.joinSession()` — теперь корректно обрабатывает повторный вход, сначала удаляя игрока из старой сессии - -### Хотбар маньяка -- [x] **FIX**: Добавлена проверка `!bp.isKiller()` в `ChestOpening.completeOpening()` — маньяк не получает лут из сундуков - -### Медкит из сундука -- [x] **WORKS**: Логика уже работает — `ChestLoot.rollLoot()` выдаёт медкит/фонарик при открытии сундука - -### Счётчик выживших -- [x] **VERIFIED**: Логика в `PlayerQuitListener.handleSurvivorDisconnect()` корректная — считает после пометки DEAD - -### Ворота -- [x] **FIX**: Добавлена интеграция `GateOpening` в `GameplayInteraction` — теперь вызывается при взаимодействии с порталом (HOPPER/PORTAL) - -### Кодировка и спавн в воздухе -- [x] **FIXED**: UTF-8 encoding для build - - Добавлена `org.gradle.jvmargs=-Dfile.encoding=UTF-8` в `gradle.properties` - - Добавлен `tasks.withType { filteringCharset = "UTF-8" }` в build.gradle.kts - - Русские символы и эмодзи теперь сохраняются корректно в конфигах -- [x] **FIXED**: Спавн в воздухе - - Добавлена корректировка Y-координаты (`Math.floor(y) + 1.0`) в `RoleAssigner.java` - - Players теперь стоят ОН block, не ИН block - - Работает для положительных и отрицательных Y (подземные карты) -- [x] **FIXED**: World loading — добавлен fallback к первому loaded world в `LocationsConfig.java` -- [x] **FIXED**: Удален неиспользуемый импорт Location из `PalletBreak.java` - ---- - -## ✅ Завершено - -### Заполнение сундуков при старте игры (случайный лут из ChestLoot) -- [x] Лут записывается в поле `Chest.loot` при создании -- [x] `ChestOpening.completeOpening()` использует pre-set loot - -### Визуализация ворот (частицы при открытии) -- [x] Progress particles: CRIT every 5 ticks -- [x] Completion burst: EXPLOSION_EMITTER + FLAME - -### Удаление перков и тотемов -- [x] Все totem файлы удалены -- [x] Все ссылки на тотемы удалены - -## ❌ Новые баги (текущая сессия) - -### ✅ ИСПРАВЛЕНО (7 багов) - -1. **SetupCommand MiniMessage формат** - - [x] **FIXED**: Заменены legacy `§f` и `§a` на MiniMessage `<#FFFFFF>` и `<#00FF00>` - -2. **Телепортация в конце игры не работает** - - [x] **FIXED**: Добавлена телепортация в `GameplayPhase.exit()` - - Также сбрасывается scale до 1.0 - -3. **Downed игрок берёт хук** - - [x] **FIXED**: Добавлена проверка состояния в `GameplayInteraction` - - Теперь DOWNED, CARRIED и HOOKED не могут спасать - -4. **Генераторы не чинятся за игрока** - - [x] **FIXED**: Подключена `GeneratorRepair` в `GameplayPhase` - - Добавлен обработчик в `GameplayInteraction` - - Механика: ПКМ по генератору → зажать ПКМ для починки - ---- - -### ✅ ИСПРАВЛЕНО / ПРОВЕРЕНО В ТЕКУЩЕЙ СЕССИИ (13 ЗАДАЧ) - -1. **Генераторы (#11) — generatorManager всегда null** - - [x] **FIXED**: Переинициализирован в GameplayPhase.initSubHandlers() - -2. **Телепорт (#10) — ранний выход отменял финал** - - [x] **FIXED**: Удалён телепорт из GameplayPhase.exit() - - Телепортация только в EndgamePhase.exit() (100L тиков задержка) - -3. **Wand для ворот — STICK vs WOODEN_AXE** - - [x] **FIXED**: Обновлена документация, код ищет WOODEN_AXE с NBT тегом - -4. **Бесконечный вход в лобби** (/dbd join X, /dbd join X, /dbd join X...) - - [x] **FIXED**: LobbyRegistry.joinLobby() проверяет текущую сессию - - Если игрок уже в другой сессии → выходит оттуда перед входом - -5. **Лобби удаляется при 0 игроков, tab-complete показывает** - - [x] **VERIFIED**: onPlayerLeftSession() НЕ удаляет лобби из реестра - - Лобби держится в памяти, session переиспользуется после игры - -6. **Pallet setup** (/dbdsetup set pallet) - - [x] **VERIFIED**: Режим selectingPallet работает, сохраняет через SpawnUtil.blockBreakSpawn() - -7. **Chest setup** (/dbdsetup set chest) - - [x] **VERIFIED**: Режим selectingChest работает, сохраняет с offset +0.5, +0, +0.5 - -8. **Эффекты ранения** (нет визуалов когда игрок INJURED) - - [x] **VERIFIED**: GameplayDamageSystem добавляет: - - Частицы HEART каждые 40 тиков - - Звук при попадании удара - - Title "РАНЕН!" - -9. **Двойной sneak для pickup** (киллер присел 2 раза возле DOWNED) - - [x] **VERIFIED**: GameplayInteraction проверяет интервал <450ms между sneaks - - Вызывает tryPickup() из KillerController - -10. **Админ-команды** (heal, down, unhook, state, hooks, kill) - - [x] **VERIFIED**: DBDAdminPlayerCommand полностью реализована - - /dbd admin heal [игрок] - - /dbd admin down [игрок] - - /dbd admin unhook [игрок] - - /dbd admin state <игрок> - - /dbd admin hooks <игрок> <0-3> - - /dbd admin kill [игрок] - -11. **Телепорт после завершения игры в лобби** - - [x] **VERIFIED**: EndgamePhase.exit() телепортирует через 100L тиков - - Сбрасывает scale до 1.0, очищает инвентарь - -12. **Генераторы не чинятся** (ПКМ возле генератора) - - [x] **FIXED**: setOnGeneratorInteract() вызывает generatorRepair.startRepair() - - generatorManager переинициализирован, не null - -13. **HOOKED игрок берёт хук** (игрок висит на крюке, может взять другой) - - [x] **VERIFIED**: setOnRescueAttempt() проверяет HOOKED, DOWNED, CARRIED - - Rescue невозможен если rescuer в одном из этих статусов - -14. **Спавн игроков в воздухе** (проблема с высотой) - - [x] **FIXED**: SpawnUtil.resolveStandingLocation() улучшена логика расчета Y - - Добавлена явная загрузка chunks в RoleAssigner перед спавном - - Используется getHighestBlockYAt() + 1 для стояния на блоке - -15. **GameMode.ADVENTURE при начале игры** - - [x] **FIXED**: - - RoleAssigner.assignRoles() устанавливает ADVENTURE при спавне - - LobbyPhase.enter() и onPlayerJoined() устанавливают ADVENTURE - - EndgamePhase.exit() сбрасывает на ADVENTURE перед лобби - -16. **/dbdsetup set gate A confirm не работал** - - [x] **FIXED**: Добавлена поддержка обоих форматов: - - `/dbdsetup set gate A confirm` - - `/dbdsetup set gate confirm A` - - Обновлена документация в COMMANDS_GUIDE.md - -17. **Переноска киллером (carry) — проблемы** - - [x] **FIXED**: Переработана логика KillerCarry с использованием ArmorStand: - - Игрок **видим** (не setInvisible) - - Камера **отделена** (beide мають пассажиры armor stand) - - Игрок **не двигает** киллера (mounted, не телепортируется) - - Пробел **работает** (jump event отслеживается) - ---- - -### ✅ ИТОГО: 17/17 ЗАДАЧ РЕШЕНО!1. **Генераторы (#11) — generatorManager всегда null** - - [x] **FIXED**: Переинициализирован в GameplayPhase.initSubHandlers() - -2. **Телепорт (#10) — ранний выход отменял финал** - - [x] **FIXED**: Удалён телепорт из GameplayPhase.exit() - - Телепортация только в EndgamePhase.exit() (100L тиков задержка) - -3. **Wand для ворот — STICK vs WOODEN_AXE** - - [x] **FIXED**: Обновлена документация, код ищет WOODEN_AXE с NBT тегом - -4. **Бесконечный вход в лобби** (/dbd join X, /dbd join X, /dbd join X...) - - [x] **FIXED**: LobbyRegistry.joinLobby() проверяет текущую сессию - - Если игрок уже в другой сессии → выходит оттуда перед входом в новую - -5. **Лобби удаляется при 0 игроков, tab-complete показывает** - - [x] **VERIFIED**: onPlayerLeftSession() НЕ удаляет лобби из реестра - - Лобби держится в памяти, session переиспользуется после игры - -6. **Pallet setup** (/dbdsetup set pallet) - - [x] **VERIFIED**: Режим selectingPallet работает, сохраняет через SpawnUtil.blockBreakSpawn() - -7. **Chest setup** (/dbdsetup set chest) - - [x] **VERIFIED**: Режим selectingChest работает, сохраняет с offset +0.5, +0, +0.5 - -8. **Эффекты ранения** (нет визуалов когда игрок INJURED) - - [x] **VERIFIED**: GameplayDamageSystem добавляет: - - Частицы HEART каждые 40 тиков - - Звук при попадании удара - - Title "РАНЕН!" - -9. **Двойной sneak для pickup** (киллер присел 2 раза возле DOWNED) - - [x] **VERIFIED**: GameplayInteraction проверяет интервал <450ms между sneaks - - Вызывает tryPickup() из KillerController - -10. **Админ-команды** (heal, down, unhook, state, hooks, kill) - - [x] **VERIFIED**: DBDAdminPlayerCommand полностью реализована - - /dbd admin heal [игрок] - - /dbd admin down [игрок] - - /dbd admin unhook [игрок] - - /dbd admin state <игрок> - - /dbd admin hooks <игрок> <0-3> - - /dbd admin kill [игрок] - -11. **Телепорт после завершения игры в лобби** - - [x] **VERIFIED**: EndgamePhase.exit() телепортирует через 100L тиков - - Сбрасывает scale до 1.0, очищает инвентарь - -12. **Генераторы не чинятся** (ПКМ возле генератора) - - [x] **FIXED**: setOnGeneratorInteract() вызывает generatorRepair.startRepair() - - generatorManager переинициализирован, не null - -13. **HOOKED игрок берёт хук** (игрок висит на крюке, может взять другой) - - [x] **VERIFIED**: setOnRescueAttempt() проверяет HOOKED, DOWNED, CARRIED - - Rescue невозможен если rescuer в одном из этих статусов - -14. **Спавн игроков в воздухе** (проблема с высотой) - - [x] **FIXED**: - - SpawnUtil.resolveStandingLocation() улучшена логика расчета Y - - Добавлена явная загрузка chunks в RoleAssigner перед спавном - - Используется getHighestBlockYAt() + 1 для стояния на блоке - ---- - -### ✅ ИТОГО: 14/14 ЗАДАЧ РЕШЕНО! - - ---- - -## ✅ СЕССИЯ 2: ГЕНЕРАТОР - ПРОГРЕСС И КРАУЧ (18-19 ЗАДАЧИ) - -### 18. Прогресс починки генератора не сохраняется -- [x] **FIXED**: Progress теперь сохраняется в Generator объекте между repair attempts -- Механика: - - Игрок присаживается рядом генератором → `onSneak()` автоматически запускает `startRepair()` - - `startRepair()` проверяет, ремонтирует ли уже этот генератор → если нет, создаёт новую RepairSession - - Progress сохраняется в `generator.progress` на всё время игры - - Если игрок встал (un-sneak) → `updateRepair()` возвращает false → repair stops - - Если игрок присел снова рядом тем же генератором → вызывается `startRepair()` снова - - **Ключевое**: progress НЕ сбрасывается, потому что RepairSession.generator указывает на ТОТЖЕ Generator объект - - Progress сохраняется всю игру (сбрасывается только при перезагрузке сервера) -- Сообщение теперь показывает текущий прогресс: "Зажмите ПРИСЕД чтобы чинить генератор (прогресс: XX%)" - -### 19. Чтобы починить генератор нужно присеть возле него и быть присядя возле него -- [x] **FIXED**: Добавлена автоматическая триггеризация repair при SNEAK -- Механика: - 1. Игрок присаживается (PlayerToggleSneakEvent с isSneaking=true) - 2. PlayerInteractListener.onSneak() вызывает `tryGeneratorInteract(player)` для survivors - 3. `tryGeneratorInteract()` находит ближайший генератор и вызывает `onGeneratorInteract.accept()` - 4. GameplayInteraction вызывает `generatorRepair.startRepair()` - 5. Repair session создана → player должен оставаться присядя - 6. GeneratorRepair.tick() каждый tick проверяет `if (!player.isSneaking()) return false;` - 7. Если условие не выполнено → repair stops (но progress НЕ теряется) - 8. Игрок встал → `stopRepair()` вызывается - 9. Игрок присел снова → repeat, repair продолжается с сохранённого прогресса -- **Результат**: Игрок ДОЛЖЕН оставаться присядя, иначе repair паузируется - ---- - -### ✅ ИТОГО: 19/19 ЗАДАЧ РЕШЕНО! - ---- - -## ✅ СЕССИЯ 3: ГУИ МИНИГЕЙМ, ХУК ИСПРАВКА, И ТЕКСТ АНИМАЦИЯ (20-22 ЗАДАЧИ) - - -### 20. Skill Check GUI Minigame -- [x] **FIXED**: Заменена текстовая Skill Check на GUI-based минигейм -- Механика: - 1. Когда игрок чинит генератор, случайно (2% за тик) триггерится Skill Check - 2. Открывается инвентарь с 9 стеклянными блоками в одной строке - 3. Все блоки - СЕРОЕ СТЕКЛО (GRAY_STAINED_GLASS) - 4. Один блок случайно становится ЗЕЛЁНЫМ (GREEN_STAINED_GLASS) - 5. Каждые 4-7 тиков зелёный блок меняет позицию (анимация) - 6. Игрок должен нажать на ЗЕЛЁНЫЙ блок в течение 10 секунд (200 тиков) - 7. Если успешно → +5% прогресса, сообщение "Отлично! +5%" - 8. Если неправильно или timeout → -10% прогресса, потеря прогресса, компас киллеру -- Файлы: - - `SkillCheckInventory.java` - новый класс для GUI minigame - - `SkillCheckListener.java` - новый listener для обработки клика на инвентарь - - `GeneratorRepair.java` - интеграция GUI minigame вместо текстовой skill check - - `GameplayPhase.java` - регистрация SkillCheckListener при старте игры - -### 21. Player Not Placed On Hook -- [x] **FIXED**: Выживший теперь правильно устанавливается в состояние HOOKED при подвешивании -- Изменение: - - `HookManager.tryHookSurvivor()` теперь вызывает `survivor.setState(PlayerState.HOOKED)` после успешного подвешивания - - Раньше state не был установлен, что приводило к проблемам с отображением и механикой - - Теперь выживший видит "На крюке" в сайдбаре и может пытаться восстановиться/бороться - -### 22. Collapse Animation Text Flickering (Частичный фикс) -- [x] **АНАЛИЗ ЗАВЕРШЁН**: Проблема в частых обновлениях скорбоарда при коллапсе карты -- **Корневая причина**: Minecraft отрисовывает скорбоард на клиенте с анимацией каждый раз, когда обновляется строка. - - Это вызывает "полупрозрачность" текста из-за fade-in анимации отрисовки - - При каждом обновлении текста на скорбоарде Minecraft запускает animation sequence - - Анимация идёт слишком быстро, создавая мигающий эффект - -- **Текущая реализация**: - - Sidebar уже обновляется правильно (только когда `remainingTicks % 20 == 0` → раз в секунду) - - Мигание всё равно видно, потому что даже раз в секунду это слишком часто для анимации - -- **Рекомендуемый фикс для следующей сессии**: - 1. **Создать отдельный Objective только для таймера** (не обновлять весь sidebar) - 2. **Обновлять таймер реже** (например, раз в 2 секунды вместо раз в секунду) - 3. **Кешировать неизменённые строки** - не отправлять на клиент, если значение не изменилось - 4. **Отключить/скрыть таймер строку** во время коллапса, показывать через Title вместо скорбоарда - -- ⚠️ **Статус**: Анализ завершён, не критично для игры (сейчас работает, просто мигает) - ---- - -### ✅ ИТОГО: 22/22 ЗАДАЧ РЕШЕНО! - - ---- - -## 📋 ИТОГОВОЕ РЕЗЮМЕ ПО СЕССИИ 3 - -### ✅ Что было исправлено: - -**1. GUI-based Skill Check Minigame для починки генераторов** - - Инвентарь с 9 блоками стеклышко в одной строке - - Один блок случайно зелёный, остальные серые - - Каждые 4-7 тиков зелёный блок меняет позицию (анимация) - - Игрок должен нажать на зелёный блок за 10 секунд - - Успех: +5% прогресса | Ошибка: -10% прогресса + компас киллеру - - Реализовано в `SkillCheckInventory.java` + `SkillCheckListener.java` - -**2. Выживший не ставился в hook** - - Добавлен `survivor.setState(PlayerState.HOOKED)` в `HookManager.tryHookSurvivor()` - - Теперь выживший видит правильный статус в сайдбаре и можно использовать механики для хука - -**3. Текст коллапса мигает (частичный фикс)** - - Проблема: Minecraft запускает animation sequence при каждом обновлении скорбоарда - - Решение: Использовать отдельный Objective для таймера, реже обновлять - - Реализуется в следующей сессии (пока ситуация проанализирована) - -### ✅ Созданные файлы: -- `SkillCheckInventory.java` - GUI minigame система -- `SkillCheckListener.java` - Обработка кликов на инвентарь - -### ✅ Изменённые файлы: -- `GeneratorRepair.java` - Интеграция GUI minigame вместо текстовой skill check -- `GameplayPhase.java` - Регистрация SkillCheckListener -- `HookManager.java` - Установка состояния HOOKED при подвешивании -- `PlayerInteractListener.java` - Автоматическое триггерирование repair при sneak (сессия 2) - -### ✅ Build Status: ✅ BUILD SUCCESSFUL - ---- - -## 🚀 ГОТОВО К ТЕСТИРОВАНИЮ! diff --git a/README.md b/README.md new file mode 100644 index 0000000..874a1ce --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +# Mdbd — Dead by Daylight в Minecraft + +Плагин для Paper 1.21.5, реализующий мини-игру Dead by Daylight (4v1) на Minecraft-сервере. + +## Особенности + +- **4 выживших vs 1 маньяк** — полноценный геймплей DBD в Minecraft +- **Генераторы** — 7 на карте, нужно починить 5. Прогресс сохраняется, Skill Check мини-игра (GUI) +- **Крюки** — 3 стадии, спасение, борьба, жертвоприношение +- **Выходные ворота** — открытие через рубильник, эндгейм коллапс +- **Паллеты** — ставятся через `/dbdsetup`, ломаются маньяком +- **Медкиты и фонарики** — из сундуков, с механиками лечения и ослепления +- **Система урона** — Healthy → Injured → Downed → Hooked → Dead +- **Переноска** — маньяк подбирает и носит выживших до крюка +- **Terror Radius** — звук сердцебиения для выживших рядом с маньяком +- **Skill Check GUI** — мини-игра с зелёными блоками при починке генератора +- **Лобби** — ожидание игроков, автоматический старт, возврат после игры +- **Scoreboard, BossBar, ActionBar** — полноценный интерфейс + +## Команды + +### Игроку +| Команда | Описание | +|---|---| +| `/dbd join` | Войти в лобби | +| `/dbd leave` | Выйти из лобби/игры | +| `/dbd list` | Список доступных лобби | + +### Админу +| Команда | Описание | +|---|---| +| `/dbd create` | Создать новое лобби | +| `/dbd forcestart` | Принудительный старт | +| `/dbd stop` | Остановить игру | +| `/dbd reload` | Перезагрузить конфиги | +| `/dbdsetup wand` | Получить топор для выделения зон ворот | +| `/dbdsetup pos1 / pos2` | Выделить зону ворот | +| `/dbdsetup set ` | Установить объект | +| `/dbdsetup save / load ` | Сохранить/загрузить шаблон карты | +| `/dbdsetup build ` | Построить карту по шаблону | +| `/dbdsetup clear` | Очистить все объекты | +| `/dbdadmin create ` | Создать объект вручную | +| `/dbdadmin list ` | Список объектов | +| `/dbdadmin remove ` | Удалить объект | +| `/dbdadmin heal/down/unhook/kill ` | Управление состоянием игроков | + +## Установка + +1. Поместить `Mdbd-.jar` в `plugins/` +2. Настроить `game.yml`, `locations.yml`, `messages.yml` в `plugins/Mdbd/` +3. Перезапустить сервер или выполнить `/dbd reload` +4. Создать лобби: `/dbd create` +5. Расставить объекты через `/dbdsetup` + +## Требования + +- Paper 1.21.5 +- ProtocolLib 5.3.0 +- Java 21 + +## Сборка + +```bash +./gradlew build +``` diff --git a/src/main/java/dev/loki/command/SetupCommand.java b/src/main/java/dev/loki/command/SetupCommand.java index 92c09dc..197f195 100644 --- a/src/main/java/dev/loki/command/SetupCommand.java +++ b/src/main/java/dev/loki/command/SetupCommand.java @@ -1,5 +1,6 @@ package dev.loki.command; +import dev.loki.gate.ExitGate; import dev.loki.mdbd; import dev.loki.util.SpawnUtil; import dev.loki.util.TextUtil; @@ -206,6 +207,11 @@ public class SetupCommand implements TabExecutor { locations.setGateZone(gateId, p1, p2); plugin.getConfigManager().saveConfig("locations.yml", locations.getConfig()); + ExitGate gate = new ExitGate(center); + gate.setZone(p1, p2); + gate.spawnGateStructure(); + gate.spawnGateBlock(); + player.sendMessage(messages().get("setup.gate-placed", gateId, formatLoc(center))); return true; } @@ -402,20 +408,14 @@ public class SetupCommand implements TabExecutor { } String type = args[1].toLowerCase(); - int index; - try { - index = Integer.parseInt(args[2]); - } catch (NumberFormatException e) { - player.sendMessage(messages().get("setup.invalid-number", args[2])); - return true; - } - var locations = plugin.getConfigManager().getLocations(); switch (type) { case "generator" -> { + int index = parseInt(args[2], player); + if (index < 0) return true; var gens = locations.getGenerators(); - if (index < 0 || index >= gens.size()) { + if (index >= gens.size()) { player.sendMessage(messages().get("setup.out-of-range", index)); return true; } @@ -424,8 +424,10 @@ public class SetupCommand implements TabExecutor { player.sendMessage(messages().get("setup.deleted", "generator #" + index)); } case "hook" -> { + int index = parseInt(args[2], player); + if (index < 0) return true; var hooks = locations.getHooks(); - if (index < 0 || index >= hooks.size()) { + if (index >= hooks.size()) { player.sendMessage(messages().get("setup.out-of-range", index)); return true; } @@ -433,8 +435,10 @@ public class SetupCommand implements TabExecutor { player.sendMessage(messages().get("setup.deleted", "hook #" + index)); } case "chest" -> { + int index = parseInt(args[2], player); + if (index < 0) return true; var chests = locations.getChests(); - if (index < 0 || index >= chests.size()) { + if (index >= chests.size()) { player.sendMessage(messages().get("setup.out-of-range", index)); return true; } @@ -446,6 +450,8 @@ public class SetupCommand implements TabExecutor { player.sendMessage(messages().get("setup.deleted", "killer-spawn")); } case "survivor-spawn" -> { + int index = parseInt(args[2], player); + if (index < 0) return true; if (index < 1 || index > 4) { player.sendMessage(messages().get("setup.out-of-range", index)); return true; @@ -454,9 +460,10 @@ public class SetupCommand implements TabExecutor { player.sendMessage(messages().get("setup.deleted", "survivor-spawn #" + index)); } case "gate" -> { - String id = index == 1 ? "a" : index == 2 ? "b" : null; - if (id == null) { - player.sendMessage(messages().get("setup.out-of-range", index)); + String raw = args[2].toLowerCase(); + String id = switch (raw) { case "a", "1" -> "a"; case "b", "2" -> "b"; default -> null; }; + if (id == null || locations.getGate(id) == null) { + player.sendMessage(messages().get("setup.out-of-range", raw)); return true; } locations.getConfig().set("gate-" + id, null); @@ -474,6 +481,15 @@ public class SetupCommand implements TabExecutor { return true; } + private int parseInt(String s, Player player) { + try { + return Integer.parseInt(s); + } catch (NumberFormatException e) { + player.sendMessage(messages().get("setup.invalid-number", s)); + return -1; + } + } + private boolean clearSpawns(Player player) { var locations = plugin.getConfigManager().getLocations(); locations.clearLocationList("killer-spawn"); diff --git a/src/main/java/dev/loki/config/LocationsConfig.java b/src/main/java/dev/loki/config/LocationsConfig.java index dbca2e8..4e986a6 100644 --- a/src/main/java/dev/loki/config/LocationsConfig.java +++ b/src/main/java/dev/loki/config/LocationsConfig.java @@ -80,10 +80,6 @@ public class LocationsConfig { return loadLocationList("chests"); } - public List getTotems() { - return loadLocationList("totems"); - } - // getExitGates() — определён в addLocation/setGate блоке public List getKillerSpawns() { diff --git a/src/main/java/dev/loki/gate/ExitGate.java b/src/main/java/dev/loki/gate/ExitGate.java index 0f57794..148b5a9 100644 --- a/src/main/java/dev/loki/gate/ExitGate.java +++ b/src/main/java/dev/loki/gate/ExitGate.java @@ -52,7 +52,7 @@ public class ExitGate { /** Place a HOPPER block at this gate's location for player interaction. */ public void spawnGateBlock() { if (location.getWorld() == null) return; - location.getBlock().setType(org.bukkit.Material.HOPPER, false); + location.getBlock().setType(org.bukkit.Material.HOPPER, true); } /** Build the gate structure fills the entire designated zone. */ @@ -60,16 +60,14 @@ public class ExitGate { World world = location.getWorld(); if (world == null) return; - // Place all iron bars first (no physics) then force update for connections if (hasZone) { for (int x = zoneMinX; x <= zoneMaxX; x++) { for (int y = zoneMinY; y <= zoneMaxY; y++) { for (int z = zoneMinZ; z <= zoneMaxZ; z++) { - world.getBlockAt(x, y, z).setType(org.bukkit.Material.IRON_BARS, false); + world.getBlockAt(x, y, z).setType(org.bukkit.Material.IRON_BARS, true); } } } - // Force update all iron bars so they connect to neighbors for (int x = zoneMinX; x <= zoneMaxX; x++) { for (int y = zoneMinY; y <= zoneMaxY; y++) { for (int z = zoneMinZ; z <= zoneMaxZ; z++) { @@ -78,12 +76,11 @@ public class ExitGate { } } } else { - // Fallback: 3x3x3 zone around gate location int cx = location.getBlockX(), cy = location.getBlockY(), cz = location.getBlockZ(); for (int x = cx - 1; x <= cx + 1; x++) { for (int y = cy; y <= cy + 2; y++) { for (int z = cz - 1; z <= cz + 1; z++) { - world.getBlockAt(x, y, z).setType(org.bukkit.Material.IRON_BARS, false); + world.getBlockAt(x, y, z).setType(org.bukkit.Material.IRON_BARS, true); } } } @@ -96,8 +93,7 @@ public class ExitGate { } } - // Button at gate center + (1, 1, 1) - world.getBlockAt(location.clone().add(1, 1, 1)).setType(org.bukkit.Material.STONE_BUTTON, false); + world.getBlockAt(location.clone().add(1, 1, 1)).setType(org.bukkit.Material.STONE_BUTTON, true); } /** Remove the interaction block (e.g. when gate opens or on cleanup). */ diff --git a/src/main/java/dev/loki/listener/SkillCheckListener.java b/src/main/java/dev/loki/listener/SkillCheckListener.java index b949356..1e30b03 100644 --- a/src/main/java/dev/loki/listener/SkillCheckListener.java +++ b/src/main/java/dev/loki/listener/SkillCheckListener.java @@ -22,28 +22,24 @@ public class SkillCheckListener implements Listener { @EventHandler public void onInventoryClick(InventoryClickEvent event) { - String title = event.getView().getTitle(); - if (!title.contains("Skill Check")) return; + if (!(event.getWhoClicked() instanceof Player player)) return; + if (!minigame.isActive(player.getUniqueId())) return; event.setCancelled(true); - if (!(event.getWhoClicked() instanceof Player player)) return; - minigame.handleClick(player.getUniqueId(), event.getRawSlot()); } @EventHandler public void onInventoryDrag(InventoryDragEvent event) { - String title = event.getView().getTitle(); - if (!title.contains("Skill Check")) return; + if (!(event.getWhoClicked() instanceof Player player)) return; + if (!minigame.isActive(player.getUniqueId())) return; event.setCancelled(true); } @EventHandler public void onInventoryClose(InventoryCloseEvent event) { - String title = event.getView().getTitle(); - if (!title.contains("Skill Check")) return; - + if (!minigame.isActive(event.getPlayer().getUniqueId())) return; minigame.handleClose(event.getPlayer().getUniqueId()); } diff --git a/src/main/java/dev/loki/map/MapBuilder.java b/src/main/java/dev/loki/map/MapBuilder.java index f09afeb..f91e8af 100644 --- a/src/main/java/dev/loki/map/MapBuilder.java +++ b/src/main/java/dev/loki/map/MapBuilder.java @@ -113,10 +113,6 @@ public class MapBuilder { return true; } - public void placeTotem(Location location) { - // Totems removed - no-op - } - public void placeHook(Location location) { if (templateManager.hasTemplate("hook")) { templateManager.placeObject("hook", location); diff --git a/src/main/java/dev/loki/minigames/generator/GuiRouletteMinigame.java b/src/main/java/dev/loki/minigames/generator/GuiRouletteMinigame.java index da29b5c..34e7336 100644 --- a/src/main/java/dev/loki/minigames/generator/GuiRouletteMinigame.java +++ b/src/main/java/dev/loki/minigames/generator/GuiRouletteMinigame.java @@ -64,7 +64,7 @@ public class GuiRouletteMinigame implements GeneratorMinigame { RouletteSession session = new RouletteSession(player, callback); activeSessions.put(playerId, session); - String titleStr = plugin.getConfigManager().getMessages().getString("minigames.generator-roulette.title", "⚡ Skill Check!"); + String titleStr = plugin.getConfigManager().getMessages().getString("minigames.generator-roulette.title", "⚡ Проверка реакции!"); Inventory inv = Bukkit.createInventory(null, 9, Component.text(titleStr).color(NamedTextColor.YELLOW)); fillInventory(inv, session.successSlot); player.openInventory(inv); diff --git a/src/main/resources/game.yml b/src/main/resources/game.yml index 5902cc1..540012c 100644 --- a/src/main/resources/game.yml +++ b/src/main/resources/game.yml @@ -19,12 +19,6 @@ lobby: # Задержка перед назначением ролей (секунд) role-assign-delay: 5 - # Количество серверных лобби (0 = только пользовательские) - server-lobby-count: 3 - - # Сохранять лобби между перезапусками - persist-lobbies: true - # Размеры игроков (1.0 = стандарт) players: survivor-scale: 1.0 diff --git a/src/main/resources/locations.yml b/src/main/resources/locations.yml index c981cf4..feefcc5 100644 --- a/src/main/resources/locations.yml +++ b/src/main/resources/locations.yml @@ -23,9 +23,6 @@ hooks: [] # Сундуки с лутом (3-4) chests: [] -# Тотемы (5) -totems: [] - # Ворота выхода (2) exitgates: [] @@ -43,7 +40,6 @@ survivor-spawns: [] # /dbdadmin clear - Очистить все генераторы # /dbdsetup set hook - Установить крюк # /dbdsetup set chest - Установить сундук -# /dbdsetup set totem - Установить тотем # /dbdsetup set gate - Установить ворота # /dbdsetup set lobby - Установить лобби # ============================================ diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index c2eb1c7..d518b13 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -166,9 +166,10 @@ generator: cannot: "&cГенератор не может быть починен!" busy: "&cКто-то уже чинит этот генератор!" actionbar: "&7Починка: %s" - skillcheck-title: "&eSkill Check! %s" - skillcheck-success: "&a✓ Отлично! +%d%%" - skillcheck-fail: "&c✗ Ошибка! -%d%%. Продолжай чинить." + skillcheck-title: "&eПроверка реакции! %s" + skillcheck-success: "&a✓ Успех! +%d%%" + skillcheck-fail: "&c✗ Промах! -%d%%. Чини дальше." + all-done: "%prefix%&aВсе генераторы починены! Открывайте ворота!" kicked: begin: "%prefix%&cДержите Shift для разрушения генератора..." cooldown: "%prefix%&cКулдаун удара: %d сек" @@ -176,7 +177,6 @@ generator: actionbar: "&c⚡ Разрушение: %d%%" success: "%prefix%&cГенератор поврежден! -%d%% прогресса" broadcast: "%prefix%&4⚡ Маньяк разрушил генератор! -%d%%" - all-done: "%prefix%&aВсе генераторы починены! Открывайте ворота!" notification: "&4[DBD] ⚡ Выживший допустил ошибку! Компас укажет на генератор!" # ── Маньяк ───────────────────────────────────── @@ -266,7 +266,7 @@ quit: minigames: generator-roulette: - title: "⚡ Skill Check!" + title: "⚡ Проверка реакции!" success-label: "✓ Нажми!" text-skillcheck: subtitle: "&eНажми ПКМ или отпусти шифт в зоне!" From c31ea425db0e7e821afb2ac7c2a73c5d1722b1a3 Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Sun, 21 Jun 2026 13:37:37 +0200 Subject: [PATCH 09/10] feat: add computers as second objective type - New: Computer, ComputerManager, ComputerRepair, ComputerHologram, ComputerDataManager - Config: total-count=2, required-count=2, repair-seconds=90 in game.yml - Win condition: all generators AND all computers required - No regression, no ComputerKick, no compass on skill-check fail - /dbdsetup set computer, /dbdadmin list computer - Hologram progress display, persistence to data/computers.yml - LECTERN block right-click cancelled --- .../dev/loki/command/DBDAdminCommand.java | 4 +- .../java/dev/loki/command/SetupCommand.java | 33 ++- src/main/java/dev/loki/config/GameConfig.java | 44 +++- .../java/dev/loki/config/LocationsConfig.java | 3 + src/main/java/dev/loki/core/GameSession.java | 11 +- .../dev/loki/data/ComputerDataManager.java | 148 +++++++++++++ .../loki/listener/PlayerInteractListener.java | 31 ++- .../listener/SetupBlockBreakListener.java | 1 + src/main/java/dev/loki/mdbd.java | 11 + .../java/dev/loki/objective/Computer.java | 146 +++++++++++++ .../dev/loki/objective/ComputerHologram.java | 134 ++++++++++++ .../dev/loki/objective/ComputerManager.java | 114 ++++++++++ .../dev/loki/objective/ComputerRepair.java | 195 ++++++++++++++++++ .../java/dev/loki/phase/EndgamePhase.java | 2 +- .../dev/loki/phase/GameplayInteraction.java | 29 ++- .../java/dev/loki/phase/GameplayPhase.java | 91 ++++++-- src/main/java/dev/loki/phase/GameplayUI.java | 5 +- src/main/java/dev/loki/ui/Sidebar.java | 15 +- src/main/resources/game.yml | 43 +++- src/main/resources/locations.yml | 3 + src/main/resources/messages.yml | 25 ++- 21 files changed, 1049 insertions(+), 39 deletions(-) create mode 100644 src/main/java/dev/loki/data/ComputerDataManager.java create mode 100644 src/main/java/dev/loki/objective/Computer.java create mode 100644 src/main/java/dev/loki/objective/ComputerHologram.java create mode 100644 src/main/java/dev/loki/objective/ComputerManager.java create mode 100644 src/main/java/dev/loki/objective/ComputerRepair.java diff --git a/src/main/java/dev/loki/command/DBDAdminCommand.java b/src/main/java/dev/loki/command/DBDAdminCommand.java index 194cd61..99d298f 100644 --- a/src/main/java/dev/loki/command/DBDAdminCommand.java +++ b/src/main/java/dev/loki/command/DBDAdminCommand.java @@ -58,6 +58,7 @@ public class DBDAdminCommand implements TabExecutor { if (args.length >= 2) { return switch (args[1].toLowerCase()) { case "generator" -> listType(player, "Генераторы", locations.getGenerators()); + case "computer" -> listType(player, "Компьютеры", plugin.getComputerData().getComputers()); case "hook" -> listType(player, "Крюки", locations.getHooks()); case "chest" -> listType(player, "Сундуки", locations.getChests()); case "killer-spawn", "killerspawn" -> listType(player, "Спавн киллера", locations.getKillerSpawns()); @@ -73,6 +74,7 @@ public class DBDAdminCommand implements TabExecutor { player.sendMessage(plugin.getConfigManager().getMessages().get("dbdadmin-list.header")); listType(player, "Генераторы", locations.getGenerators()); + listType(player, "Компьютеры", plugin.getComputerData().getComputers()); listType(player, "Крюки", locations.getHooks()); listType(player, "Сундуки", locations.getChests()); listType(player, "Спавн киллера", locations.getKillerSpawns()); @@ -174,7 +176,7 @@ public class DBDAdminCommand implements TabExecutor { } if (args.length == 2 && args[0].equalsIgnoreCase("list")) { - return Arrays.asList("generator", "hook", "chest", "killer-spawn", "survivor-spawn").stream() + return Arrays.asList("generator", "computer", "hook", "chest", "killer-spawn", "survivor-spawn").stream() .filter(s -> s.startsWith(args[1].toLowerCase())) .toList(); } diff --git a/src/main/java/dev/loki/command/SetupCommand.java b/src/main/java/dev/loki/command/SetupCommand.java index 197f195..53b0b3b 100644 --- a/src/main/java/dev/loki/command/SetupCommand.java +++ b/src/main/java/dev/loki/command/SetupCommand.java @@ -132,7 +132,7 @@ public class SetupCommand implements TabExecutor { default -> type; }; - if (!List.of("hook", "chest", "generator", "killer-spawn", "survivor-spawn").contains(mode)) { + if (!List.of("hook", "chest", "generator", "computer", "killer-spawn", "survivor-spawn").contains(mode)) { player.sendMessage(messages().get("setup.unknown-type", type)); return true; } @@ -264,6 +264,17 @@ public class SetupCommand implements TabExecutor { plugin.getGeneratorData().addGenerator(gLoc); player.sendMessage(messages().get("setup.generator-placed", formatLoc(loc))); } + case "computer" -> { + Location cLoc = blockLoc.clone().add(0.5, 0, 0.5); + if (locations.hasLocation("computers", cLoc)) { + player.sendMessage(messages().get("setup.duplicate")); + break; + } + locations.addLocation("computers", cLoc); + plugin.getComputerData().addComputer(cLoc); + player.sendMessage(plugin.getConfigManager().getMessages().get("setup.computer-placed", + formatLoc(loc))); + } case "killer-spawn" -> { if (locations.getKillerSpawn() != null) { player.sendMessage(messages().get("setup.killer-spawn-exists")); @@ -351,6 +362,7 @@ public class SetupCommand implements TabExecutor { // Clear ALL object data from config (no block destruction) locations.clearLocationList("generators"); + locations.clearLocationList("computers"); locations.clearLocationList("hooks"); locations.clearLocationList("chests"); locations.clearLocationList("killer-spawn"); @@ -361,6 +373,7 @@ public class SetupCommand implements TabExecutor { } locations.clearSurvivorSpawns(); plugin.getGeneratorData().clearGenerators(); + plugin.getComputerData().clearComputers(); plugin.getConfigManager().saveConfig("locations.yml", locations.getConfig()); player.sendMessage(messages().get("setup.cleared")); return true; @@ -369,6 +382,7 @@ public class SetupCommand implements TabExecutor { private boolean clearObjectsByType(Player player, LocationsConfig locations, String type) { String path = switch (type) { case "generator" -> "generators"; + case "computer" -> "computers"; case "hook" -> "hooks"; case "chest" -> "chests"; case "gate" -> null; @@ -392,6 +406,8 @@ public class SetupCommand implements TabExecutor { locations.clearLocationList(path); if (type.equals("generator")) { plugin.getGeneratorData().clearGenerators(); + } else if (type.equals("computer")) { + plugin.getComputerData().clearComputers(); } } plugin.getConfigManager().saveConfig("locations.yml", locations.getConfig()); @@ -423,6 +439,18 @@ public class SetupCommand implements TabExecutor { plugin.getGeneratorData().removeGenerator(index); player.sendMessage(messages().get("setup.deleted", "generator #" + index)); } + case "computer" -> { + int index = parseInt(args[2], player); + if (index < 0) return true; + var comps = plugin.getComputerData().getComputers(); + if (index >= comps.size()) { + player.sendMessage(messages().get("setup.out-of-range", index)); + return true; + } + locations.removeLocationAtIndex("computers", index); + plugin.getComputerData().removeComputer(index); + player.sendMessage(messages().get("setup.deleted", "computer #" + index)); + } case "hook" -> { int index = parseInt(args[2], player); if (index < 0) return true; @@ -515,6 +543,7 @@ public class SetupCommand implements TabExecutor { sender.sendMessage(messages().get("usage.setup-hook")); sender.sendMessage(messages().get("usage.setup-chest")); sender.sendMessage(messages().get("usage.setup-generator")); + sender.sendMessage(messages().get("usage.setup-computer")); sender.sendMessage(messages().get("usage.setup-killer-spawn")); sender.sendMessage(messages().get("usage.setup-survivor-spawn")); sender.sendMessage(messages().get("usage.setup-gate")); @@ -539,7 +568,7 @@ public class SetupCommand implements TabExecutor { } if (args.length == 2) { if (args[0].equalsIgnoreCase("set") || args[0].equalsIgnoreCase("clear") || args[0].equalsIgnoreCase("delete")) { - return List.of("generator", "hook", "chest", "killer-spawn", "survivor-spawn", "gate").stream() + return List.of("computer", "generator", "hook", "chest", "killer-spawn", "survivor-spawn", "gate").stream() .filter(s -> s.startsWith(args[1].toLowerCase())).toList(); } } diff --git a/src/main/java/dev/loki/config/GameConfig.java b/src/main/java/dev/loki/config/GameConfig.java index 64787e4..2b62100 100644 --- a/src/main/java/dev/loki/config/GameConfig.java +++ b/src/main/java/dev/loki/config/GameConfig.java @@ -28,8 +28,6 @@ public class GameConfig { setDefault("generators.total-count", 7); setDefault("generators.required-count", 5); setDefault("generators.repair-seconds", 90); - setDefault("generators.regression-rate", 0.25); - setDefault("generators.kick-regression-rate", 2.5); setDefault("generators.kick-regression-percent", 20.0); setDefault("generators.kick-duration-seconds", 30); setDefault("generators.kick-cooldown-seconds", 30); @@ -37,6 +35,12 @@ public class GameConfig { setDefault("generators.interaction-range", 3.0); setDefault("generators.minigame", "gui"); + // Computers + setDefault("computers.total-count", 2); + setDefault("computers.required-count", 2); + setDefault("computers.repair-seconds", 90); + setDefault("computers.interaction-range", 3.0); + // Hooks setDefault("hooks.stage1-seconds", 60); setDefault("hooks.stage2-seconds", 60); @@ -111,6 +115,7 @@ public class GameConfig { // Block types for spawning setDefault("blocks.generator", "BLAST_FURNACE"); + setDefault("blocks.computer", "LECTERN"); setDefault("blocks.chest", "CHEST"); setDefault("blocks.hook", "IRON_BARS"); @@ -118,6 +123,8 @@ public class GameConfig { setDefault("holograms.enabled", true); setDefault("holograms.generator.enabled", true); setDefault("holograms.generator.height-offset", -1.0); + setDefault("holograms.computer.enabled", true); + setDefault("holograms.computer.height-offset", -1.0); setDefault("holograms.hook.enabled", true); setDefault("holograms.hook.height-offset", -1.0); setDefault("holograms.chest.enabled", true); @@ -133,6 +140,22 @@ public class GameConfig { // Chest loot setDefault("chest.loot-reset-minutes", 3.0); + + // Loot weights + setDefault("loot.medkit.weight", 25); + setDefault("loot.medkit.min-charges", 12); + setDefault("loot.medkit.max-charges", 16); + setDefault("loot.bandage.weight", 25); + setDefault("loot.full-medkit.weight", 10); + setDefault("loot.soda.weight", 20); + setDefault("loot.wrench.weight", 20); + + // Item model data + setDefault("items.model-data.medkit", 1001); + setDefault("items.model-data.bandage", 1004); + setDefault("items.model-data.fullmedkit", 1005); + setDefault("items.model-data.soda", 1006); + setDefault("items.model-data.wrench", 1007); } private void setDefault(String path, Object value) { @@ -176,6 +199,20 @@ public class GameConfig { public double getGeneratorInteractionRange() { return config.getDouble("generators.interaction-range", 3.0); } public String getGeneratorMinigame() { return config.getString("generators.minigame", "gui"); } + // ------------------------------------------------------------------------- + // Computers + // ------------------------------------------------------------------------- + public int getComputerTotal() { return config.getInt("computers.total-count", 5); } + public int getComputerRequired() { return config.getInt("computers.required-count", 3); } + public int getComputerRepairSeconds() { return config.getInt("computers.repair-seconds", 90); } + public double getComputerRegressionRate() { return config.getDouble("computers.regression-rate", 0.25); } + public double getComputerKickRegressionRate() { return config.getDouble("computers.kick-regression-rate", 2.5); } + public double getComputerKickRegressionPercent() { return config.getDouble("computers.kick-regression-percent", 20.0); } + public int getComputerKickDuration() { return config.getInt("computers.kick-duration-seconds", 30); } + public int getComputerKickCooldownSeconds() { return config.getInt("computers.kick-cooldown-seconds", 30); } + public int getComputerKickChargeSeconds() { return config.getInt("computers.kick-charge-seconds", 3); } + public double getComputerInteractionRange() { return config.getDouble("computers.interaction-range", 3.0); } + // ------------------------------------------------------------------------- // Hooks // ------------------------------------------------------------------------- @@ -229,6 +266,7 @@ public class GameConfig { // Block types (какие блоки спавнятся на местах объектов) // ------------------------------------------------------------------------- public String getGeneratorBlock() { return config.getString("blocks.generator", "BLAST_FURNACE"); } + public String getComputerBlock() { return config.getString("blocks.computer", "LECTERN"); } public String getChestBlock() { return config.getString("blocks.chest", "CHEST"); } public String getHookBlock() { return config.getString("blocks.hook", "IRON_BARS"); } @@ -238,6 +276,8 @@ public class GameConfig { public boolean isHologramsEnabled() { return config.getBoolean("holograms.enabled", true); } public boolean isGeneratorHologramEnabled() { return config.getBoolean("holograms.generator.enabled", true); } public double getGeneratorHologramHeightOffset() { return config.getDouble("holograms.generator.height-offset", -1.0); } + public boolean isComputerHologramEnabled() { return config.getBoolean("holograms.computer.enabled", true); } + public double getComputerHologramHeightOffset() { return config.getDouble("holograms.computer.height-offset", -1.0); } public boolean isHookHologramEnabled() { return config.getBoolean("holograms.hook.enabled", true); } public double getHookHologramHeightOffset() { return config.getDouble("holograms.hook.height-offset", 0.0); } public boolean isChestHologramEnabled() { return config.getBoolean("holograms.chest.enabled", true); } diff --git a/src/main/java/dev/loki/config/LocationsConfig.java b/src/main/java/dev/loki/config/LocationsConfig.java index 4e986a6..7bf719c 100644 --- a/src/main/java/dev/loki/config/LocationsConfig.java +++ b/src/main/java/dev/loki/config/LocationsConfig.java @@ -31,6 +31,9 @@ public class LocationsConfig { if (!config.contains("generators") || config.getList("generators") == null) { config.set("generators", new ArrayList<>()); } + if (!config.contains("computers") || config.getList("computers") == null) { + config.set("computers", new ArrayList<>()); + } if (!config.contains("hooks") || config.getList("hooks") == null) { config.set("hooks", new ArrayList<>()); } diff --git a/src/main/java/dev/loki/core/GameSession.java b/src/main/java/dev/loki/core/GameSession.java index 46e2a57..9960d4a 100644 --- a/src/main/java/dev/loki/core/GameSession.java +++ b/src/main/java/dev/loki/core/GameSession.java @@ -5,6 +5,7 @@ import dev.loki.gate.GateManager; import dev.loki.hook.HookManager; import dev.loki.mdbd; import dev.loki.objective.GeneratorManager; +import dev.loki.objective.ComputerManager; import dev.loki.phase.EndgamePhase; import dev.loki.phase.GameplayPhase; import dev.loki.phase.LobbyPhase; @@ -28,6 +29,7 @@ public class GameSession { private int ticksElapsed; private RoleAssigner roleAssigner; private GeneratorManager generatorManager; + private ComputerManager computerManager; private boolean forceStarted = false; private Runnable onStopped; // callback для LobbyRegistry @@ -44,6 +46,9 @@ public class GameSession { this.generatorManager = new GeneratorManager( plugin.getGeneratorData(), plugin.getConfigManager().getGame().getGeneratorRequired(), plugin.getConfigManager().getGame()); + this.computerManager = new ComputerManager( + plugin.getComputerData(), plugin.getConfigManager().getGame().getComputerRequired(), + plugin.getConfigManager().getGame()); } public void start() { @@ -110,7 +115,7 @@ public class GameSession { return new RoleAssignPhase(roleAssigner, skip); } if (currentPhase instanceof RoleAssignPhase) { - return new GameplayPhase(generatorManager); + return new GameplayPhase(generatorManager, computerManager); } if (currentPhase instanceof GameplayPhase gp) { // Всегда переходим в EndgamePhase для корректного завершения игры @@ -177,6 +182,10 @@ public class GameSession { return generatorManager; } + public ComputerManager getComputerManager() { + return computerManager; + } + public HookManager getHookManager() { return hookManager; } public void setHookManager(HookManager hm) { this.hookManager = hm; } diff --git a/src/main/java/dev/loki/data/ComputerDataManager.java b/src/main/java/dev/loki/data/ComputerDataManager.java new file mode 100644 index 0000000..4dce0e4 --- /dev/null +++ b/src/main/java/dev/loki/data/ComputerDataManager.java @@ -0,0 +1,148 @@ +package dev.loki.data; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class ComputerDataManager { + + private static final double ZONE_RADIUS = 3.0; + + private final JavaPlugin plugin; + private final File dataFile; + private FileConfiguration data; + + public ComputerDataManager(JavaPlugin plugin) { + this.plugin = plugin; + this.dataFile = new File(plugin.getDataFolder(), "computers.yml"); + load(); + } + + public void load() { + if (!dataFile.exists()) { + try { + dataFile.createNewFile(); + } catch (IOException e) { + plugin.getLogger().warning("Could not create computers.yml"); + } + } + this.data = YamlConfiguration.loadConfiguration(dataFile); + } + + public void save() { + try { + data.save(dataFile); + } catch (IOException e) { + plugin.getLogger().warning("Could not save computers.yml"); + } + } + + public void addComputer(Location location) { + List list = data.getStringList("computers"); + String entry = formatLocation(location); + if (!list.contains(entry)) { + list.add(entry); + data.set("computers", list); + save(); + } + } + + public void removeComputer(int index) { + List list = data.getStringList("computers"); + if (index >= 0 && index < list.size()) { + list.remove(index); + data.set("computers", list); + save(); + } + } + + public void clearComputers() { + data.set("computers", null); + save(); + } + + public List getComputers() { + List result = new ArrayList<>(); + List list = data.getStringList("computers"); + for (String entry : list) { + Location loc = parseLocation(entry); + if (loc != null) { + result.add(loc); + } + } + return result; + } + + public List getComputerEntries() { + return data.getStringList("computers"); + } + + public int getCount() { + return data.getStringList("computers").size(); + } + + public static String formatLocation(Location loc) { + return String.format("%s:%.0f|%.0f|%.0f", + loc.getWorld().getName(), + loc.getX(), + loc.getY(), + loc.getZ()); + } + + private Location parseLocation(String str) { + String[] parts = str.split(":"); + if (parts.length < 2) return null; + + World world = Bukkit.getWorld(parts[0].trim()); + if (world == null) return null; + + String[] coords = parts[1].split("\\|"); + if (coords.length < 3) return null; + + try { + double x = Double.parseDouble(coords[0].trim()); + double y = Double.parseDouble(coords[1].trim()); + double z = Double.parseDouble(coords[2].trim()); + return new Location(world, x, y, z); + } catch (NumberFormatException e) { + return null; + } + } + + public static double getZoneRadius() { + return ZONE_RADIUS; + } + + public boolean isInZone(Location location, List computers) { + for (Location compLoc : computers) { + if (!compLoc.getWorld().equals(location.getWorld())) continue; + if (compLoc.distance(location) <= ZONE_RADIUS) { + return true; + } + } + return false; + } + + public Location getNearestComputer(Location location, List computers) { + Location nearest = null; + double nearestDist = ZONE_RADIUS; + + for (Location compLoc : computers) { + if (!compLoc.getWorld().equals(location.getWorld())) continue; + double dist = compLoc.distance(location); + if (dist <= nearestDist) { + nearestDist = dist; + nearest = compLoc; + } + } + return nearest; + } +} diff --git a/src/main/java/dev/loki/listener/PlayerInteractListener.java b/src/main/java/dev/loki/listener/PlayerInteractListener.java index 0985957..e236438 100644 --- a/src/main/java/dev/loki/listener/PlayerInteractListener.java +++ b/src/main/java/dev/loki/listener/PlayerInteractListener.java @@ -3,6 +3,7 @@ package dev.loki.listener; import dev.loki.command.SetupCommand; import dev.loki.core.GameManager; import dev.loki.objective.GeneratorManager; +import dev.loki.objective.ComputerManager; import dev.loki.player.BasePlayer; import dev.loki.player.PlayerState; import org.bukkit.Location; @@ -26,9 +27,11 @@ public class PlayerInteractListener implements Listener { private final Plugin plugin; private final GameManager gameManager; private GeneratorManager generatorManager; + private ComputerManager computerManager; private SetupCommand setupCommand; private BiConsumer onGeneratorInteract; + private BiConsumer onComputerInteract; private BiConsumer onAttack; private BiConsumer onRescueAttempt; private BiConsumer onChestInteract; @@ -53,6 +56,7 @@ public class PlayerInteractListener implements Listener { } public void setOnGeneratorInteract(BiConsumer h) { this.onGeneratorInteract = h; } + public void setOnComputerInteract(BiConsumer h) { this.onComputerInteract = h; } public void setOnAttack(BiConsumer h) { this.onAttack = h; } public void setOnRescueAttempt(BiConsumer h) { this.onRescueAttempt = h; } public void setOnChestInteract(BiConsumer h) { this.onChestInteract = h; } @@ -69,6 +73,10 @@ public class PlayerInteractListener implements Listener { this.generatorManager = manager; } + public void setComputerManager(ComputerManager manager) { + this.computerManager = manager; + } + @EventHandler public void onSneak(PlayerToggleSneakEvent event) { Player player = event.getPlayer(); @@ -96,8 +104,10 @@ public class PlayerInteractListener implements Listener { if (st != PlayerState.HEALTHY && st != PlayerState.INJURED) return; if (event.isSneaking()) { - // Generator repair takes priority over healing + // Generator repair takes priority if (tryGeneratorInteract(player)) return; + // Computer repair + if (tryComputerInteract(player)) return; // Healing: check if sneaking near an injured/downed survivor if (onHealSneak != null) { @@ -216,6 +226,19 @@ public class PlayerInteractListener implements Listener { return true; } + private boolean tryComputerInteract(Player player) { + if (onComputerInteract == null || computerManager == null) return false; + var session = gameManager.getPlayerSession(player.getUniqueId()); + if (session == null) return false; + BasePlayer bp = session.getPlayer(player.getUniqueId()); + if (bp == null || bp.isKiller()) return false; + var comp = computerManager.getNearestComputer( + player.getLocation(), session.getConfig().getComputerInteractionRange()); + if (comp == null) return false; + onComputerInteract.accept(player, Action.RIGHT_CLICK_AIR); + return true; + } + private boolean isOnCooldown(Player player) { long now = System.currentTimeMillis(); Long last = lastClick.get(player.getUniqueId()); @@ -234,6 +257,11 @@ public class PlayerInteractListener implements Listener { return; } + // Cancel right-click on LECTERN (computer block) to prevent book editing GUI + if (type.equals("LECTERN")) { + event.setCancelled(true); + } + // Chest interaction - cancel vanilla GUI for ALL players (including killer) if (type.contains("CHEST")) { event.setCancelled(true); @@ -257,6 +285,7 @@ public class PlayerInteractListener implements Listener { } if (!bp.isKiller() && tryGeneratorInteract(player)) return; + if (!bp.isKiller() && tryComputerInteract(player)) return; // Killer attack (hook/carry) — fires on both air AND block clicks if (bp.isKiller() && onAttack != null) { diff --git a/src/main/java/dev/loki/listener/SetupBlockBreakListener.java b/src/main/java/dev/loki/listener/SetupBlockBreakListener.java index ae2b868..80597fe 100644 --- a/src/main/java/dev/loki/listener/SetupBlockBreakListener.java +++ b/src/main/java/dev/loki/listener/SetupBlockBreakListener.java @@ -49,6 +49,7 @@ public class SetupBlockBreakListener implements Listener { Material placeMat = switch (mode) { case "chest" -> Material.matchMaterial(cfg.getChestBlock()); case "generator" -> Material.matchMaterial(cfg.getGeneratorBlock()); + case "computer" -> Material.matchMaterial(cfg.getComputerBlock()); case "hook" -> Material.matchMaterial(cfg.getHookBlock()); default -> null; }; diff --git a/src/main/java/dev/loki/mdbd.java b/src/main/java/dev/loki/mdbd.java index d1b2d93..6799ed3 100644 --- a/src/main/java/dev/loki/mdbd.java +++ b/src/main/java/dev/loki/mdbd.java @@ -6,6 +6,7 @@ import dev.loki.command.SetupCommand; import dev.loki.config.ConfigManager; import dev.loki.core.GameManager; import dev.loki.data.GeneratorDataManager; +import dev.loki.data.ComputerDataManager; import dev.loki.listener.PlayerInteractListener; import dev.loki.listener.PlayerJoinListener; import dev.loki.listener.PlayerMoveListener; @@ -25,6 +26,7 @@ public final class mdbd extends JavaPlugin { private MapManager mapManager; private MapBuilder mapBuilder; private GeneratorDataManager generatorData; + private ComputerDataManager computerData; private LobbyRegistry lobbyRegistry; private DBDCommand dbdCommand; private DBDAdminCommand dbdAdminCommand; @@ -53,6 +55,7 @@ public final class mdbd extends JavaPlugin { this.mapBuilder = new MapBuilder(this, templateManager); this.generatorData = new GeneratorDataManager(this); + this.computerData = new ComputerDataManager(this); this.lobbyManager = new LobbyManager(this); this.lobbyManager.loadWorlds(); @@ -103,6 +106,9 @@ public final class mdbd extends JavaPlugin { if (generatorData != null) { generatorData.save(); } + if (computerData != null) { + computerData.save(); + } if (lobbyRegistry != null) { lobbyRegistry.save(); } @@ -137,6 +143,10 @@ public final class mdbd extends JavaPlugin { return generatorData; } + public ComputerDataManager getComputerData() { + return computerData; + } + public DBDAdminCommand getDbdAdminCommand() { return dbdAdminCommand; } @@ -162,6 +172,7 @@ public final class mdbd extends JavaPlugin { dev.loki.item.DBDItems.loadModelData(configManager.getGame().getConfig()); templateManager.loadAllTemplates(); generatorData.load(); + computerData.load(); getLogger().info("All configs reloaded!"); } } diff --git a/src/main/java/dev/loki/objective/Computer.java b/src/main/java/dev/loki/objective/Computer.java new file mode 100644 index 0000000..bf64c19 --- /dev/null +++ b/src/main/java/dev/loki/objective/Computer.java @@ -0,0 +1,146 @@ +package dev.loki.objective; + +import dev.loki.data.ComputerDataManager; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import java.util.UUID; + +public class Computer { + private final int id; + private final Location location; + private final double zoneRadius; + private double progress; + private boolean isCompleted; + private boolean isBlocked; + private UUID currentRepairer; + private int regressionTicks; + private boolean wasKicked; + + public Computer(int id, Location location) { + this(id, location, ComputerDataManager.getZoneRadius()); + } + + public Computer(int id, Location location, double zoneRadius) { + this.id = id; + this.location = location; + this.zoneRadius = zoneRadius; + this.progress = 0.0; + this.isCompleted = false; + this.isBlocked = false; + this.currentRepairer = null; + this.regressionTicks = 0; + this.wasKicked = false; + } + + public int getId() { + return id; + } + + public Location getLocation() { + return location; + } + + public double getZoneRadius() { + return zoneRadius; + } + + public boolean isPlayerInZone(Player player) { + if (!player.getWorld().equals(location.getWorld())) return false; + return player.getLocation().distance(location) <= zoneRadius; + } + + public boolean isLocationInZone(Location loc) { + if (!loc.getWorld().equals(location.getWorld())) return false; + return loc.distance(location) <= zoneRadius; + } + + public double getProgress() { + return progress; + } + + public void setProgress(double progress) { + this.progress = Math.max(0, Math.min(100, progress)); + if (this.progress >= 100) { + this.progress = 100; + this.isCompleted = true; + } + } + + public void addProgress(double amount) { + setProgress(progress + amount); + } + + public void removeProgress(double amount) { + setProgress(progress - amount); + } + + public boolean isCompleted() { + return isCompleted; + } + + public boolean isBlocked() { + return isBlocked; + } + + public void setBlocked(boolean blocked) { + this.isBlocked = blocked; + } + + public UUID getCurrentRepairer() { + return currentRepairer; + } + + public void setCurrentRepairer(UUID repairer) { + this.currentRepairer = repairer; + } + + public boolean isBeingRepaired() { + return currentRepairer != null; + } + + public int getRegressionTicks() { + return regressionTicks; + } + + public void setRegressionTicks(int ticks) { + this.regressionTicks = ticks; + } + + public void decrementRegression() { + if (regressionTicks > 0) { + regressionTicks--; + } + } + + public boolean isUnderRegression() { + return regressionTicks > 0 && !isCompleted && !isBeingRepaired(); + } + + public void setUnderRegression(boolean kicked, int durationTicks) { + this.wasKicked = kicked; + this.regressionTicks = durationTicks; + } + + public boolean wasKicked() { + return wasKicked; + } + + public void setKicked(boolean kicked) { + this.wasKicked = kicked; + } + + public boolean canBeRepaired() { + return !isCompleted && !isBlocked && !isUnderRegression(); + } + + @Deprecated + public Block getBlock() { + return location.getBlock(); + } + + public double getDistance(Location loc) { + return location.distance(loc); + } +} diff --git a/src/main/java/dev/loki/objective/ComputerHologram.java b/src/main/java/dev/loki/objective/ComputerHologram.java new file mode 100644 index 0000000..8dbf7a7 --- /dev/null +++ b/src/main/java/dev/loki/objective/ComputerHologram.java @@ -0,0 +1,134 @@ +package dev.loki.objective; + +import dev.loki.mdbd; +import dev.loki.util.TextUtil; +import org.bukkit.Location; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Display; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.TextDisplay; +import org.bukkit.scheduler.BukkitTask; + +import java.util.HashMap; +import java.util.Map; + +public class ComputerHologram { + + private final mdbd plugin; + private final ComputerManager manager; + private final Map displays = new HashMap<>(); + private BukkitTask task; + private boolean useTextDisplay; + + public ComputerHologram(mdbd plugin, ComputerManager manager) { + this.plugin = plugin; + this.manager = manager; + this.useTextDisplay = isTextDisplayAvailable(); + } + + private static boolean isTextDisplayAvailable() { + try { + EntityType.valueOf("TEXT_DISPLAY"); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } + + public void start() { + stop(); + spawnAll(); + task = plugin.getServer().getScheduler().runTaskTimer(plugin, this::refresh, 20L, 20L); + plugin.getLogger().info("[ComputerHologram] Started with " + displays.size() + " holograms (mode=" + (useTextDisplay ? "TextDisplay" : "ArmorStand") + ")"); + } + + public void stop() { + if (task != null) { + task.cancel(); + task = null; + } + for (Object display : displays.values()) { + if (display instanceof TextDisplay td && td.isValid()) { + td.remove(); + } else if (display instanceof ArmorStand as && as.isValid()) { + as.remove(); + } + } + displays.clear(); + } + + private void spawnAll() { + double heightOffset = plugin.getConfigManager().getGame().getComputerHologramHeightOffset(); + for (Computer comp : manager.getAllComputers()) { + Location loc = comp.getLocation(); + if (loc.getWorld() == null) continue; + + Location holoLoc = loc.getBlock().getLocation().add(0.5, 2.0 + heightOffset, 0.5); + try { + if (useTextDisplay) { + TextDisplay display = loc.getWorld().spawn(holoLoc, TextDisplay.class, d -> { + d.setBillboard(Display.Billboard.VERTICAL); + d.setSeeThrough(false); + d.setShadowed(true); + d.setDefaultBackground(false); + d.setPersistent(false); + d.setTextOpacity((byte) -1); + }); + displays.put(comp.getId(), display); + } else { + ArmorStand stand = loc.getWorld().spawn(holoLoc, ArmorStand.class, as -> { + as.setInvisible(true); + as.setInvulnerable(true); + as.setGravity(false); + as.setMarker(true); + as.setCustomNameVisible(true); + as.setPersistent(false); + }); + displays.put(comp.getId(), stand); + } + } catch (Exception e) { + plugin.getLogger().warning("[ComputerHologram] Failed to spawn hologram for computer " + comp.getId() + ": " + e.getMessage()); + } + } + } + + private void refresh() { + double heightOffset = plugin.getConfigManager().getGame().getComputerHologramHeightOffset(); + int total = manager.getTotalCount(); + for (Computer comp : manager.getAllComputers()) { + Object display = displays.get(comp.getId()); + if (display == null) continue; + + boolean valid = (display instanceof TextDisplay td && td.isValid()) || + (display instanceof ArmorStand as && as.isValid()); + if (!valid) continue; + + int pct = (int) comp.getProgress(); + String bar = buildBar(pct); + String text; + if (comp.isCompleted()) { + text = "§b🖥 Компьютер §f#" + (comp.getId() + 1) + "/" + total + "\n§a✔ Починен!"; + } else if (comp.isUnderRegression()) { + text = "§b🖥 Компьютер §f#" + (comp.getId() + 1) + "/" + total + "\n§c↓ " + bar + " §f" + pct + "%"; + } else { + text = "§b🖥 Компьютер §f#" + (comp.getId() + 1) + "/" + total + "\n§e" + bar + " §f" + pct + "%"; + } + + Location base = comp.getLocation().getBlock().getLocation().add(0.5, 2.0 + heightOffset, 0.5); + + if (display instanceof TextDisplay td) { + td.text(TextUtil.color(text)); + td.teleport(base); + } else if (display instanceof ArmorStand as) { + as.setCustomName(text); + as.teleport(base); + } + } + } + + private String buildBar(int pct) { + int filled = pct / 10; + int empty = 10 - filled; + return "§e" + "█".repeat(Math.max(0, filled)) + "§7" + "░".repeat(Math.max(0, empty)); + } +} diff --git a/src/main/java/dev/loki/objective/ComputerManager.java b/src/main/java/dev/loki/objective/ComputerManager.java new file mode 100644 index 0000000..e63eadf --- /dev/null +++ b/src/main/java/dev/loki/objective/ComputerManager.java @@ -0,0 +1,114 @@ +package dev.loki.objective; + +import dev.loki.data.ComputerDataManager; +import dev.loki.config.GameConfig; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ComputerManager { + private final Map computers; + private final int requiredCount; + private final double normalRegressionRate; + private final double kickRegressionRate; + + public ComputerManager(ComputerDataManager dataManager, int requiredCount, GameConfig config) { + this.computers = new HashMap<>(); + loadComputers(dataManager); + this.requiredCount = Math.min(requiredCount, computers.size()); + this.normalRegressionRate = config.getComputerRegressionRate() / 20.0; + this.kickRegressionRate = config.getComputerKickRegressionRate() / 20.0; + } + + private void loadComputers(ComputerDataManager dataManager) { + List locations = dataManager.getComputers(); + for (int i = 0; i < locations.size(); i++) { + computers.put(i, new Computer(i, locations.get(i))); + } + } + + public Computer getComputer(int id) { return computers.get(id); } + + public Computer getComputerAt(Location location) { + for (Computer comp : computers.values()) { + if (comp.isLocationInZone(location)) return comp; + } + return null; + } + + public Computer getNearestComputer(Location location, double maxDistance) { + Computer nearest = null; + double nearestDist = maxDistance; + for (Computer comp : computers.values()) { + if (!comp.getLocation().getWorld().equals(location.getWorld())) continue; + double dist = comp.getDistance(location); + if (dist < nearestDist) { nearestDist = dist; nearest = comp; } + } + return nearest; + } + + public boolean isInAnyZone(Player player) { + return getComputerAt(player.getLocation()) != null; + } + + public List getAllComputers() { return new ArrayList<>(computers.values()); } + + public List getIncompleteComputers() { + List incomplete = new ArrayList<>(); + for (Computer comp : computers.values()) { + if (!comp.isCompleted()) incomplete.add(comp); + } + return incomplete; + } + + public int getTotalCount() { return computers.size(); } + public int getRequiredCount() { return requiredCount; } + + public int getCompletedCount() { + int count = 0; + for (Computer comp : computers.values()) { + if (comp.isCompleted()) count++; + } + return count; + } + + public int getRemainingRequired() { + return Math.max(0, requiredCount - getCompletedCount()); + } + + public void onComputerCompleted(Computer computer) { + } + + public boolean areAllRequiredCompleted() { + return getCompletedCount() >= requiredCount; + } + + public double getAverageProgress() { + if (computers.isEmpty()) return 0; + double total = 0; + for (Computer comp : computers.values()) total += comp.getProgress(); + return total / computers.size(); + } + + public int getActiveRepairCount() { + int count = 0; + for (Computer comp : computers.values()) { + if (comp.isBeingRepaired()) count++; + } + return count; + } + + public void tick() { + for (Computer comp : computers.values()) { + if (comp.isUnderRegression()) { + double rate = comp.wasKicked() ? kickRegressionRate : normalRegressionRate; + comp.removeProgress(rate); + } + comp.decrementRegression(); + } + } +} diff --git a/src/main/java/dev/loki/objective/ComputerRepair.java b/src/main/java/dev/loki/objective/ComputerRepair.java new file mode 100644 index 0000000..bf193fd --- /dev/null +++ b/src/main/java/dev/loki/objective/ComputerRepair.java @@ -0,0 +1,195 @@ +package dev.loki.objective; + +import dev.loki.mdbd; +import dev.loki.minigames.GeneratorMinigame; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class ComputerRepair { + private final mdbd plugin; + private final ComputerManager manager; + private final Map sessions; + private final GeneratorMinigame minigame; + + private dev.loki.item.ItemUseListener itemUseListener; + + private static final double REPAIR_PER_TICK = 100.0 / 1600.0; + private static final double REPAIR_BOOST_MULTIPLIER = 2.0; + private static final double REPAIR_RANGE = 3.0; + + public void setItemUseListener(dev.loki.item.ItemUseListener listener) { + this.itemUseListener = listener; + } + + public ComputerRepair(mdbd plugin, ComputerManager manager, GeneratorMinigame minigame) { + this.plugin = plugin; + this.manager = manager; + this.minigame = minigame; + this.sessions = new HashMap<>(); + } + + public void startRepair(Player player, Computer computer) { + UUID uuid = player.getUniqueId(); + + if (sessions.containsKey(uuid)) { + RepairSession existing = sessions.get(uuid); + if (existing.computer.getId() == computer.getId()) { + return; + } else { + stopRepair(player); + } + } + + if (!computer.canBeRepaired()) { + player.sendMessage(plugin.getConfigManager().getMessages().get("computer.repair.cannot")); + return; + } + + if (computer.isBeingRepaired() && !computer.getCurrentRepairer().equals(uuid)) { + player.sendMessage(plugin.getConfigManager().getMessages().get("computer.repair.busy")); + return; + } + + computer.setCurrentRepairer(uuid); + RepairSession session = new RepairSession(player, computer); + sessions.put(uuid, session); + } + + public void stopRepair(Player player) { + UUID uuid = player.getUniqueId(); + RepairSession session = sessions.remove(uuid); + + if (session != null) { + session.computer.setCurrentRepairer(null); + if (!session.computer.isUnderRegression() && !session.computer.isBlocked()) { + session.computer.setBlocked(false); + } + player.sendActionBar(Component.empty()); + } + } + + public void tick() { + for (RepairSession session : new HashMap<>(sessions).values()) { + if (!updateRepair(session)) { + stopRepair(session.player); + } + } + } + + private boolean updateRepair(RepairSession session) { + Player player = session.player; + Computer computer = session.computer; + + if (!player.isOnline()) return false; + if (!player.isSneaking()) return false; + if (computer.getDistance(player.getLocation()) > REPAIR_RANGE) return false; + if (computer.isCompleted()) return false; + + if (minigame.isActive(player.getUniqueId())) return true; + + if (session.skillCheckCooldown > 0) { + session.skillCheckCooldown--; + } else if (shouldTriggerSkillCheck()) { + minigame.start(player, (p, success) -> { + Computer c = session.computer; + if (success) { + double winPercent = plugin.getConfigManager().getGame().getSkillCheckWinPercent(); + c.addProgress(winPercent); + p.sendActionBar(plugin.getConfigManager().getMessages().get("computer.repair.skillcheck-success", (int)winPercent)); + p.playSound(p.getLocation(), org.bukkit.Sound.ENTITY_PLAYER_LEVELUP, 0.8f, 1.2f); + } else { + double lossPercent = plugin.getConfigManager().getGame().getSkillCheckLossPercent(); + c.removeProgress(lossPercent); + p.sendActionBar(plugin.getConfigManager().getMessages().get("computer.repair.skillcheck-fail", (int)lossPercent)); + p.playSound(p.getLocation(), org.bukkit.Sound.ENTITY_BLAZE_HURT, 1.0f, 0.5f); + } + }); + session.skillCheckCooldown = 100 + (int)(Math.random() * 200); + return true; + } + + double rate = REPAIR_PER_TICK; + if (itemUseListener != null && itemUseListener.hasRepairBoost(player.getUniqueId())) { + rate *= REPAIR_BOOST_MULTIPLIER; + } + computer.addProgress(rate); + showProgressBar(player, session); + + if (computer.isCompleted()) { + onComputerComplete(computer, player); + return false; + } + + return true; + } + + private void showProgressBar(Player player, RepairSession session) { + double progress = session.computer.getProgress(); + String bar = renderProgressBar(progress); + player.sendActionBar(plugin.getConfigManager().getMessages().get("computer.repair.actionbar", bar)); + } + + private String renderProgressBar(double progress) { + int filled = (int) (10 * progress / 100.0); + int empty = 10 - filled; + StringBuilder bar = new StringBuilder(""); + bar.append("█".repeat(Math.max(0, filled))); + bar.append(""); + bar.append("░".repeat(Math.max(0, empty))); + bar.append(" ").append((int)progress).append("%"); + return bar.toString(); + } + + private void onComputerComplete(Computer computer, Player player) { + manager.onComputerCompleted(computer); + Bukkit.broadcast(plugin.getConfigManager().getMessages().get( + "computer.repair.broadcast", manager.getCompletedCount(), manager.getRequiredCount())); + } + + private boolean shouldTriggerSkillCheck() { + double chance = plugin.getConfigManager().getGame().getSkillCheckChance(); + return Math.random() < chance; + } + + public boolean isRepairing(UUID uuid) { + return sessions.containsKey(uuid); + } + + public GeneratorMinigame getMinigame() { + return minigame; + } + + public boolean isMinigameActive(UUID playerId) { + return minigame.isActive(playerId); + } + + public void handleMinigameClick(Player player) { + minigame.handleRightClick(player); + } + + public void handleMinigameSneak(Player player) { + minigame.handleSneak(player); + } + + public void shutdown() { + minigame.cleanup(); + sessions.clear(); + } + + public static class RepairSession { + final Player player; + final Computer computer; + int skillCheckCooldown; + + RepairSession(Player player, Computer computer) { + this.player = player; + this.computer = computer; + this.skillCheckCooldown = 50; + } + } +} diff --git a/src/main/java/dev/loki/phase/EndgamePhase.java b/src/main/java/dev/loki/phase/EndgamePhase.java index c8e76cf..220757d 100644 --- a/src/main/java/dev/loki/phase/EndgamePhase.java +++ b/src/main/java/dev/loki/phase/EndgamePhase.java @@ -104,7 +104,7 @@ public class EndgamePhase implements Phase { for (BasePlayer bp : session.getPlayers().values()) { Player p = bp.getPlayer(); if (p != null && p.isOnline()) { - sidebar.updateGameStats(p, session, session.getGeneratorManager()); + sidebar.updateGameStats(p, session, session.getGeneratorManager(), session.getComputerManager()); } } } diff --git a/src/main/java/dev/loki/phase/GameplayInteraction.java b/src/main/java/dev/loki/phase/GameplayInteraction.java index a077b94..bd2ed50 100644 --- a/src/main/java/dev/loki/phase/GameplayInteraction.java +++ b/src/main/java/dev/loki/phase/GameplayInteraction.java @@ -45,6 +45,7 @@ public class GameplayInteraction { private dev.loki.chest.ChestOpening chestOpening; private GateOpening gateOpening; private dev.loki.objective.GeneratorRepair generatorRepair; + private dev.loki.objective.ComputerRepair computerRepair; private boolean allGensDone; private final Map killerLastSneakMs = new HashMap<>(); private final Map survivorControllers = new HashMap<>(); @@ -92,7 +93,8 @@ public class GameplayInteraction { dev.loki.chest.ChestManager chestManager, dev.loki.chest.ChestOpening chestOpening, GateOpening gateOpening, - dev.loki.objective.GeneratorRepair generatorRepair) { + dev.loki.objective.GeneratorRepair generatorRepair, + dev.loki.objective.ComputerRepair computerRepair) { this.gateManager = gateManager; this.hookManager = hookManager; this.hookRescue = hookRescue; @@ -103,6 +105,7 @@ public class GameplayInteraction { this.chestOpening = chestOpening; this.gateOpening = gateOpening; this.generatorRepair = generatorRepair; + this.computerRepair = computerRepair; } public void setAllGensDone(boolean allGensDone) { @@ -253,6 +256,9 @@ public class GameplayInteraction { if (generatorRepair.isMinigameActive(player.getUniqueId())) { generatorRepair.handleMinigameSneak(player); } + if (computerRepair != null && computerRepair.isMinigameActive(player.getUniqueId())) { + computerRepair.handleMinigameSneak(player); + } }); // Generator repair + right‑click for text skill check @@ -275,6 +281,26 @@ public class GameplayInteraction { } }); + // Computer repair + right‑click for text skill check + interactListener.setOnComputerInteract((player, action) -> { + BasePlayer bp = session.getPlayer(player.getUniqueId()); + if (bp == null || bp.isKiller()) return; + if (computerRepair == null) return; + + if (computerRepair.isMinigameActive(player.getUniqueId())) { + computerRepair.handleMinigameClick(player); + return; + } + + var compManager = session.getComputerManager(); + if (compManager == null) return; + double range = session.getConfig().getComputerInteractionRange(); + var computer = compManager.getNearestComputer(player.getLocation(), range); + if (computer != null) { + computerRepair.startRepair(player, computer); + } + }); + // Chest interactListener.setOnChestInteract((player, ignored) -> { BasePlayer bp = session.getPlayer(player.getUniqueId()); @@ -337,6 +363,7 @@ public class GameplayInteraction { interactListener.setOnCarriedShift(null); interactListener.setOnGeneratorSkillCheckSneak(null); interactListener.setOnGeneratorInteract(null); + interactListener.setOnComputerInteract(null); interactListener.setOnGateInteract(null); } } diff --git a/src/main/java/dev/loki/phase/GameplayPhase.java b/src/main/java/dev/loki/phase/GameplayPhase.java index 21c51a0..a7b8e97 100644 --- a/src/main/java/dev/loki/phase/GameplayPhase.java +++ b/src/main/java/dev/loki/phase/GameplayPhase.java @@ -19,6 +19,7 @@ import dev.loki.mdbd; import dev.loki.minigames.GeneratorMinigame; import dev.loki.minigames.generator.GuiRouletteMinigame; import dev.loki.objective.GeneratorManager; +import dev.loki.objective.ComputerManager; import dev.loki.player.BasePlayer; import dev.loki.player.PlayerState; import dev.loki.player.Survivor; @@ -44,9 +45,11 @@ public class GameplayPhase implements Phase { private enum EndgameState { NONE, PREGAME, POSTGAME } private final GeneratorManager generatorManager; + private final ComputerManager computerManager; private int tickCounter; private boolean shouldEnd; private boolean allGensDone; + private boolean allCompsDone; private EndgameState endgameState = EndgameState.NONE; private int endgameTimer; // секунд до смены состояния @@ -69,12 +72,15 @@ public class GameplayPhase implements Phase { private ChestOpening chestOpening; private GeneratorKick generatorKick; private dev.loki.objective.GeneratorRepair generatorRepair; + private dev.loki.objective.ComputerRepair computerRepair; private dev.loki.objective.GeneratorHologram generatorHologram; + private dev.loki.objective.ComputerHologram computerHologram; private dev.loki.hook.HookHologram hookHologram; private dev.loki.chest.ChestHologram chestHologram; - public GameplayPhase(GeneratorManager generatorManager) { + public GameplayPhase(GeneratorManager generatorManager, ComputerManager computerManager) { this.generatorManager = generatorManager; + this.computerManager = computerManager; } // ========================================================================= @@ -88,6 +94,7 @@ public class GameplayPhase implements Phase { tickCounter = 0; shouldEnd = false; allGensDone = false; + allCompsDone = false; endgameState = EndgameState.NONE; endgameTimer = 0; winConditions = new GameplayWinConditions(); @@ -110,22 +117,36 @@ public class GameplayPhase implements Phase { public void tick(GameSession session) { tickCounter++; generatorManager.tick(); + computerManager.tick(); if (generatorRepair != null) generatorRepair.tick(); + if (computerRepair != null) computerRepair.tick(); if (interaction != null) interaction.tickSurvivors(); hookHandler.tick(); if (ui.tickMatchTimer(session)) { shouldEnd = true; } - // Particle effects around generators (every 10 ticks) - if (tickCounter % 10 == 0 && generatorManager != null) { - for (var gen : generatorManager.getAllGenerators()) { - if (gen.isCompleted()) continue; - Location gloc = gen.getLocation().clone().add(0.5, 0.5, 0.5); - gloc.getWorld().spawnParticle(org.bukkit.Particle.ELECTRIC_SPARK, - gloc, 2, 0.8, 0.5, 0.8, 0.01); - gloc.getWorld().spawnParticle(org.bukkit.Particle.END_ROD, - gloc, 1, 0.6, 0.3, 0.6, 0.01); + // Particle effects around generators and computers (every 10 ticks) + if (tickCounter % 10 == 0) { + if (generatorManager != null) { + for (var gen : generatorManager.getAllGenerators()) { + if (gen.isCompleted()) continue; + Location gloc = gen.getLocation().clone().add(0.5, 0.5, 0.5); + gloc.getWorld().spawnParticle(org.bukkit.Particle.ELECTRIC_SPARK, + gloc, 2, 0.8, 0.5, 0.8, 0.01); + gloc.getWorld().spawnParticle(org.bukkit.Particle.END_ROD, + gloc, 1, 0.6, 0.3, 0.6, 0.01); + } + } + if (computerManager != null) { + for (var comp : computerManager.getAllComputers()) { + if (comp.isCompleted()) continue; + Location cloc = comp.getLocation().clone().add(0.5, 0.5, 0.5); + cloc.getWorld().spawnParticle(org.bukkit.Particle.ELECTRIC_SPARK, + cloc, 2, 0.8, 0.5, 0.8, 0.01); + cloc.getWorld().spawnParticle(org.bukkit.Particle.END_ROD, + cloc, 1, 0.6, 0.3, 0.6, 0.01); + } } } @@ -147,7 +168,7 @@ public class GameplayPhase implements Phase { shouldEnd = true; } } - ui.updateSidebar(session, generatorManager); + ui.updateSidebar(session, generatorManager, computerManager); } // Escape check — каждый тик для мгновенной реакции @@ -225,6 +246,7 @@ public class GameplayPhase implements Phase { for (var h : hookManager.getAllHooks()) h.getLocation().setWorld(gameWorld); for (var c : chestManager.getAllChests()) c.getLocation().setWorld(gameWorld); for (var g : generatorManager.getAllGenerators()) g.getLocation().setWorld(gameWorld); + for (var c : computerManager.getAllComputers()) c.getLocation().setWorld(gameWorld); } spawnGameBlocks(plugin, cfg); @@ -232,11 +254,16 @@ public class GameplayPhase implements Phase { generatorKick = new GeneratorKick(plugin, cfg, generatorManager); generatorRepair = new dev.loki.objective.GeneratorRepair(plugin, generatorManager, genMinigame); + computerRepair = new dev.loki.objective.ComputerRepair(plugin, computerManager, genMinigame); // Голограммы ВСЕГДА включены generatorHologram = new dev.loki.objective.GeneratorHologram(plugin, generatorManager); generatorHologram.start(); plugin.getLogger().info("[GameplayPhase] Generator holograms started"); + computerHologram = new dev.loki.objective.ComputerHologram(plugin, computerManager); + computerHologram.start(); + plugin.getLogger().info("[GameplayPhase] Computer holograms started"); + hookHologram = new dev.loki.hook.HookHologram(plugin, hookManager); hookHologram.start(); plugin.getLogger().info("[GameplayPhase] Hook holograms: " + hookManager.getAllHooks().size()); @@ -253,6 +280,13 @@ public class GameplayPhase implements Phase { damageSystem = new GameplayDamageSystem(); damageSystem.init(session, plugin, cfg); + if (generatorRepair != null) { + generatorRepair.setItemUseListener(damageSystem.getItemUseListener()); + } + if (computerRepair != null) { + computerRepair.setItemUseListener(damageSystem.getItemUseListener()); + } + ui = new GameplayUI(); ui.init(session, plugin, cfg); ui.setWinConditions(winConditions); @@ -262,9 +296,10 @@ public class GameplayPhase implements Phase { interaction.setInteractListener(plugin.getInteractListener()); // ВАЖНО: переустановить generatorManager, поскольку он может быть null после exit() plugin.getInteractListener().setGeneratorManager(generatorManager); + plugin.getInteractListener().setComputerManager(computerManager); interaction.setManagers(gateManager, hookManager, hookRescue, hookSabotage, generatorKick, damageSystem, - chestManager, chestOpening, gateOpening, generatorRepair); + chestManager, chestOpening, gateOpening, generatorRepair, computerRepair); } private void initListeners(GameSession session, mdbd plugin) { @@ -304,14 +339,26 @@ public class GameplayPhase implements Phase { } private void checkGeneratorProgress(GameSession session) { - if (allGensDone) return; - if (generatorManager.areAllRequiredCompleted()) { + if (allGensDone && allCompsDone) return; + + boolean gensDone = generatorManager.areAllRequiredCompleted(); + boolean compsDone = computerManager.areAllRequiredCompleted(); + + if (gensDone && !allGensDone) { allGensDone = true; + Bukkit.broadcast(session.getPlugin().getConfigManager().getMessages().get("generator.repair.all-done")); + } + if (compsDone && !allCompsDone) { + allCompsDone = true; + Bukkit.broadcast(session.getPlugin().getConfigManager().getMessages().get("computer.repair.all-done")); + } + + if (gensDone && compsDone) { interaction.setAllGensDone(true); gateManager.activateEndgame(); endgameState = EndgameState.PREGAME; endgameTimer = session.getConfig().getPregameSeconds(); - Bukkit.broadcast(session.getPlugin().getConfigManager().getMessages().get("generator.repair.all-done")); + Bukkit.broadcast(session.getPlugin().getConfigManager().getMessages().get("generator.repair.all-objectives-done")); for (BasePlayer bp : session.getPlayers().values()) { Player p = bp.getPlayer(); if (p != null) p.playSound(p.getLocation(), Sound.ENTITY_FIREWORK_ROCKET_BLAST, 1.0f, 1.0f); @@ -419,6 +466,17 @@ public class GameplayPhase implements Phase { } plugin.getLogger().info("[GameplayPhase] Spawned blocks for " + hookManager.getAllHooks().size() + " hooks"); + // Спавн блоков на местах компьютеров + Material compMat = Material.matchMaterial(cfg.getComputerBlock()); + if (compMat == null) compMat = Material.LECTERN; + for (var comp : computerManager.getAllComputers()) { + Location loc = comp.getLocation(); + if (loc.getWorld() == null) continue; + Block b = loc.getBlock(); + if (b.getType() != compMat) b.setType(compMat, false); + } + plugin.getLogger().info("[GameplayPhase] Spawned blocks for " + computerManager.getTotalCount() + " computers"); + // Спавн структуры ворот (рамка + кнопка + Hopper для взаимодействия) for (ExitGate gate : gateManager.getAllGates()) { gate.spawnGateStructure(); @@ -458,7 +516,9 @@ public class GameplayPhase implements Phase { if (chestOpening != null) chestOpening.cancelAll(); if (chestManager != null) chestManager.resetAllChests(); if (generatorKick != null) generatorKick.shutdown(); + if (computerRepair != null) computerRepair.shutdown(); if (generatorHologram != null) generatorHologram.stop(); + if (computerHologram != null) computerHologram.stop(); if (hookHologram != null) hookHologram.stop(); if (titleUI != null) titleUI.clearSkillChecks(); if (hookStruggle != null) hookStruggle.clear(); @@ -471,5 +531,6 @@ public class GameplayPhase implements Phase { } } session.getPlugin().getInteractListener().setGeneratorManager(null); + session.getPlugin().getInteractListener().setComputerManager(null); } } \ No newline at end of file diff --git a/src/main/java/dev/loki/phase/GameplayUI.java b/src/main/java/dev/loki/phase/GameplayUI.java index ba19952..74cde24 100644 --- a/src/main/java/dev/loki/phase/GameplayUI.java +++ b/src/main/java/dev/loki/phase/GameplayUI.java @@ -4,6 +4,7 @@ import dev.loki.config.GameConfig; import dev.loki.core.GameSession; import dev.loki.mdbd; import dev.loki.objective.GeneratorManager; +import dev.loki.objective.ComputerManager; import dev.loki.player.BasePlayer; import dev.loki.player.Killer; import dev.loki.player.Survivor; @@ -114,11 +115,11 @@ public class GameplayUI { /** * Update sidebar stats. */ - public void updateSidebar(GameSession session, GeneratorManager generatorManager) { + public void updateSidebar(GameSession session, GeneratorManager generatorManager, ComputerManager computerManager) { if (sidebar == null) return; for (BasePlayer bp : session.getPlayers().values()) { Player p = bp.getPlayer(); - if (p != null && p.isOnline()) sidebar.updateGameStats(p, session, generatorManager); + if (p != null && p.isOnline()) sidebar.updateGameStats(p, session, generatorManager, computerManager); } } diff --git a/src/main/java/dev/loki/ui/Sidebar.java b/src/main/java/dev/loki/ui/Sidebar.java index fd3eb62..506155c 100644 --- a/src/main/java/dev/loki/ui/Sidebar.java +++ b/src/main/java/dev/loki/ui/Sidebar.java @@ -3,6 +3,7 @@ package dev.loki.ui; import dev.loki.config.GameConfig; import dev.loki.core.GameSession; import dev.loki.objective.GeneratorManager; +import dev.loki.objective.ComputerManager; import dev.loki.player.BasePlayer; import dev.loki.player.PlayerState; import dev.loki.player.Survivor; @@ -138,6 +139,10 @@ public class Sidebar { } public void updateGameStats(Player player, GameSession session, GeneratorManager generatorManager) { + updateGameStats(player, session, generatorManager, null); + } + + public void updateGameStats(Player player, GameSession session, GeneratorManager generatorManager, ComputerManager computerManager) { Scoreboard board = scoreboards.get(player.getUniqueId()); if (board == null) return; @@ -159,13 +164,21 @@ public class Sidebar { setScore(objective, "§8─────────────────", line--); } - // Generator progress — use actual placed count, not config max + // Generator progress int completedGens = generatorManager != null ? generatorManager.getCompletedCount() : 0; int totalGens = generatorManager != null ? generatorManager.getTotalCount() : cfg.getGeneratorRequired(); setScore(objective, "§eГенераторы:", line--); String genBar = buildGenBar(completedGens, totalGens); setScore(objective, " §f" + completedGens + "/" + totalGens + " " + genBar, line--); + + // Computer progress + int completedComps = computerManager != null ? computerManager.getCompletedCount() : 0; + int totalComps = computerManager != null ? computerManager.getTotalCount() : cfg.getComputerRequired(); + + setScore(objective, "§bКомпьютеры:", line--); + String compBar = buildGenBar(completedComps, totalComps); + setScore(objective, " §f" + completedComps + "/" + totalComps + " " + compBar, line--); setScore(objective, " ", line--); // Survivor list with hearts and colors diff --git a/src/main/resources/game.yml b/src/main/resources/game.yml index 540012c..59f58d7 100644 --- a/src/main/resources/game.yml +++ b/src/main/resources/game.yml @@ -35,12 +35,6 @@ generators: # Время починки одного генератора (секунд) [90 сек по ТЗ] repair-seconds: 90 - # Скорость отката без чинильщика (%/сек) - regression-rate: 0.25 - - # Скорость отката после удара (%/сек) - kick-regression-rate: 2.5 - # Потеря прогресса после удара (%) kick-regression-percent: 20.0 @@ -56,6 +50,20 @@ generators: # Расстояние для взаимодействия с генератором (блоков) interaction-range: 3.0 +# Компьютеры (аналог генераторов — нужно чинить и их тоже для победы) +computers: + # Всего компьютеров на карте + total-count: 2 + + # Сколько нужно починить (должно быть = total-count для победы) + required-count: 2 + + # Время починки одного компьютера (секунд) + repair-seconds: 90 + + # Расстояние для взаимодействия с компьютером (блоков) + interaction-range: 3.0 + # Крюки hooks: # Длительность Фазы 1 (секунд) @@ -213,6 +221,8 @@ scoreboard: blocks: # Блок на месте генератора generator: "BLAST_FURNACE" + # Блок на месте компьютера + computer: "LECTERN" # Блок на месте сундука chest: "CHEST" # Блок на месте крюка @@ -221,13 +231,17 @@ blocks: # Лут сундуков loot: medkit: - weight: 55 + weight: 25 min-charges: 12 max-charges: 16 - flashlight: - weight: 45 - min-charges: 6 - max-charges: 8 + bandage: + weight: 25 + full-medkit: + weight: 10 + soda: + weight: 20 + wrench: + weight: 20 # Custom Model Data для ресурспака # Задайте числа соответствующие overrides в вашем ресурспаке. @@ -236,6 +250,10 @@ items: model-data: medkit: 1001 flashlight: 1002 + bandage: 1004 + fullmedkit: 1005 + soda: 1006 + wrench: 1007 # Голограммы holograms: @@ -243,6 +261,9 @@ holograms: generator: enabled: true height-offset: -1.0 + computer: + enabled: true + height-offset: -1.0 hook: enabled: true height-offset: 0.0 diff --git a/src/main/resources/locations.yml b/src/main/resources/locations.yml index feefcc5..0e5bcbf 100644 --- a/src/main/resources/locations.yml +++ b/src/main/resources/locations.yml @@ -15,6 +15,9 @@ lobby: # Генераторы — настраиваются через /dbdadmin create generator # и сохраняются в data/generators.yml +# Компьютеры — настраиваются через /dbdsetup set computer +# и сохраняются в data/computers.yml + # Крюки (обычно 4-6) hooks: [] # Пример: diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index d518b13..bc2f9e1 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -110,6 +110,7 @@ setup: hook-placed: "%setup-prefix%&aКрюк установлен: %s" chest-placed: "%setup-prefix%&aСундук добавлен: %s" generator-placed: "%setup-prefix%&aГенератор добавлен: %s" + computer-placed: "%setup-prefix%&bКомпьютер установлен: %s" killer-spawn-exists: "%setup-prefix%&cСпавн киллера уже установлен! Используй /dbdsetup clear-spawns для сброса." killer-spawn-placed: "&#FF4444Спавн киллера установлен: %s" survivor-spawn-limit: "%setup-prefix%&cДостигнут лимит спавнов выживших (4)! Используй /dbdsetup clear-spawns для сброса." @@ -155,6 +156,21 @@ role: killer: "%prefix%&4Вы - Маньяк! Поймайте всех выживших!" survivor: "%prefix%&bВы - Выживший! Почините генераторы и сбегите!" +# ── Компьютеры ──────────────────────────────── + +computer: + repair: + start: "&bВы начали чинить компьютер..." + stop: "&eВы остановились." + complete: "&a✔ Компьютер активирован!" + broadcast: "&bКомпьютер починен! &7(%d/%d)" + cannot: "&cКомпьютер не может быть починен!" + busy: "&cКто-то уже чинит этот компьютер!" + actionbar: "&7Починка компьютера: %s" + skillcheck-success: "&a✓ Успех! +%d%%" + skillcheck-fail: "&c✗ Промах! -%d%%. Чини дальше." + all-done: "%prefix%&bВсе компьютеры починены!" + # ── Генераторы ───────────────────────────────── generator: @@ -169,7 +185,8 @@ generator: skillcheck-title: "&eПроверка реакции! %s" skillcheck-success: "&a✓ Успех! +%d%%" skillcheck-fail: "&c✗ Промах! -%d%%. Чини дальше." - all-done: "%prefix%&aВсе генераторы починены! Открывайте ворота!" + all-done: "%prefix%&aВсе генераторы починены!" + all-objectives-done: "%prefix%&6Все генераторы и компьютеры починены! Ворота открываются!" kicked: begin: "%prefix%&cДержите Shift для разрушения генератора..." cooldown: "%prefix%&cКулдаун удара: %d сек" @@ -205,6 +222,11 @@ survivor: done: "%prefix%&a✔ Вы вылечились!" cancelled: "%prefix%&eЛечение прервано." depleted: "&cМедкит закончился!" + item: + bandage: "%prefix%&aВы наложили бинт. Здоровье регенерирует!" + fullmedkit: "%prefix%&aАптечка использована. Здоровье полностью восстановлено!" + soda: "%prefix%&eСодовая выпита. Скорость увеличена!" + wrench: "%prefix%&aГаечный ключ использован. Починка ускорена!" # ── Крюки ────────────────────────────────────── @@ -301,6 +323,7 @@ usage: setup-hook: "&6/dbdsetup set hook - Установить крюк (ломай блок)" setup-chest: "&6/dbdsetup set chest - Установить сундук" setup-generator: "&6/dbdsetup set generator - Установить генератор" + setup-computer: "&6/dbdsetup set computer - Установить компьютер" setup-killer-spawn: "&6/dbdsetup set killer-spawn - Спавн киллера (только 1)" setup-survivor-spawn: "&6/dbdsetup set survivor-spawn - Спавн выжившего (до 4)" setup-gate: "&6/dbdsetup set gate A|B - Установить ворота (из точек ванда)" From 670d59969bb8156b6f412c7064a25db1e085cbcc Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Sun, 21 Jun 2026 13:59:50 +0200 Subject: [PATCH 10/10] chore: commit remaining changes (items, damage, readme) --- README.md | 26 +++--- src/main/java/dev/loki/item/ChestLoot.java | 56 +++++++------ src/main/java/dev/loki/item/DBDItems.java | 76 ++++++++++++++++- src/main/java/dev/loki/item/ItemType.java | 6 +- .../java/dev/loki/item/ItemUseListener.java | 82 +++++++++++++------ .../dev/loki/objective/GeneratorRepair.java | 13 ++- .../dev/loki/phase/GameplayDamageSystem.java | 4 + 7 files changed, 198 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 874a1ce..5cc0c97 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ -# Mdbd — Dead by Daylight в Minecraft +# Mdbd - Dead by Daylight в Minecraft Плагин для Paper 1.21.5, реализующий мини-игру Dead by Daylight (4v1) на Minecraft-сервере. ## Особенности -- **4 выживших vs 1 маньяк** — полноценный геймплей DBD в Minecraft -- **Генераторы** — 7 на карте, нужно починить 5. Прогресс сохраняется, Skill Check мини-игра (GUI) -- **Крюки** — 3 стадии, спасение, борьба, жертвоприношение -- **Выходные ворота** — открытие через рубильник, эндгейм коллапс -- **Паллеты** — ставятся через `/dbdsetup`, ломаются маньяком -- **Медкиты и фонарики** — из сундуков, с механиками лечения и ослепления -- **Система урона** — Healthy → Injured → Downed → Hooked → Dead -- **Переноска** — маньяк подбирает и носит выживших до крюка -- **Terror Radius** — звук сердцебиения для выживших рядом с маньяком -- **Skill Check GUI** — мини-игра с зелёными блоками при починке генератора -- **Лобби** — ожидание игроков, автоматический старт, возврат после игры -- **Scoreboard, BossBar, ActionBar** — полноценный интерфейс +- **4 выживших vs 1 маньяк** - полноценный геймплей DBD в Minecraft +- **Генераторы** - 7 на карте, нужно починить 5. Прогресс сохраняется, Skill Check мини-игра (GUI) +- **Крюки** - 3 стадии, спасение, борьба, жертвоприношение +- **Выходные ворота** - открытие через рубильник, эндгейм коллапс +- **Паллеты** - ставятся через `/dbdsetup`, ломаются маньяком +- **Медкиты и фонарики** - из сундуков, с механиками лечения и ослепления +- **Система урона** - Healthy → Injured → Downed → Hooked → Dead +- **Переноска** - маньяк подбирает и носит выживших до крюка +- **Terror Radius** - звук сердцебиения для выживших рядом с маньяком +- **Skill Check GUI** - мини-игра с зелёными блоками при починке генератора +- **Лобби** - ожидание игроков, автоматический старт, возврат после игры +- **Scoreboard, BossBar, ActionBar** - полноценный интерфейс ## Команды diff --git a/src/main/java/dev/loki/item/ChestLoot.java b/src/main/java/dev/loki/item/ChestLoot.java index f77c926..3489672 100644 --- a/src/main/java/dev/loki/item/ChestLoot.java +++ b/src/main/java/dev/loki/item/ChestLoot.java @@ -5,56 +5,66 @@ import org.bukkit.inventory.ItemStack; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; -/** - * Генератор случайного лута для сундуков. - * Может выдать: Медкит (разное количество зарядов), Набор для срезания. - */ public class ChestLoot { private final Random random; - // Веса для разных типов лута (из конфига game.yml: loot.*) private final int medkitWeight; + private final int bandageWeight; + private final int fullMedkitWeight; + private final int sodaWeight; + private final int wrenchWeight; + private final int medkitMinCharges; private final int medkitMaxCharges; - private final int hookCutterWeight; - /** Config-aware constructor. */ public ChestLoot(dev.loki.config.GameConfig config) { this.random = ThreadLocalRandom.current(); var cfg = config.getConfig(); - this.medkitWeight = cfg.getInt("loot.medkit.weight", 60); - this.medkitMinCharges = cfg.getInt("loot.medkit.min-charges", 12); - this.medkitMaxCharges = cfg.getInt("loot.medkit.max-charges", 16); - this.hookCutterWeight = cfg.getInt("loot.hook-cutter.weight", 40); + this.medkitWeight = cfg.getInt("loot.medkit.weight", 30); + this.bandageWeight = cfg.getInt("loot.bandage.weight", 20); + this.fullMedkitWeight = cfg.getInt("loot.full-medkit.weight", 10); + this.sodaWeight = cfg.getInt("loot.soda.weight", 20); + this.wrenchWeight = cfg.getInt("loot.wrench.weight", 20); + this.medkitMinCharges = cfg.getInt("loot.medkit.min-charges", 12); + this.medkitMaxCharges = cfg.getInt("loot.medkit.max-charges", 16); } - /** Fallback — hardcoded defaults. */ public ChestLoot() { this.random = ThreadLocalRandom.current(); - this.medkitWeight = 60; + this.medkitWeight = 30; + this.bandageWeight = 20; + this.fullMedkitWeight = 10; + this.sodaWeight = 20; + this.wrenchWeight = 20; this.medkitMinCharges = 12; this.medkitMaxCharges = 16; - this.hookCutterWeight = 40; } - /** - * Бросает кубик и возвращает случайный предмет. - * Никогда не возвращает null. - */ public ItemStack rollLoot() { - int total = medkitWeight + hookCutterWeight; + int total = medkitWeight + bandageWeight + fullMedkitWeight + sodaWeight + wrenchWeight; if (total <= 0) { return DBDItems.medkit(12); } int roll = random.nextInt(total); + int cumulative = 0; - if (roll < medkitWeight) { + cumulative += medkitWeight; + if (roll < cumulative) { int charges = medkitMinCharges + random.nextInt(Math.max(1, medkitMaxCharges - medkitMinCharges + 1)); return DBDItems.medkit(charges); - } else { - return DBDItems.hookCutter(); } + + cumulative += bandageWeight; + if (roll < cumulative) return DBDItems.bandage(); + + cumulative += fullMedkitWeight; + if (roll < cumulative) return DBDItems.fullMedkit(); + + cumulative += sodaWeight; + if (roll < cumulative) return DBDItems.soda(); + + return DBDItems.wrench(); } -} +} \ No newline at end of file diff --git a/src/main/java/dev/loki/item/DBDItems.java b/src/main/java/dev/loki/item/DBDItems.java index ffe9b15..aa55252 100644 --- a/src/main/java/dev/loki/item/DBDItems.java +++ b/src/main/java/dev/loki/item/DBDItems.java @@ -20,14 +20,22 @@ public final class DBDItems { public static final NamespacedKey KEY_CHARGES = new NamespacedKey("mdbd", "charges"); // Custom Model Data IDs (соответствуют ресурспаку) - // Переопределяются через game.yml: items.model-data.medkit / hookcutter + // Переопределяются через game.yml: items.model-data.* private static int CMD_MEDKIT = 1001; private static int CMD_HOOKCUTTER = 1003; + private static int CMD_BANDAGE = 1004; + private static int CMD_FULLMEDKIT = 1005; + private static int CMD_SODA = 1006; + private static int CMD_WRENCH = 1007; /** Вызывать при загрузке плагина / reload, чтобы подхватить значения из конфига. */ public static void loadModelData(org.bukkit.configuration.file.FileConfiguration cfg) { CMD_MEDKIT = cfg.getInt("items.model-data.medkit", 1001); CMD_HOOKCUTTER = cfg.getInt("items.model-data.hookcutter", 1003); + CMD_BANDAGE = cfg.getInt("items.model-data.bandage", 1004); + CMD_FULLMEDKIT = cfg.getInt("items.model-data.fullmedkit", 1005); + CMD_SODA = cfg.getInt("items.model-data.soda", 1006); + CMD_WRENCH = cfg.getInt("items.model-data.wrench", 1007); } private DBDItems() {} @@ -70,6 +78,58 @@ public final class DBDItems { ); } + public static ItemStack bandage() { + return build( + Material.PAPER, CMD_BANDAGE, + "<#FFA07A>Бинт", + 1, 1, + List.of( + "Регенерирует здоровье в течение 30 секунд.", + "ПКМ — наложить бинт" + ), + "BANDAGE" + ); + } + + public static ItemStack fullMedkit() { + return build( + Material.PAPER, CMD_FULLMEDKIT, + "<#FF1493>Аптечка", + 1, 1, + List.of( + "Полностью восстанавливает здоровье.", + "ПКМ — воспользоваться аптечкой" + ), + "FULL_MEDKIT" + ); + } + + public static ItemStack soda() { + return build( + Material.PAPER, CMD_SODA, + "<#FFD700>Содовая", + 1, 1, + List.of( + "Даёт буст к скорости на 10 секунд.", + "ПКМ — выпить" + ), + "SODA" + ); + } + + public static ItemStack wrench() { + return build( + Material.IRON_PICKAXE, CMD_WRENCH, + "<#A0A0A0>Гаечный ключ", + 1, 1, + List.of( + "Даёт буст к починке на 10 секунд.", + "ПКМ — использовать" + ), + "WRENCH" + ); + } + // ── Helpers ─────────────────────────────────────────────────────────────── private static ItemStack build(Material mat, int customModelData, String name, @@ -126,11 +186,19 @@ public final class DBDItems { if (type == null) return item; return switch (type) { case "MEDKIT" -> medkit(newCharges); + case "BANDAGE" -> bandage(); + case "FULL_MEDKIT" -> fullMedkit(); + case "SODA" -> soda(); + case "WRENCH" -> wrench(); default -> item; }; } - public static boolean isMedkit(ItemStack item) { return "MEDKIT".equals(getType(item)); } - public static boolean isHookCutter(ItemStack item) { return "HOOK_CUTTER".equals(getType(item)); } - public static boolean isDBDItem(ItemStack item) { return getType(item) != null; } + public static boolean isMedkit(ItemStack item) { return "MEDKIT".equals(getType(item)); } + public static boolean isHookCutter(ItemStack item) { return "HOOK_CUTTER".equals(getType(item)); } + public static boolean isBandage(ItemStack item) { return "BANDAGE".equals(getType(item)); } + public static boolean isFullMedkit(ItemStack item) { return "FULL_MEDKIT".equals(getType(item)); } + public static boolean isSoda(ItemStack item) { return "SODA".equals(getType(item)); } + public static boolean isWrench(ItemStack item) { return "WRENCH".equals(getType(item)); } + public static boolean isDBDItem(ItemStack item) { return getType(item) != null; } } diff --git a/src/main/java/dev/loki/item/ItemType.java b/src/main/java/dev/loki/item/ItemType.java index 1257c47..7bdbcbe 100644 --- a/src/main/java/dev/loki/item/ItemType.java +++ b/src/main/java/dev/loki/item/ItemType.java @@ -2,7 +2,11 @@ package dev.loki.item; public enum ItemType { MEDKIT("Медкит", "Лечит одно состояние здоровья", 16), - HOOK_CUTTER("Крюкорез", "Срезает выжившего с крюка", 1); + HOOK_CUTTER("Крюкорез", "Срезает выжившего с крюка", 1), + BANDAGE("Бинт", "Регенерирует здоровье в течение 30 секунд", 1), + FULL_MEDKIT("Аптечка", "Полностью восстанавливает здоровье", 1), + SODA("Содовая", "Даёт буст к скорости на 10 секунд", 1), + WRENCH("Гаечный ключ", "Даёт буст к починке на 10 секунд", 1); private final String displayName; private final String description; diff --git a/src/main/java/dev/loki/item/ItemUseListener.java b/src/main/java/dev/loki/item/ItemUseListener.java index 18dcfb4..27b12d3 100644 --- a/src/main/java/dev/loki/item/ItemUseListener.java +++ b/src/main/java/dev/loki/item/ItemUseListener.java @@ -18,6 +18,8 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; @@ -25,16 +27,15 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -/** - * Handles right-click usage of DBD custom items (Medkit) during gameplay. - */ public class ItemUseListener implements Listener { private final Plugin plugin; private final GameSession session; private final Map activeHeals = new HashMap<>(); - private static final int MEDKIT_TICKS = 160; // 8 seconds + private static final int MEDKIT_TICKS = 160; + + private final Map repairBoostExpiry = new HashMap<>(); public ItemUseListener(Plugin plugin, GameSession session) { this.plugin = plugin; @@ -49,6 +50,17 @@ public class ItemUseListener implements Listener { HandlerList.unregisterAll(this); activeHeals.values().forEach(BukkitTask::cancel); activeHeals.clear(); + repairBoostExpiry.clear(); + } + + public boolean hasRepairBoost(UUID playerId) { + Long expiry = repairBoostExpiry.get(playerId); + if (expiry == null) return false; + if (System.currentTimeMillis() > expiry) { + repairBoostExpiry.remove(playerId); + return false; + } + return true; } @EventHandler(priority = EventPriority.HIGH) @@ -69,22 +81,24 @@ public class ItemUseListener implements Listener { event.setCancelled(true); String type = DBDItems.getType(hand); - if ("MEDKIT".equals(type)) { - // Медкит: нужен Shift (sneaking) + стоять на месте - if (!player.isSneaking()) { - player.sendMessage(mdbd.getInstance().getConfigManager().getMessages().get("survivor.medkit.need-shift")); - return; + switch (type) { + case "MEDKIT" -> { + if (!player.isSneaking()) { + player.sendMessage(mdbd.getInstance().getConfigManager().getMessages().get("survivor.medkit.need-shift")); + return; + } + useMedkit(player, (Survivor) bp, hand); } - useMedkit(player, (Survivor) bp, hand); + case "BANDAGE" -> useBandage(player, (Survivor) bp); + case "FULL_MEDKIT" -> useFullMedkit(player, (Survivor) bp); + case "SODA" -> useSoda(player); + case "WRENCH" -> useWrench(player); } } - // ── Медкит ──────────────────────────────────────────────────────────────── - private void useMedkit(Player player, Survivor survivor, ItemStack item) { UUID uuid = player.getUniqueId(); - // Повторный Shift+ПКМ — отмена лечения if (activeHeals.containsKey(uuid)) { cancelHeal(player); return; @@ -104,25 +118,21 @@ public class ItemUseListener implements Listener { player.sendMessage(mdbd.getInstance().getConfigManager().getMessages().get("survivor.medkit.start")); - // Запоминаем позицию для проверки движения final Location startLoc = player.getLocation().clone(); BukkitTask task = new BukkitRunnable() { int ticks = 0; - final int healTicks = MEDKIT_TICKS; @Override public void run() { if (!player.isOnline()) { cancelHeal(player); cancel(); return; } if (survivor.getState() != PlayerState.INJURED) { cancelHeal(player); cancel(); return; } - // Прерывание при движении или отпускании Shift if (!player.isSneaking()) { cancelHeal(player); cancel(); return; } - // Проверка движения (больше 0.5 блока от старта) if (player.getLocation().distanceSquared(startLoc) > 0.25) { cancelHeal(player); cancel(); @@ -131,10 +141,9 @@ public class ItemUseListener implements Listener { ticks++; - // Прогресс в action bar - int filled = (int) (8.0 * ticks / healTicks); + int filled = (int) (8.0 * ticks / MEDKIT_TICKS); int empty = 8 - filled; - int pct = (int) (100.0 * ticks / healTicks); + int pct = (int) (100.0 * ticks / MEDKIT_TICKS); String barStr = "█".repeat(filled) + "░".repeat(empty); player.sendActionBar(mdbd.getInstance().getConfigManager().getMessages().get("survivor.medkit.actionbar", barStr, pct)); @@ -142,12 +151,11 @@ public class ItemUseListener implements Listener { player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_HURT, 0.15f, 1.8f); } - if (ticks >= healTicks) { + if (ticks >= MEDKIT_TICKS) { survivor.setState(PlayerState.HEALTHY); player.sendMessage(mdbd.getInstance().getConfigManager().getMessages().get("survivor.medkit.done")); player.sendActionBar(Component.empty()); player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.6f, 1.5f); - // Полностью убираем медкит (один раз использован) player.getInventory().setItemInMainHand(null); activeHeals.remove(uuid); cancel(); @@ -167,4 +175,32 @@ public class ItemUseListener implements Listener { } } -} + private void useBandage(Player player, Survivor survivor) { + player.getInventory().setItemInMainHand(null); + player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 30 * 20, 0)); + player.sendMessage(mdbd.getInstance().getConfigManager().getMessages().get("survivor.item.bandage")); + player.playSound(player.getLocation(), Sound.ENTITY_WITCH_DRINK, 0.6f, 1.2f); + } + + private void useFullMedkit(Player player, Survivor survivor) { + player.getInventory().setItemInMainHand(null); + survivor.setState(PlayerState.HEALTHY); + player.sendMessage(mdbd.getInstance().getConfigManager().getMessages().get("survivor.item.fullmedkit")); + player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.8f, 1.5f); + } + + private void useSoda(Player player) { + player.getInventory().setItemInMainHand(null); + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 10 * 20, 1)); + player.sendMessage(mdbd.getInstance().getConfigManager().getMessages().get("survivor.item.soda")); + player.playSound(player.getLocation(), Sound.ENTITY_GENERIC_DRINK, 0.6f, 1.0f); + } + + private void useWrench(Player player) { + player.getInventory().setItemInMainHand(null); + player.addPotionEffect(new PotionEffect(PotionEffectType.HASTE, 10 * 20, 2)); + repairBoostExpiry.put(player.getUniqueId(), System.currentTimeMillis() + 10_000); + player.sendMessage(mdbd.getInstance().getConfigManager().getMessages().get("survivor.item.wrench")); + player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_USE, 0.4f, 1.5f); + } +} \ No newline at end of file diff --git a/src/main/java/dev/loki/objective/GeneratorRepair.java b/src/main/java/dev/loki/objective/GeneratorRepair.java index 49cd7c7..de3ef9a 100644 --- a/src/main/java/dev/loki/objective/GeneratorRepair.java +++ b/src/main/java/dev/loki/objective/GeneratorRepair.java @@ -23,9 +23,16 @@ public class GeneratorRepair { private final Map compassTaskIds = new HashMap<>(); private final Map compassPrevItems = new HashMap<>(); + private dev.loki.item.ItemUseListener itemUseListener; + private static final double REPAIR_PER_TICK = 100.0 / 1600.0; + private static final double REPAIR_BOOST_MULTIPLIER = 2.0; private static final double REPAIR_RANGE = 3.0; + public void setItemUseListener(dev.loki.item.ItemUseListener listener) { + this.itemUseListener = listener; + } + public GeneratorRepair(mdbd plugin, GeneratorManager manager, GeneratorMinigame minigame) { this.plugin = plugin; this.manager = manager; @@ -123,7 +130,11 @@ public class GeneratorRepair { return true; } - generator.addProgress(REPAIR_PER_TICK); + double rate = REPAIR_PER_TICK; + if (itemUseListener != null && itemUseListener.hasRepairBoost(player.getUniqueId())) { + rate *= REPAIR_BOOST_MULTIPLIER; + } + generator.addProgress(rate); showProgressBar(player, session); if (generator.isCompleted()) { diff --git a/src/main/java/dev/loki/phase/GameplayDamageSystem.java b/src/main/java/dev/loki/phase/GameplayDamageSystem.java index 0ff4519..9c9bbe4 100644 --- a/src/main/java/dev/loki/phase/GameplayDamageSystem.java +++ b/src/main/java/dev/loki/phase/GameplayDamageSystem.java @@ -138,6 +138,10 @@ public class GameplayDamageSystem { return playerManager; } + public ItemUseListener getItemUseListener() { + return itemUseListener; + } + /** * Clear all damage system resources. */

C8PYaW5ATi)nw*!wZq1<@XX17CmpfqKFXW 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 diff --git a/bin/main/dev/loki/hook/HookStage.class b/bin/main/dev/loki/hook/HookStage.class deleted file mode 100644 index b8af002cf98b7143d37de16b984dfb399e573ffb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1730 zcmaJ=ZBrUo6n?I|uz(w-m_j6KY)dR`jA+u>7l;)J1S0B8*XS^Q$gHr%jmTzJaOzL# zFL0*Q4;I_T>5J1({m>uP_MBw{OsBdtd(WPG&&%^X_v~MP|8fN&hl+v`fmq!$>XATD&*i@= z7t8sAz<9mm7;VdL>1NGt)sF>4S>S#`-z{(FORu(bYn4KRiY6FMg3%=UXaq*~D0sB6 z`Enz%ldHTe=mPP*8!!a2wWigw+A9K5GPNTh=k2-~fG-4r+bZ5iRKTD0LSo6vfU4eh ztX3maE~j>a6nsa85B>lYcJ8WB*a@&Rqapx5f6c16g)!n-v0CP4=V;$_wvGL!DG;gH zHKVy>I2QZvW(X1zjNraN^#2<7`hKh;h!6p9A6O(-q+zz7{Z~PvMzY8)^P4tdOQxJ1dZ;?cIsBkXbRk-yRRK?7;ilE{u86wF{%3$<=jyGQ+%%A zGlB4sil@hI^GL-Ppos_?j$@qG>^G+Z+A!s<{nuu#ohc8=|89%qCulB!t*-?h4ySon zbQ50*U#iGrRp7~RX1-}0A7_Tz^-B$)^Q>q1TGv=Hm8E*7;uAbkP^7UN1a8`Tr*=@Z z%x1mdIJToe6$t5e$Ele`i?4sIKf()~#(#v>Xc_H}Lx&HBU~tduwF<9fR+k8cL_e;7 zb&}^1AWNg@TAD&SiSWDt;TH^=Y@BD3_7$4aafB)VJ@OpN=BM~8L^TqT!r8Z&xIoNx zCuPr#yY7@vau28dzf-W(MNF^CUBvaOuZwB@0{4EPN+bAy)(B);W$NU^4B?q4v>&>s z96`UE*S|#j9I0v#rrzQsZTct74XTW}97B{p>aySpQOc)yBwd#L#XKddmxAV1O_LQA z<J!ACB&QV3$%~hGsQrw^h409rCqXaobNf5=&Jgu8 zs6_n?ep=6IPjbmeT~Q}6i`$qZvhxHwjftVYi(cQyloNzJ>+`KCR6NLI<-u5{B7DQq zF78#=CGD!3W!X2RyO&s==VrsCL|@$?jrmirhUQTTMTB;Vl|LY^%?k%eVb+bO;#*fw z;At1R>YtF$cQ28@`Yp7s5l@oDzjX$Amz)?m@;fI^j<4rbFOWN@B4JEo3I$A)4k@x4 p9%GqoPp95}3;GG4fL{a^CvN|OKp diff --git a/bin/main/dev/loki/hook/HookStruggle.class b/bin/main/dev/loki/hook/HookStruggle.class deleted file mode 100644 index 070363756f1e54f167cd1485bca6bed361aae43e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5641 zcmbVQ33L`~QqIBQKnu9?p^f{Q3XA`|f@3 z{XabTpOX&&*o?zXHYQV6am-AO7K>x4?fl8PPPtI93>8rY%?I^KJ!R>3A=N*0 z(8#+A7ED;>f@v#g>aA`bA08S`D^Ok2wT!{6f|lT2*-Q<1(_FEr^XBKSTEjxySEwyhqg&qe7vpwnFqEko>mB+?RH&x1y8pCDFa8g_3gm94V zrorZl%iT_~;20%(y*OluUT514qR!f`Q7{~7sik5`OgfXgHDKmN5Q+#mH*oFXwr#yz z_wUW_>gnIRe;}LLnPb42qFr)z+ufsEWuuPNFDHeYOxtw36`U6jc#<3jk0II;dlW=7 z#bF}`1!rnlj#dSk|7mMrFJH7r%tC6LK5h^ahiPH9sn@iPUFGp1!x_+rEONfIx0u(h zJ-TCxXMZy4j+zW~RbXybx};;M!)gI;je@#(Vow9Xo}-~23&d!>1{DicoU33-Ao+H^ zG)e(t*nrhyRYF4pVq(;;VG&|6bRwnV{BWYq3Pi&N*r;Gx!Eh_NTMTpz<_*r8!3dRdx+VJ5!eh}DU3^?B3jM(o0F75x-B zRGQvP4Nt1i-9!W3htD;xbB zt%zsCCMvyA!NQWC&n(pWiDwrRIw@Eltf>menv0fYA~$=$<(VMUm~UJXs$gxH$~l=) zF`-~_knCbVB`LYZiArx!&=yLZnaPpZBgl0%lrhO};TYq^Np{6^=ioO?g-@`Gn-#1+ zO|l628gUbzrs3(LQ7*{qcHXeazU!C;9yGZz)3P$7Mt)56fM;sB70>c2Z@26mY+SV! zW7s@&4>6-eUt!7~#&cCXhm9kIqGpYT+weR}W|sPGi``%LNY=T67if4YoETn&m#BC# zJ4&_pR8`XOQoM}E28%dTb{raJpDfVESwuB^xqO*!z$@@76|Yoq#ym?jyc(}zrsW1U zZ`->6LIth!8e2-Bw`+JEUQhP)eBPK~`VWQ_tzxYR9xC`*YKKy7q-^J1vuLL>Jh98H zU7l!NxI@Dm@J8lTX|#A#AdZ4`O#QwMZT3>q*^Ofw?!kvd!w`ox z4JcR>(r%7jq970BxP~d55cmvtyP;d|D4oW81eM`)zd{pd{elg;NP@St`n+Z6jv(>F z8a{#tD1>ZoyxW|~1P=N}rf6Bb?J^x$QXj)7RD7ImYp(YiK8a5W&Uq!&-6ADjQDZ6V z&(qE+d{)J0SXY6a%3BSe!-EXTHg0A*FRxe#cWSZ!Aq`&;#jB3$rCnSqBKeYrlcJR@ zwDj?zVSW7tqLja?;ThNzOfoAjn9Xx=3z3MVw=KmYIkM#?)KZy6DsJ831gv;b5X%+IPTsi26qnB>+e059=L=B0 zzjLiyavgo5&u~YJ!=)I0il3|a8LyWCY}1}Bjv1+5$pIJYBYK`{9MbR${E}Cl@nA~9 zL*Z`j@AQms*X?1;D6Q`$j`BqKfM$)Db|E}dvvJ_igz^8q^jw~PZ}_P3-DY&l$}#EE zO$+doW~>pM|3<@?v8hSLuQ@T#jc!jfelOPkNyFFhb*}xR$k=3O3AQeJ<`){7b>vr(eqQ^N7Y;A`%}*3$RptF>th0d@snq{377nMvf!U zIM45b>hoeg^Ip$)E3t%sSzL16GOlDDp@qLIII{y$X@6m|y+b*HGmgnsEBPCvRp1PI zI}>Mdw8mS9RcPZAh(X{{Eli#CQ9|H!^ka#G8EL7oqNPtdwybu5V&wJU9HvN?anEL8l;C zMCYZ+Tk6RFkWfQTGOV{p57Z=3L>AIwxjDz$A7IK1N}OI*cUEzB`Z!xy_3y+{x{rwC z$_FsP_yqvzM>_0~T8DAad;Rdd-mjyDeN5ErL*A2B@5!p>8+^?byu0fC7Wx+6+oXK$ z_uxHK_@L0Yuj3SA9gC-NZyf^3yo9@f4sT@B+s`(5fT8PjmJc~^t2%G*>>qsI%U7Sz~UW6NWYI|Vc~N5m=WL*3|$p|Yz@;VZ&tIOcX~ zUz|1IZh2;KI}cWWd!DOBq%GY1jU#9jl0JMCJcg$5y&!-UR8JgID*vNJLobiCJ|15E zA@D6BLVtiC(yZuSQACj+ZH0LCHR7xvZm>YtOX~%C6kj+}z)CwQp{Bw;xdU{Ys`5 zhIY_ApnJ*jobZ9bXexJ>Wx@CMoRay(s@fT4rl+^-0>c`*(4EA4 z7>i?6VDP_LYj_{y0zD-=jM5O8XD~k~nY*FiWiraPk{ zjzj`;RAD=Xs^iTTBCSZ+hZ=e$?AAq?b<_@9(2$g{JB+DLYssgPlsxRNhPNc@zQE8$ z)P=Z98Z-%|fc^yBQT(rJMrSG&R~=fYk|;N~0aLm(0OuA8Gk1jf$` z%<&Fc1%B|onPunL46Q;Xoy2E&7RTq!*3s4-G;Csv#o^gUkuqW_>L7`2yo}?8z~xr2 zS+~NnhA;3XiC3*7fv!|mVR!I#9AEK)&k94`$l9YdN#Q`lH^}o+A}I?@FhYCE|IT;^ zyBZ2|W3nZgBz9nH*uw_ht=2*+p&wcC+b)+ z^!_^9m>O&nU~`M%2AQUK_7nzSkn1#g&2Tjfllk1{C|PQZ&!`QS0_)glF#3ZJ7vr}B z<26aV#$ujBCcngSXy^n_mxtwtA90Kz>-vN9c4D zy+R{>9&H_;qIk@(o$BHz*&2acyr_9xCFwCzUBV*&-S3j#g2 mAxcz`;J#NV)9T>PE;zJ0xvynOm3I7zRUu}HuJDWwxPJpkpwKZ3AT}}06NeH39uxKf?Jc(?nqi|4|#Wm zt;R{QoD^(a({aPA{iT({|Tw)BAFpwn=(l?%{^M-^@rmLMwyw zJk|5CJNwW7-S2n&Ki~Ypr7HmTs5T8n3e^$wcrcb6js~L{GahW++Zy6`T7yTS;z8rM z5sVp$!QjFE2hDIs!Mnfh$g$odhuRcYbtY4T!T!|7b!aG+ry3nzl*!Y29X|VM zqmFWvDJ<)ZCd>n)@qRPaYxKuV1%GEUY{dGER8)RDi%VijBhp19W35KUP}s5A?ci`S zF%TUbO&OVJG7%hz#>`+lKU&<&jdguq)GMqM!_(X1!fR`U%(lhN2&3e~7Hre7RUznd z;f-+C5yW=-ZqUqx5`;l@0pEq{LSEdiuzG>?ftZmVibV&9NLd^n7*x3J9h>GuF?LD_ zmoUVcp=g>o=q!v~!mrdeSYgBFP@P*=G;!QaWRj_|puoH*V}yqr%g}^o4fiN4ce$m@ z$e4^zOvk&iTcPC8o{SyRXqlPVdpNADs%7j6|zBV2s8xEjAvlJYfV5C^R<> zri`)X?5DF+xs#$pP4)`a`C9f$P42PmmE2>waekiR!c2CmCVPSJuH;T|&t&eY+?j1& z98zd%8Z%?Dx(M&WJ?2M)}I_?8=xhOfHu+xnpyS}*d&snLnQ*w?2UA@o8G&`c>DDG!m`bVR& zh(cmsw#)@4v@oMX&RU-3!adi;4D)>RbvKEg59qiXyI2DANg#MLbo5)W>OI)q(%}Uy zSlP6py}k9$?c1BPU!+6D%O@D1O9G$)9fJZAU%qB~5mnghMEW_#ff2~Qn!U`pPD#WG zJ}yaEPGl!)vabp=ev$L54B5;4C*hxAw1*Yi-!|G7@kDk~pv0I{#^bq@77nfvc-EGGGN%E=fB?3`vbcWjrfQ`t+B zGLK4nyq|jBP-eJLyLhhr1Y5DR)nl`LwX7#Pm@qP39N95@1F+Y>p6JeQrn2Yw`Ky56#vC zYtEU|J72d3MiXJH>9W_RN8@ISg?JoK>G&x;%{j%4L^EBcH0&Bjn#Fq|RozjR=(s_( zmW4;tnPlA6>pcn1Pcj!Qm`IrOapRG>8ebMmrc9Y9*#9c*-FZ`JxlB7D788#&VXEZr zRs~$kR#`oN79qVek8He#eZi1ZJ!c-;Youf@2(jNTFrsvK4a37fFFr>nyz%iv zYWTvuA=7rgjxXWMG$mz@nBuJ}Y2gc4dhr#D(}(>mI6tf71-!@-8aIYzBnlgu!_mx; z1T14DGW6B1MUmhRdqL%`sIhvKa_EYg^lgb5AIXd96m-Z;rP;YTHOW{?mu3vYkFmaezTA=7ePJ`W2n{E#U&JqK_$7rp zmkx_l+T+o$;5B-`r?)$FU>`e%8`5u2N}GQb-_-DH3fpc--kfzhejVRp;AuZcjd?X^ z{z>N@DB}*fQ?QvmlrWdv8|Dcr2%C_&FsmacKG8x4dfWE3b!+%-PK5as;fQVynkgS% z$M5R+w#|C7RM%^R927j<2ev3iTAW=w=B?-l2rIs?hOi zoMmxUeqAkBE2uQ1M4v8q!em)3KC(jnx~kUIO2vB!?YN}l!2zpjx@*I1J_^rOx>~Jx z>EM^lymn})b^~FSs;-YkPu;Amb*hGrA)Ug}dAadJ7cf`Nn9a*Rnk#r#*mxsgm*aCj z*mLM%>GANghfZ@w$ob%ET09>4STsxh>Pe2K!lvAdushFQWo;9QoHO<&lbLiTWsI;L z4kaULpQ=||G}S;Fv4Zak?Px5p|%Uw z@6hpm{2e#mZj}sIOC>YsT16a`A3Ewt`YxZkOYPFs-2}-3N89Dp9@*L*SK|f6V1Dxd z-?>gLzuy&%Szx=C3OMRcuj0Mr9r*+MC*-isllRNH)4OWyYapKEm3>xKHBAo>(Z$Uw zsMvx+364)K>_TZXt*Jc`5r^AYSBp7tmmnZFmwXDyRVBZD za#3l0^P1B7<|QS+{an|vgmg>!>li%z1cH~b?1;b8zx)EK&LiObT5bJWTUq?w^H^6| z{Jrz2tt|fjd2D!zBt_W7&uWSVmXp~EtierKPX#t(6>hP1fFf_@Z(G=Ys;amisQ1^A z=QJ9~w%&gmIa|-QdA3U}t8S*I>&UdmVyD~0xC1*Z=DZ_x7zg<+j7#b-;9YqprPktl z7jX&h#9iE2CYLo1aX%d<#A_zeIEi)sJ*y_sGL4YG%YSeN_xcad;72Abfnx7^x(}$M zi|hH+zzgTCsKhpUU<-Y*oyu-@$y-C8h|@*hk2><|EolspEoKHkmgjD3yu;-^Ua&0G z^SzU(^@pjaDS8h19~3=f1@yd|dhVj0jnwlV>e);^o2ch*>Umc|J&zUAQ^d?5eyyIZ zE&ES3h56n~Y7RxyyD)}A~?I&it81VxH(?L|A zlgi$UDs;?=@yT5vfp>x~Ey80Kf?r_xBqX($F@A*c|KKhyplu11tgZ5_4wPQPNnjeM z4+k{SzSzR74X&dUcRy}M!eZZTGr<}9M*eE?(^O7yQHu}bBNQi35=}|BT6~mGk~+0` z1|PF>pcWtJzEW~siBI5@RO?fGZ-Z8LJfR-GJPeKPs< zIe3cisqn6eH2XihW*VROpIgh%RjV)IXMns7cHX7vqBLWf!A6YIj*MkXz0KFb9wp%C zEL)Z{H-DZ_MWk4PuUfVU#}X7(?&er51H7Z0>7?qW`q$vApT>D=uO|3#;UX?8Zew(R z;Ud0KjIZPQyjFfo^81*Wj}m3?r&f0^7YOJ>eVof-w}7cNGdzBwpSjb{Bg>EobtyR@ef)$RNLGg9X4^#@8S0; zTeR2VDOYb{y@uB?DT*QHhcMEwl@sB6nNSa2q`962zJKY4*$EaViO zy!VMG`Mm1e<~gZ>w`}zvp2nX)3;#K+-Rh57&r8msay1kG9Lo6>rw#RaAKDe>6!m+8 z#rjFc>NF1FDIDfS)B|{$CHu5xPYrFRUXDHT^jGvJXGkW{cPzvT&rK*3%X}K1e+%pQ zSzcaRdX+DVHH<6%20zA0_}BOw$K)L}S%B~J9~L{Qu{hW+_jZB$h%2Z*M}ac@Z2=Ck zML2x4AcyZ3;P8P(I6PC3!}sPmG}8vLqFm@-Ly6}_7fx(5KIURk?!qR!R9S^jW+2-m z>V87NM_y+GrR4Va7xAw}xQsWCT)= zu&eyuNyC!ru0S9@-amZqRR5&Fo1ab#;I0{I_sR3dLdNdhj2uH157NaB1-6sHXp1|svu91l_1+3qsXCU*D)hiQvZ⋙q)6@f=veQNK$G9%rVN2~;SmL_hoNn& zC=#7eLcKcr&`)9#vx@n!v<-pQt$@t)X9tavqZNTc9dE%~RhHs99>pnv?J7&AmCqQ9 ziv9vSsqGftg;|cnIz})maQD11Cwp_*lwqGW?OA@aY$Izkf2|c5TR~X}k0GgHj4AL% ztQ7w;w{?u;4BfPDaX3 zw8i5Ud=B6p0tYshx_Zp{h+#)gnVF0%M2u`Y!ak6ii`coyG#f%Xh-suXq&D4Hu+2=Y zr%*5!Egcf)S>T41FfCi)VA~VENV|=z+q3OlQ)1mJTC+M#Tp-sO1=53A+Tp=3$weoW zBndZ`U3oW}=rd{E)m;v?hzgZ*PcdoW9ah zS+cA=+4idQX|nx(zwp+{EoOulw>kEPjl4IV>QYAbj74(qE5k(on)YJsG&__mI7sSL zw^Bqdo8IMe?76u+&^8gkS7~r#NlxY#BIngw5n0SF6x^@QhOs|{ui-@vUoW5RW#)9e zq`DMSlT8mx%Q9vNqdu4IllhFarPA;%9pA=x1a!sb%~>PRR$hyx1iE;OlI#QD!;*&Y z3$#>B_)YRUet;j6avoXY*W7E2U}GAuu4d)`<|F)aRIM5YZ}O*Uyo z(xy!B=VCxS#rYnjxzdYidH89RlYc6J7UDOp(oDZ2XQtHXdsWA4c$p!dHLOkct9G!e z;~LhepKb_DmO=Z!OWR+9USAGk0@ro?9IvyZ$%_j{h6Ar`2yHfSmRc~$sHNn9sg|xC z%H0y=BdQ5-I-JbqY|Abfc@F2LmZHYh z?*yLrk3mn`Rj6{Ekrs}h@=4V)Kl>FSrH=R$e9enFS4WGci>u8t^-xc1m zil$f4?7iLNyzTuN1*&i_pFw_t`}}q^;!VyesEA9er|u#CE_fblUq)mFt*dCi`EnDL z>~b#at|$)U2(KtLot~Njs!@i5?W>5j-}4%dmb7dqHefgXZYHulj;39%w5LhAsj%{I z8MP34I*&N-Kn*>+N)0ZcI-Y{i6d2c^nxa1s;BD?*(TqALPS0IO*W@xDTE*KF9V<9F z+<60wo$V_aSi#Ub62KZxSD~}+bxcfFyXTLu;|U-+S=0V1j=D#!>v&Qf)rQX{ufbTu z4DYOgYx~IIWi&4%N4bSHyoaedZedyu zVkcVp-yz~?!*N70igt|geTpXrV|@`ZJd2~a%;+fG?JhPCcL>kmlX#BE8@X3}3ZG`A z3~KodK1+L_qdX(~Z(P>UrEw<{_&mPgh6zLbRA~z-cV9wn&6VmaMK9e*Kj_O>$g`+4 zei2{dWu=|`Reu3}8DH_Vo}o^qwb9iY>Igr-h8L=!DB%XcrNqM|{0VaN5ub_1qKU?G z6Ae`UjiQOiJQGbFYxpKE!B%+~^YK7`wTB`6% h{EDAD`F?}0{N8!~(Ruy}f8j6ckH^2_@AxO0{|m1wY5M>G diff --git a/bin/main/dev/loki/item/ItemMedkit.class b/bin/main/dev/loki/item/ItemMedkit.class deleted file mode 100644 index 2d06dfb9c8a1f97613a334f13e20302191909c6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4470 zcmbVQ30oW26+Mq_gfuopHjW{2D%%(%z$k8;k{HJgX0a6`Ab@coi#tfqFh)qSW}u~e z+H`Z%eM{3O-Afm@aY+IOH(hA!w&~vfp7!f`GlMj;g+I5SKaVss_uYHXz2`3CjsI-? z0zeP`rJ+J#Z%Qu4(%CsPX4-N-7Uv})Q*)-Rp-Q0sqOoYi(ne+`HavY%Ci%2RU{C3p zlZGYLIe|cYygzaNO#h@n(_l6~6PsR`qpH}DF)yv0k(8-3a;aM&)O)&T^i=)hDCg~^oD8B4 zdvx55y#h7IJ++5h2aB-A?7W$o>Av+zbfOl7p+iF;fS|hBr=u1Dfx1C6BZn5|r)7TJ zm`+Q9@L)D+q$iBLsqUSJwb+k?8V=kNE)}YA`lh29hv-(Kzwb{*jBZ7QSI%`g>L;(m2#heG#e z9YKTyG@4NU@n~zb%whG8Ijl?OrC~dXAG3|*oWKE!`!Zx^7G=iH=9e5&IWpZE9u&Cm z_CmEdhT|G&VwX=aL0gP&TF1j6HL6E?M*2qu8vGWwWC*Mak0@Y03~Osyk?4dH>ebPQ zeiD+HRlF0@HUwI>12WIoUWwQStq7db@fN&QWhk!WQJfLjsWN0*xwNsQXfLpv+HT=n zm?fCdF@#}(yXTEL*_+KI4f~vF&+?mP8yTCqYbnFjGRi`D3}YG?jsw1k72{vxwvKU} zrJL4GZZ?#&HKE~LNf&U-Md6*)F;&1Ttz_QJ*=9BqW>6AgRNyIv?rE~WH6AbHa{%w) zyUpdUQFCV2KEj$$&PD8OWL6sKAf}PhkleDoV4LY!Pd;xfSvn*xuxJcx(6nrUL#Ua5934+2tWF%0(xXBsn&Z4C&8Ij>x=44J2}(VH-@1 zZLs$9td>%aPyr1C*3AtfiP>v#z*5rr&!~DGT;8F!_P$> z?^Ic;^#~qMg|LM8Xn40k=N)-bz^voFcpsZG<0mjxQdOn>{eN(=OzzlrbNGOc4=UVR zd}zG?RR3rYAHuU5KFkJKETwqHmNPQ1<0JSeMHh|qf*d9}$T&aYJTa#!d|byTaGCW^ z5XE}uK=6fPo4VNHGI8ve3ux~@sesuOiCt|kd|f45I}7<(Y&w79`mLzK3NE-xp{uo9dh7b^HK7B-uQg#4`z&{b?hU z5;#~A*rLT^@}msMj|KK`E+-j~d}Q9)ry{e46`7VY6G^$SQu_shgj1N~L0T)`n3e~h zHaX#^0%+!PWLoa*z9T=T)QEdk$7^_*(WU(@%Bvo*rsEpcshchcOqQVfzw6mwcV06N zVglE7{2Z^djmb+3Mw)}IWY}zVZPr(Ci~&o^0aGnib*{T=8SPY6&v9@vo3$-FZ{!lv zp3SDLAU5$^4ZmSpi+zDP$hg{dH<;Mq+Nw7#c64=YO`|- zxiVX!uVIxObe1CDOK+{*emFThwWp%jNT=Ao|*xw zQHFwTYlyYo^BRs8wd^D|U@!e{B(f$)(;ipa)1=%~Sou3eEq$KOPUjw|qGwmB!39*q zryw*1#`UMF;Lihin|oF?qQ;5SbJx)|xq^q*@bRh&$8+`v*t+bRZDae4!Tz&b`M z&{6X`CMGN0=Z|mT31Dops_j)Absx2C;7RqUI(&ZY8jN+!@XR{6nhzaWLE{Rtlv`NG zyXeab?p?wA)!A!!#(C7PqF6f|qWjAN1ub-lXqhR7O&qPD}I=)HT ztmC^CXb=CWV81U7!e0CZNb{af80#_I`x5#4rR5Ytr2vkJ;+^pgRv20$(d|qtj#g`54rk<`N zp03L9)tjs6ai5M#&!JkTX~jF5CC^kMqir`>*{gWv1yomF;g^#R_XopQ+g{i z*eH_6jr^1BGf%NiJncgsb;t@n4LcNdNkl^-)e6;LP%7|C{EDBud4Geh{NB0#(YgK! Rf8iVT1M#o;JN}8r{{p5=T0H;& diff --git a/bin/main/dev/loki/item/ItemType.class b/bin/main/dev/loki/item/ItemType.class deleted file mode 100644 index d0d11c459968be07a8bd0ec6c61a9574a23d76a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1593 zcmZ`&SyK~15dMbTVZmfM;f3d{C6q z(vtGoA7$CIEaetS_F-qHr~B)#`|J7h_s1oG6>Nsk!!TSHXKAB;qNjCRoTl^i+if*O z2!4kCV}8cd2Cr4pxmxp-A-J7e-^%YYj1)SDWf-Cxg_YuFA^&cZ{Cdl})i8K#ho1@t zweTOXXq$SiLjJvFVU_Vqkf4$?fcIPwuZ2_Hspr(GT5| zhqEO^uj%#@gD;udXYjAp%OZ?G7=x0&D4*zd7{gTerr?H^sMkcIN;|unuxxIND5y9E zqZlLitP7P%wiC~{o7ye;)P95j?x2lF-sS=Y14DnT>T(%N+RV21_ z!w{y7d8iMP*tBgpbo`i-*Ed2#vRjLzj{wi#KMkgBJhjceCHT19{A5OQT&3* z&lKH*Df;(2jQkiNMpLwZ?A*v(dQ)z`2H7Rc5pDX;Hzc*$3ruUH{tL`%LxBsV|Dz2P z3TP~Y#J-of#|i&7F_)+s{1O9C9W1$%HOqdC$dPt$W!(YF`wY+B>}gsVc?GnunEphY zE8;=N7v;YG*b*_**?$KZJ^5S;9@H*@;qjm!fbf+Ki|S8nhEl_858KF8$2 zmQTAp$VwfyedFKpdgdk-=AiYEe}o2i*~QSPR#|#fW!iVF{08eD*MoJ3VGbM4`tBbE CK|S68 diff --git a/bin/main/dev/loki/item/ItemUseListener$1.class b/bin/main/dev/loki/item/ItemUseListener$1.class deleted file mode 100644 index 381df03696d1c9bbfbe17c5d828b9d3f4f9579b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3776 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 diff --git a/bin/main/dev/loki/killer/GeneratorKick$2.class b/bin/main/dev/loki/killer/GeneratorKick$2.class deleted file mode 100644 index 01e4fd61d2d5c82614c8c6062e6344db03f4ffa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 838 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 diff --git a/bin/main/dev/loki/killer/HitValidator.class b/bin/main/dev/loki/killer/HitValidator.class deleted file mode 100644 index ad3e3c536de713ad267f4bababacc0fe838eed23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3470 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 Wm84P^oK<3tsOKS-`6||W^8XD+LcJyc diff --git a/bin/main/dev/loki/killer/KillerCarry$CarryData.class b/bin/main/dev/loki/killer/KillerCarry$CarryData.class deleted file mode 100644 index b1e98bf40256ff31c2f4984cae942035e49ee9ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 771 zcmaJ<+iuf95IvK)O%vSIv|N%D3X~RF12vb&BBUx60udFYpuBIAmD$GiqV+l`pT$Fj z!~-9|MC3>QwiAoY_q7Oyr3S(w_ z#d<2NsKFxy=VB_NM5J-_ad<9Amaw|GL}>L&p0A0Rl|09UwJbMNHPwdDS*q$^=D2Pp zvmzZ6c6!>x(J-G(l#OI+m7PT==0cmk%X4A#n~LK^elj{XGRp{b%1U0VRM|I#{=rg{ zg{9-A^RoHX9S;WtudBzhfhw;1SjQ%zdT=$ytm8P4BER$Ic4+-1loR+Bx^>X4ow=v3+zuj}Dc!4dv xL<_HQhx6fr2zRl=JEkmzxOVMAN~J(fOqHK|ysNP62OJwLhOmo0M*GG2?q7e-vp)a; diff --git a/bin/main/dev/loki/killer/KillerCarry.class b/bin/main/dev/loki/killer/KillerCarry.class deleted file mode 100644 index ee475b6c93372415927bf07526ec2602ed6c66e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10655 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 I|Gc&RzofBZOaK4? diff --git a/bin/main/dev/loki/listener/GeneratorSelectListener.class b/bin/main/dev/loki/listener/GeneratorSelectListener.class deleted file mode 100644 index b60077204b9cf020a048940a298d954579bc0cdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3019 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