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