From ccdea596bc0848f3ea71fb9420925fb09331b402 Mon Sep 17 00:00:00 2001 From: Misat11 <20199703+Misat11@users.noreply.github.com> Date: Fri, 21 Jun 2024 21:02:08 +0200 Subject: [PATCH] feat: warn users during arena creation if the pos1/pos2 overlaps with another arena bounding box Closes #371 --- .../bedwars/game/GameCreator.java | 62 +++++++++++++++++-- .../main/resources/languages/language_en.yml | 3 +- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/plugin/src/main/java/org/screamingsandals/bedwars/game/GameCreator.java b/plugin/src/main/java/org/screamingsandals/bedwars/game/GameCreator.java index df4086936..f627cc6aa 100644 --- a/plugin/src/main/java/org/screamingsandals/bedwars/game/GameCreator.java +++ b/plugin/src/main/java/org/screamingsandals/bedwars/game/GameCreator.java @@ -70,9 +70,9 @@ public boolean cmd(Player player, String action, String[] args) { } else if (action.equalsIgnoreCase("spec")) { response = setSpecSpawn(player.getLocation()); } else if (action.equalsIgnoreCase("pos1")) { - response = setPos1(player.getLocation()); + response = setPos1(player.getLocation(), args.length > 0 && "force".equalsIgnoreCase(args[0])); } else if (action.equalsIgnoreCase("pos2")) { - response = setPos2(player.getLocation()); + response = setPos2(player.getLocation(), args.length > 0 && "force".equalsIgnoreCase(args[0])); } else if (action.equalsIgnoreCase("pausecountdown")) { if (args.length >= 1) { response = setPauseCountdown(Integer.parseInt(args[0])); @@ -891,7 +891,7 @@ public String setSpecSpawn(Location loc) { .replace("%yaw%", Float.toString(loc.getYaw())).replace("%pitch%", Float.toString(loc.getPitch())); } - public String setPos1(Location loc) { + public String setPos1(Location loc, boolean force) { if (game.getWorld() == null) { game.setWorld(loc.getWorld()); } @@ -903,13 +903,27 @@ public String setPos1(Location loc) { return i18n("admin_command_pos1_pos2_difference_must_be_higher"); } } + + if (!force) { + for (String gameN : Main.getGameNames()) { + Game game1 = Main.getGame(gameN); + if (game1 == game) { + continue; + } + + if (game.getPos2() != null && arenaOverlaps(game1.getPos1(), game1.getPos2(), loc, game.getPos2()) || game.getPos2() == null && isInArea(game1.getPos1(), game1.getPos2(), loc)) { + return i18n("admin_arena_overlaps").replace("%arena%", game.getName()).replace("%position%", "pos1"); + } + } + } + game.setPos1(loc); return i18n("admin_command_pos1_setted").replace("%arena%", game.getName()) .replace("%x%", Integer.toString(loc.getBlockX())).replace("%y%", Integer.toString(loc.getBlockY())) .replace("%z%", Integer.toString(loc.getBlockZ())); } - public String setPos2(Location loc) { + public String setPos2(Location loc, boolean force) { if (game.getWorld() == null) { game.setWorld(loc.getWorld()); } @@ -921,6 +935,20 @@ public String setPos2(Location loc) { return i18n("admin_command_pos1_pos2_difference_must_be_higher"); } } + + if (!force) { + for (String gameN : Main.getGameNames()) { + Game game1 = Main.getGame(gameN); + if (game1 == game) { + continue; + } + + if (game.getPos1() != null && arenaOverlaps(game1.getPos1(), game1.getPos2(), game.getPos1(), loc) || game.getPos1() == null && isInArea(game1.getPos1(), game1.getPos2(), loc)) { + return i18n("admin_arena_overlaps").replace("%arena%", game.getName()).replace("%position%", "pos2"); + } + } + } + game.setPos2(loc); return i18n("admin_command_pos2_setted").replace("%arena%", game.getName()) .replace("%x%", Integer.toString(loc.getBlockX())).replace("%y%", Integer.toString(loc.getBlockY())) @@ -956,6 +984,32 @@ public static boolean isInArea(Location l, Location p1, Location p2) { && max.getY() >= l.getY() && max.getZ() >= l.getZ()); } + public static boolean arenaOverlaps(Location l1, Location l2, Location p1, Location p2) { + if (!p1.getWorld().equals(l1.getWorld())) { + return false; + } + + double minLX = Math.min(l1.getX(), l2.getX()); + double minLY = Math.min(l1.getY(), l2.getY()); + double minLZ = Math.min(l1.getZ(), l2.getZ()); + double maxLX = Math.max(l1.getX(), l2.getX()); + double maxLY = Math.max(l1.getY(), l2.getY()); + double maxLZ = Math.max(l1.getZ(), l2.getZ()); + + double minPX = Math.min(p1.getX(), p2.getX()); + double minPY = Math.min(p1.getY(), p2.getY()); + double minPZ = Math.min(p1.getZ(), p2.getZ()); + double maxPX = Math.max(p1.getX(), p2.getX()); + double maxPY = Math.max(p1.getY(), p2.getY()); + double maxPZ = Math.max(p1.getZ(), p2.getZ()); + + // From https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse/src/main/java/org/bukkit/util/BoundingBox.java#699 + // The method in Bukkit is too new for us + return minLX < maxPX && maxLX > minPX + && minLY < maxPY && maxLY > minPY + && minLZ < maxPZ && maxLZ > minPZ; + } + public static boolean isChunkInArea(Chunk l, Location p1, Location p2) { if (!p1.getWorld().equals(l.getWorld())) { return false; diff --git a/plugin/src/main/resources/languages/language_en.yml b/plugin/src/main/resources/languages/language_en.yml index d5327d486..996124ce3 100644 --- a/plugin/src/main/resources/languages/language_en.yml +++ b/plugin/src/main/resources/languages/language_en.yml @@ -371,4 +371,5 @@ game_ended_too_early: "&cThe game ends too early. No one wins." help_bw_cheatin_give: "/bw cheatIn give - &cGives player specified amount of resource" help_bw_cheatin_kill: "/bw cheatIn kill - &cKills specified player" help_bw_cheatin_destroybed: "/bw cheatIn destroybed - &cDestroys bed of the specific team" -help_bw_cheatin_destroyallbeds: "/bw cheatIn destroyallbeds - &cDestroys all beds in the game" \ No newline at end of file +help_bw_cheatin_destroyallbeds: "/bw cheatIn destroyallbeds - &cDestroys all beds in the game" +admin_arena_overlaps: "&cThe chosen location causes the arena to overlap with another arena, which can lead to errors! Please choose a different location. If you insist on using this location, execute &7/bw admin %arena% %position% force" \ No newline at end of file