fix: позиция голограмм (getBlock.Location) + зона ворот (corner1/corner2)
This commit is contained in:
parent
b0afb3f6be
commit
eb4a670e9c
8 changed files with 124 additions and 13 deletions
|
|
@ -73,7 +73,7 @@ public class ChestHologram {
|
||||||
continue;
|
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 {
|
try {
|
||||||
if (useTextDisplay) {
|
if (useTextDisplay) {
|
||||||
TextDisplay display = loc.getWorld().spawn(holoLoc, TextDisplay.class, d -> {
|
TextDisplay display = loc.getWorld().spawn(holoLoc, TextDisplay.class, d -> {
|
||||||
|
|
@ -139,11 +139,11 @@ public class ChestHologram {
|
||||||
|
|
||||||
if (display instanceof TextDisplay td) {
|
if (display instanceof TextDisplay td) {
|
||||||
td.text(TextUtil.color(text));
|
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);
|
td.teleport(base);
|
||||||
} else if (display instanceof ArmorStand as) {
|
} else if (display instanceof ArmorStand as) {
|
||||||
as.setCustomName(text);
|
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);
|
as.teleport(base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,7 @@ public class SetupCommand implements TabExecutor {
|
||||||
|
|
||||||
var locations = plugin.getConfigManager().getLocations();
|
var locations = plugin.getConfigManager().getLocations();
|
||||||
locations.setGate(gateId, center);
|
locations.setGate(gateId, center);
|
||||||
|
locations.setGateZone(gateId, p1, p2);
|
||||||
plugin.getConfigManager().saveConfig("locations.yml", locations.getConfig());
|
plugin.getConfigManager().saveConfig("locations.yml", locations.getConfig());
|
||||||
|
|
||||||
player.sendMessage(messages().get("setup.gate-placed", gateId, formatLoc(center)));
|
player.sendMessage(messages().get("setup.gate-placed", gateId, formatLoc(center)));
|
||||||
|
|
|
||||||
|
|
@ -225,12 +225,24 @@ public class LocationsConfig {
|
||||||
config.set(path, list);
|
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) {
|
public void setGate(String id, Location loc) {
|
||||||
String key = "gate-" + id.toLowerCase();
|
String key = "gate-" + id.toLowerCase();
|
||||||
config.set(key, locationToString(loc));
|
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) {
|
public Location getGate(String id) {
|
||||||
String key = "gate-" + id.toLowerCase();
|
String key = "gate-" + id.toLowerCase();
|
||||||
String str = config.getString(key);
|
String str = config.getString(key);
|
||||||
|
|
@ -251,6 +263,15 @@ public class LocationsConfig {
|
||||||
return gates;
|
return gates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get all gate IDs that exist in config. */
|
||||||
|
public List<String> getGateIds() {
|
||||||
|
List<String> ids = new ArrayList<>();
|
||||||
|
for (String id : List.of("a", "b")) {
|
||||||
|
if (getGate(id) != null) ids.add(id);
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
private String locationToString(Location loc) {
|
private String locationToString(Location loc) {
|
||||||
// Use | as separator instead of , to avoid issues with negative coordinates in YAML
|
// Use | as separator instead of , to avoid issues with negative coordinates in YAML
|
||||||
return String.format(Locale.US, "%s|%.2f|%.2f|%.2f|%.1f|%.1f",
|
return String.format(Locale.US, "%s|%.2f|%.2f|%.2f|%.1f|%.1f",
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@ public class ExitGate {
|
||||||
private double savedProgress; // сохраняется при уходе игрока
|
private double savedProgress; // сохраняется при уходе игрока
|
||||||
private boolean powered;
|
private boolean powered;
|
||||||
|
|
||||||
|
private int zoneMinX, zoneMinY, zoneMinZ;
|
||||||
|
private int zoneMaxX, zoneMaxY, zoneMaxZ;
|
||||||
|
private boolean hasZone;
|
||||||
|
|
||||||
public enum GateState {
|
public enum GateState {
|
||||||
CLOSED,
|
CLOSED,
|
||||||
OPENING,
|
OPENING,
|
||||||
|
|
@ -23,6 +27,22 @@ public class ExitGate {
|
||||||
this.progress = 0.0;
|
this.progress = 0.0;
|
||||||
this.savedProgress = 0.0;
|
this.savedProgress = 0.0;
|
||||||
this.powered = false;
|
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() {
|
public Location getLocation() {
|
||||||
|
|
@ -35,12 +55,71 @@ public class ExitGate {
|
||||||
location.getBlock().setType(org.bukkit.Material.HOPPER, false);
|
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). */
|
/** Remove the interaction block (e.g. when gate opens or on cleanup). */
|
||||||
public void removeGateBlock() {
|
public void removeGateBlock() {
|
||||||
if (location.getWorld() == null) return;
|
if (location.getWorld() == null) return;
|
||||||
location.getBlock().setType(org.bukkit.Material.AIR, false);
|
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() {
|
public GateState getState() {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +181,8 @@ public class ExitGate {
|
||||||
if (progress >= 1.0) {
|
if (progress >= 1.0) {
|
||||||
progress = 1.0;
|
progress = 1.0;
|
||||||
state = GateState.OPEN;
|
state = GateState.OPEN;
|
||||||
removeGateBlock();
|
removeGateStructure();
|
||||||
|
spawnOpenParticles();
|
||||||
playOpenedSound();
|
playOpenedSound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,17 @@ public class GateManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadGates(LocationsConfig locations) {
|
private void loadGates(LocationsConfig locations) {
|
||||||
List<Location> gateLocations = locations.getExitGates();
|
for (String id : locations.getGateIds()) {
|
||||||
for (int i = 0; i < Math.min(gateLocations.size(), GATE_COUNT); i++) {
|
Location center = locations.getGate(id);
|
||||||
gates.add(new ExitGate(gateLocations.get(i)));
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ public class HookHologram {
|
||||||
continue;
|
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 {
|
try {
|
||||||
if (useTextDisplay) {
|
if (useTextDisplay) {
|
||||||
TextDisplay display = loc.getWorld().spawn(holoLoc, TextDisplay.class, d -> {
|
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;
|
String text = "§c⚓ Крюк §f#" + visibleIndex + "/" + total + "\n§7" + status;
|
||||||
|
|
||||||
double heightOffset = plugin.getConfigManager().getGame().getHookHologramHeightOffset();
|
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) {
|
if (display instanceof TextDisplay td) {
|
||||||
td.text(TextUtil.color(text));
|
td.text(TextUtil.color(text));
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ public class GeneratorHologram {
|
||||||
Location loc = gen.getLocation();
|
Location loc = gen.getLocation();
|
||||||
if (loc.getWorld() == null) continue;
|
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 {
|
try {
|
||||||
if (useTextDisplay) {
|
if (useTextDisplay) {
|
||||||
TextDisplay display = loc.getWorld().spawn(holoLoc, TextDisplay.class, d -> {
|
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 + "%";
|
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) {
|
if (display instanceof TextDisplay td) {
|
||||||
td.text(TextUtil.color(text));
|
td.text(TextUtil.color(text));
|
||||||
|
|
|
||||||
|
|
@ -321,8 +321,9 @@ public class GameplayPhase implements Phase {
|
||||||
}
|
}
|
||||||
plugin.getLogger().info("[GameplayPhase] Spawned blocks for " + hookManager.getAllHooks().size() + " hooks");
|
plugin.getLogger().info("[GameplayPhase] Spawned blocks for " + hookManager.getAllHooks().size() + " hooks");
|
||||||
|
|
||||||
// Спавн блоков на местах ворот (Hopper — для открытия через ПКМ)
|
// Спавн структуры ворот (рамка + кнопка + Hopper для взаимодействия)
|
||||||
for (ExitGate gate : gateManager.getAllGates()) {
|
for (ExitGate gate : gateManager.getAllGates()) {
|
||||||
|
gate.spawnGateStructure();
|
||||||
gate.spawnGateBlock();
|
gate.spawnGateBlock();
|
||||||
}
|
}
|
||||||
plugin.getLogger().info("[GameplayPhase] Spawned blocks for " + gateManager.getAllGates().size() + " gates");
|
plugin.getLogger().info("[GameplayPhase] Spawned blocks for " + gateManager.getAllGates().size() + " gates");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue