From 2706d6d12380d12c982bb5aeb9968b725a9136f8 Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Sun, 14 Jun 2026 16:40:07 +0200 Subject: [PATCH] fix: lobby ownership, duplicate locations, hook hologram, TP hooked players back --- .../java/dev/loki/command/DBDCommand.java | 18 ++++++++++++- .../java/dev/loki/command/SetupCommand.java | 23 +++++++++++++--- .../java/dev/loki/config/LocationsConfig.java | 6 +++++ src/main/java/dev/loki/hook/HookHologram.java | 2 +- .../dev/loki/phase/GameplayHookHandler.java | 27 ++++++++++++++++--- .../java/dev/loki/world/LobbyRegistry.java | 7 +++++ src/main/resources/messages.yml | 1 + 7 files changed, 75 insertions(+), 9 deletions(-) diff --git a/src/main/java/dev/loki/command/DBDCommand.java b/src/main/java/dev/loki/command/DBDCommand.java index 59ce45d..63902f7 100644 --- a/src/main/java/dev/loki/command/DBDCommand.java +++ b/src/main/java/dev/loki/command/DBDCommand.java @@ -350,12 +350,28 @@ public class DBDCommand implements TabExecutor { return DBDAdminPlayerCommand.tabComplete(args); } // Предлагаем имена лобби для join / delete - if (args.length == 2 && (args[0].equalsIgnoreCase("join") || args[0].equalsIgnoreCase("delete"))) { + if (args.length == 2 && args[0].equalsIgnoreCase("join")) { return lobbyRegistry.getAllLobbies().stream() .map(dev.loki.world.LobbySession::getName) .filter(s -> s.startsWith(args[1].toLowerCase())) .toList(); } + // Для delete — только свои лобби (если не admin) + if (args.length == 2 && args[0].equalsIgnoreCase("delete")) { + if (sender.hasPermission("mdbd.admin")) { + return lobbyRegistry.getAllLobbies().stream() + .map(dev.loki.world.LobbySession::getName) + .filter(s -> s.startsWith(args[1].toLowerCase())) + .toList(); + } + if (sender instanceof Player p) { + return lobbyRegistry.getOwnedLobbies(p.getUniqueId()).stream() + .map(dev.loki.world.LobbySession::getName) + .filter(s -> s.startsWith(args[1].toLowerCase())) + .toList(); + } + return List.of(); + } return List.of(); } } diff --git a/src/main/java/dev/loki/command/SetupCommand.java b/src/main/java/dev/loki/command/SetupCommand.java index 1390d2e..5e8d218 100644 --- a/src/main/java/dev/loki/command/SetupCommand.java +++ b/src/main/java/dev/loki/command/SetupCommand.java @@ -228,16 +228,31 @@ public class SetupCommand implements TabExecutor { switch (mode) { case "hook" -> { - locations.addLocation("hooks", blockLoc.clone().add(0.5, 0, 0.5)); + Location hLoc = blockLoc.clone().add(0.5, 0, 0.5); + if (locations.hasLocation("hooks", hLoc)) { + player.sendMessage(messages().get("setup.duplicate")); + break; + } + locations.addLocation("hooks", hLoc); player.sendMessage(messages().get("setup.hook-placed", formatLoc(loc))); } case "chest" -> { - locations.addLocation("chests", blockLoc.clone().add(0.5, 0, 0.5)); + Location cLoc = blockLoc.clone().add(0.5, 0, 0.5); + if (locations.hasLocation("chests", cLoc)) { + player.sendMessage(messages().get("setup.duplicate")); + break; + } + locations.addLocation("chests", cLoc); player.sendMessage(messages().get("setup.chest-placed", formatLoc(loc))); } case "generator" -> { - locations.addLocation("generators", blockLoc.clone().add(0.5, 0, 0.5)); - plugin.getGeneratorData().addGenerator(blockLoc.clone().add(0.5, 0, 0.5)); + Location gLoc = blockLoc.clone().add(0.5, 0, 0.5); + if (locations.hasLocation("generators", gLoc)) { + player.sendMessage(messages().get("setup.duplicate")); + break; + } + locations.addLocation("generators", gLoc); + plugin.getGeneratorData().addGenerator(gLoc); player.sendMessage(messages().get("setup.generator-placed", formatLoc(loc))); } case "killer-spawn" -> { diff --git a/src/main/java/dev/loki/config/LocationsConfig.java b/src/main/java/dev/loki/config/LocationsConfig.java index 4fe6847..054d24c 100644 --- a/src/main/java/dev/loki/config/LocationsConfig.java +++ b/src/main/java/dev/loki/config/LocationsConfig.java @@ -174,8 +174,14 @@ public class LocationsConfig { } } + public boolean hasLocation(String path, Location loc) { + String needle = locationToString(loc); + return safeGetStringList(path).contains(needle); + } + public void addLocation(String path, Location loc) { List list = safeGetStringList(path); + if (list.contains(locationToString(loc))) return; list.add(locationToString(loc)); config.set(path, list); } diff --git a/src/main/java/dev/loki/hook/HookHologram.java b/src/main/java/dev/loki/hook/HookHologram.java index 93f2653..9691a17 100644 --- a/src/main/java/dev/loki/hook/HookHologram.java +++ b/src/main/java/dev/loki/hook/HookHologram.java @@ -119,7 +119,7 @@ public class HookHologram { status = "§c✂ Саботирован"; } else if (hook.isOccupied()) { int pct = (int) hook.getStageProgressPercent(); - status = "§4Занят [" + hook.getCurrentStage().name() + " " + pct + "%]"; + status = "§fЗанят [" + pct + "%]"; } else { status = "§aСвободен"; } diff --git a/src/main/java/dev/loki/phase/GameplayHookHandler.java b/src/main/java/dev/loki/phase/GameplayHookHandler.java index 73bbcf4..2c1ede6 100644 --- a/src/main/java/dev/loki/phase/GameplayHookHandler.java +++ b/src/main/java/dev/loki/phase/GameplayHookHandler.java @@ -27,13 +27,34 @@ public class GameplayHookHandler { this.hookRecovery = hookRecovery; } + private int hookTpTick; + /** - * Called every tick - checks hook stage progression. + * Called every tick - checks hook stage progression and teleports hooked players back. */ public void tick() { - // HookManager handles its own ticking via startTicking() - // We just need to check stage transitions here checkHookStages(); + hookTpTick++; + if (hookTpTick >= 20) { + hookTpTick = 0; + tpHookedBack(); + } + } + + /** + * Teleport hooked survivors back to their hook if they've moved too far. + */ + private void tpHookedBack() { + for (Hook hook : hookManager.getAllHooks()) { + if (!hook.isOccupied()) continue; + Survivor hooked = hook.getHookedSurvivor(); + if (hooked == null) continue; + Player p = hooked.getPlayer(); + if (p == null || !p.isOnline()) continue; + if (p.getLocation().distanceSquared(hook.getLocation()) > 1.0) { + p.teleport(hook.getLocation().clone().add(0.5, 0, 0.5)); + } + } } /** diff --git a/src/main/java/dev/loki/world/LobbyRegistry.java b/src/main/java/dev/loki/world/LobbyRegistry.java index 27c80cb..d854960 100644 --- a/src/main/java/dev/loki/world/LobbyRegistry.java +++ b/src/main/java/dev/loki/world/LobbyRegistry.java @@ -338,6 +338,13 @@ public class LobbyRegistry { return Collections.unmodifiableCollection(lobbies.values()); } + /** Lobbies owned by a specific player. */ + public Collection getOwnedLobbies(UUID ownerUuid) { + return lobbies.values().stream() + .filter(ls -> ls.getOwnerUuid().equals(ownerUuid)) + .toList(); + } + /** Lobbies that have a live session (for tab-complete). */ public Collection getJoinableLobbies() { return lobbies.values().stream() diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 1ed8152..2db8982 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -106,6 +106,7 @@ setup: gate-need-points: "%setup-prefix%&cСначала выбери оба угла топориком! (ЛКМ=точка 1, ПКМ=точка 2)" gate-same-world: "%setup-prefix%&cТочки должны быть в одном мире!" gate-placed: "%setup-prefix%&aВорота &f%s &aустановлены: %s" + duplicate: "%setup-prefix%&cНа этом месте уже есть объект!" hook-placed: "%setup-prefix%&aКрюк установлен: %s" chest-placed: "%setup-prefix%&aСундук добавлен: %s" generator-placed: "%setup-prefix%&aГенератор добавлен: %s"