fix: lobby ownership, duplicate locations, hook hologram, TP hooked players back

This commit is contained in:
loki5512344 2026-06-14 16:40:07 +02:00
parent 183df22d13
commit 2706d6d123
7 changed files with 75 additions and 9 deletions

View file

@ -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();
}
}

View file

@ -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" -> {

View file

@ -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<String> list = safeGetStringList(path);
if (list.contains(locationToString(loc))) return;
list.add(locationToString(loc));
config.set(path, list);
}

View file

@ -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Свободен";
}

View file

@ -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));
}
}
}
/**

View file

@ -338,6 +338,13 @@ public class LobbyRegistry {
return Collections.unmodifiableCollection(lobbies.values());
}
/** Lobbies owned by a specific player. */
public Collection<LobbySession> 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<LobbySession> getJoinableLobbies() {
return lobbies.values().stream()

View file

@ -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"