Skip to content

Commit

Permalink
Report overlapping arena regions on load.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
garbagemule committed Dec 31, 2019
1 parent 57c26b2 commit 77ead3d
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 27 additions & 1 deletion src/main/java/com/garbagemule/MobArena/ArenaMasterImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -532,14 +532,40 @@ public void loadArenasInWorld(String worldName) {
if (arenaNames == null || arenaNames.isEmpty()) {
return;
}

List<Arena> arenas = new ArrayList<>();
for (String arenaName : arenaNames) {
Arena arena = getArenaWithName(arenaName);
if (arena != null) continue;

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

Expand Down
17 changes: 17 additions & 0 deletions src/main/java/com/garbagemule/MobArena/region/ArenaRegion.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit 77ead3d

Please sign in to comment.