From eb4a670e9c1d5525850bca05c8a9b79764bc8c6a Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Sun, 14 Jun 2026 17:49:28 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=BF=D0=BE=D0=B7=D0=B8=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B3=D0=BE=D0=BB=D0=BE=D0=B3=D1=80=D0=B0=D0=BC=D0=BC?= =?UTF-8?q?=20(getBlock.Location)=20+=20=D0=B7=D0=BE=D0=BD=D0=B0=20=D0=B2?= =?UTF-8?q?=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");