From 77ead3de5cfc322337524a8fb6646821edfd24f8 Mon Sep 17 00:00:00 2001 From: Andreas Troelsen Date: Tue, 31 Dec 2019 23:21:08 +0100 Subject: [PATCH] Report overlapping arena regions on load. This commit introduces an `intersects()` method on ArenaRegion that allows us to check whether two regions intersect. The new method is employed in ArenaMasterImpl during arena load. If an arena's region intersects with any other arena's region (in the same world), we print a warning to the server log. Fixes #367 --- changelog.md | 1 + .../garbagemule/MobArena/ArenaMasterImpl.java | 28 ++++++++++++++++++- .../MobArena/region/ArenaRegion.java | 17 +++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index b342b6e7..f0c23113 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,7 @@ These changes will (most likely) be included in the next version. - Entities outside of the arena can no longer target players, pets, or monsters inside of the arena. - Tab completion for `/ma kick` and `/ma restore` now uses actual player names instead of display names. - If the world of an exit warp, leaderboard, or linked class chest is not available on (re)load, MobArena now throws a config error instead of failing silently later down the road. +- Overlapping arena regions are now reported as warnings in the server log during arena load, because overlapping regions can result in undefined, buggy behavior. - MobArena's internal version checker has been rewritten. It now uses the resource API of Spigot instead of DBO. It's also a lot more lightweight and caches results for up to one hour. ## [0.104] - 2019-08-08 diff --git a/src/main/java/com/garbagemule/MobArena/ArenaMasterImpl.java b/src/main/java/com/garbagemule/MobArena/ArenaMasterImpl.java index 6ab23fae..dfa9d05a 100644 --- a/src/main/java/com/garbagemule/MobArena/ArenaMasterImpl.java +++ b/src/main/java/com/garbagemule/MobArena/ArenaMasterImpl.java @@ -532,6 +532,8 @@ public void loadArenasInWorld(String worldName) { if (arenaNames == null || arenaNames.isEmpty()) { return; } + + List arenas = new ArrayList<>(); for (String arenaName : arenaNames) { Arena arena = getArenaWithName(arenaName); if (arena != null) continue; @@ -539,7 +541,31 @@ public void loadArenasInWorld(String worldName) { String arenaWorld = config.getString("arenas." + arenaName + ".settings.world", ""); if (!arenaWorld.equals(worldName)) continue; - loadArena(arenaName); + Arena loaded = loadArena(arenaName); + if (loaded != null) { + arenas.add(loaded); + } + } + + reportOverlappingRegions(arenas); + } + + private void reportOverlappingRegions(List arenas) { + // If we iterate the upper/lower triangular matrix of the cartesian + // product of the arena list, we avoid not only duplicate reports like + // "a vs. b and b vs. a", but also "self comparisons" (j = i + 1). + for (int i = 0; i < arenas.size(); i++) { + Arena a = arenas.get(i); + for (int j = i + 1; j < arenas.size(); j++) { + Arena b = arenas.get(j); + if (a.getRegion().intersects(b.getRegion())) { + plugin.getLogger().warning(String.format( + "Regions of arenas '%s' and '%s' overlap!", + a.configName(), + b.configName() + )); + } + } } } diff --git a/src/main/java/com/garbagemule/MobArena/region/ArenaRegion.java b/src/main/java/com/garbagemule/MobArena/region/ArenaRegion.java index c4af962e..d9462c59 100644 --- a/src/main/java/com/garbagemule/MobArena/region/ArenaRegion.java +++ b/src/main/java/com/garbagemule/MobArena/region/ArenaRegion.java @@ -242,6 +242,23 @@ public boolean contains(Location l, int radius) { (y + radius >= p1.getBlockY() && y - radius <= p2.getBlockY())); } + public boolean intersects(ArenaRegion other) { + if (lobbySetup && other.lobbySetup) { + if (intersects(l1, l2, other.l1, other.l2)) { + return true; + } + } + return intersects(p1, p2, other.p1, other.p2); + } + + private boolean intersects(Location a1, Location a2, Location b1, Location b2) { + return ( + b1.getBlockX() <= a2.getBlockX() && a1.getBlockX() <= b2.getBlockX() && + b1.getBlockZ() <= a2.getBlockZ() && a1.getBlockZ() <= b2.getBlockZ() && + b1.getBlockY() <= a2.getBlockY() && a1.getBlockY() <= b2.getBlockY() + ); + } + // Region expand public void expandUp(int amount) { int x = p2.getBlockX();