From c3142f68fdfea4c1b4f69702473e60e4fc00aca0 Mon Sep 17 00:00:00 2001 From: tastybento Date: Mon, 8 Apr 2024 20:03:50 -0700 Subject: [PATCH] Islands are now updated correctly across servers. This build has a lot of debug in it! --- .../bentobox/database/objects/Island.java | 75 ++++++++++++++++++- .../bentobox/managers/island/IslandCache.java | 37 ++++++--- .../bentobox/managers/island/IslandGrid.java | 67 +++++++++++------ 3 files changed, 143 insertions(+), 36 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/database/objects/Island.java b/src/main/java/world/bentobox/bentobox/database/objects/Island.java index 16d0c8524..d7a6616b9 100644 --- a/src/main/java/world/bentobox/bentobox/database/objects/Island.java +++ b/src/main/java/world/bentobox/bentobox/database/objects/Island.java @@ -41,6 +41,7 @@ import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.adapters.Adapter; import world.bentobox.bentobox.database.objects.adapters.LogEntryListAdapter; import world.bentobox.bentobox.lists.Flags; +import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.util.Pair; import world.bentobox.bentobox.util.Util; @@ -290,6 +291,7 @@ public class Island implements DataObject, MetaDataAble { this.world = island.getWorld(); this.bonusRanges.addAll(island.getBonusRanges()); this.primaries.addAll(island.getPrimaries()); + BentoBox.getInstance().logDebug("Constructor copy"); this.setChanged(); } @@ -306,6 +308,7 @@ public class Island implements DataObject, MetaDataAble { public void addMember(@NonNull UUID playerUUID) { if (getRank(playerUUID) != RanksManager.MEMBER_RANK) { setRank(playerUUID, RanksManager.MEMBER_RANK); + BentoBox.getInstance().logDebug("Add member"); setChanged(); } } @@ -326,6 +329,7 @@ public class Island implements DataObject, MetaDataAble { setRank(target, RanksManager.BANNED_RANK); log(new LogEntry.Builder("BAN").data("player", target.toString()).data("issuer", issuer.toString()) .build()); + BentoBox.getInstance().logDebug("Ban"); setChanged(); } return true; @@ -615,6 +619,7 @@ public class Island implements DataObject, MetaDataAble { public int getMaxEverProtectionRange() { if (maxEverProtectionRange > this.getRange()) { maxEverProtectionRange = this.getRange(); + BentoBox.getInstance().logDebug("get max ever protect"); setChanged(); } return Math.max(this.getProtectionRange(), maxEverProtectionRange); @@ -634,6 +639,7 @@ public class Island implements DataObject, MetaDataAble { if (maxEverProtectionRange > this.range) { this.maxEverProtectionRange = this.range; } + BentoBox.getInstance().logDebug("setMaxEverProtectionRange"); setChanged(); } @@ -1011,6 +1017,7 @@ public class Island implements DataObject, MetaDataAble { */ public void removeMember(UUID playerUUID) { if (members.remove(playerUUID) != null) { + BentoBox.getInstance().logDebug("removeMember"); setChanged(); } } @@ -1022,6 +1029,7 @@ public class Island implements DataObject, MetaDataAble { if (!center.getWorld().equals(this.center.getWorld()) || !center.equals(this.center)) { this.world = center.getWorld(); this.center = center; + BentoBox.getInstance().logDebug("setCenter"); setChanged(); } } @@ -1032,6 +1040,7 @@ public class Island implements DataObject, MetaDataAble { public void setCreatedDate(long createdDate) { if (this.createdDate != createdDate) { this.createdDate = createdDate; + BentoBox.getInstance().logDebug("setCreatedDate"); setChanged(); } } @@ -1058,6 +1067,7 @@ public class Island implements DataObject, MetaDataAble { public void setFlag(Flag flag, int value, boolean doSubflags) { if (flags.containsKey(flag.getID()) && flags.get(flag.getID()) != value) { flags.put(flag.getID(), value); + BentoBox.getInstance().logDebug("setFlag " + flag); setChanged(); } // Subflag support @@ -1072,6 +1082,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setFlags(Map flags) { this.flags = flags; + BentoBox.getInstance().logDebug("setFlags "); setChanged(); } @@ -1090,7 +1101,6 @@ public class Island implements DataObject, MetaDataAble { .forEach(f -> result.put(f.getID(), plugin.getIWM().getDefaultIslandSettings(world).getOrDefault(f, f.getDefaultRank()))); this.setFlags(result); - setChanged(); } /** @@ -1098,6 +1108,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setMembers(Map members) { this.members = members; + BentoBox.getInstance().logDebug("setMembers"); setChanged(); } @@ -1111,6 +1122,7 @@ public class Island implements DataObject, MetaDataAble { public void setName(String name) { if (name == null || !name.equals(this.name)) { this.name = (name != null && !name.equals("")) ? name : null; + BentoBox.getInstance().logDebug("setName"); setChanged(); } } @@ -1137,6 +1149,7 @@ public class Island implements DataObject, MetaDataAble { } } setRank(owner, RanksManager.OWNER_RANK); + BentoBox.getInstance().logDebug("setOwner"); setChanged(); } @@ -1147,6 +1160,7 @@ public class Island implements DataObject, MetaDataAble { if (this.protectionRange != protectionRange) { this.protectionRange = protectionRange; this.updateMaxEverProtectionRange(); + BentoBox.getInstance().logDebug("setProtectionRange"); setChanged(); } } @@ -1182,6 +1196,7 @@ public class Island implements DataObject, MetaDataAble { public void setPurgeProtected(boolean purgeProtected) { if (this.purgeProtected != purgeProtected) { this.purgeProtected = purgeProtected; + BentoBox.getInstance().logDebug("setPurgeProtected"); setChanged(); } } @@ -1199,6 +1214,7 @@ public class Island implements DataObject, MetaDataAble { public void setRange(int range) { if (this.range != range) { this.range = range; + BentoBox.getInstance().logDebug("setRange"); setChanged(); } } @@ -1240,6 +1256,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setRanks(Map ranks) { members = ranks; + BentoBox.getInstance().logDebug("setRanks"); setChanged(); } @@ -1264,6 +1281,7 @@ public class Island implements DataObject, MetaDataAble { setFlag(Flags.LOCK, RanksManager.VISITOR_RANK); } log(new LogEntry.Builder("SPAWN").data("value", String.valueOf(isSpawn)).build()); + BentoBox.getInstance().logDebug("setSpawn"); setChanged(); } @@ -1285,6 +1303,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setSpawnPoint(Map spawnPoint) { this.spawnPoint = spawnPoint; + BentoBox.getInstance().logDebug("setSpawnPoint"); setChanged(); } @@ -1305,6 +1324,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setWorld(World world) { this.world = world; + BentoBox.getInstance().logDebug("setWorld"); setChanged(); } @@ -1329,6 +1349,7 @@ public class Island implements DataObject, MetaDataAble { if (flag.getType().equals(Flag.Type.SETTING) || flag.getType().equals(Flag.Type.WORLD_SETTING)) { setSettingsFlag(flag, newToggleValue, doSubflags); } + BentoBox.getInstance().logDebug("toggleFlag " + flag); setChanged(); } @@ -1360,6 +1381,7 @@ public class Island implements DataObject, MetaDataAble { flag.getSubflags().forEach(subflag -> setSettingsFlag(subflag, state, true)); } } + BentoBox.getInstance().logDebug("setSettingsFlag " + flag); setChanged(); } @@ -1397,6 +1419,7 @@ public class Island implements DataObject, MetaDataAble { */ public void removeRank(Integer rank) { if (members.values().removeIf(rank::equals)) { + BentoBox.getInstance().logDebug("removeRank"); setChanged(); } } @@ -1417,6 +1440,7 @@ public class Island implements DataObject, MetaDataAble { */ public void log(LogEntry logEntry) { history.add(logEntry); + BentoBox.getInstance().logDebug("log"); setChanged(); } @@ -1427,6 +1451,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setHistory(List history) { this.history = history; + BentoBox.getInstance().logDebug("setHistory"); setChanged(); } @@ -1442,6 +1467,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setDoNotLoad(boolean doNotLoad) { this.doNotLoad = doNotLoad; + BentoBox.getInstance().logDebug("setDoNotLoad"); setChanged(); } @@ -1457,6 +1483,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setDeleted(boolean deleted) { this.deleted = deleted; + BentoBox.getInstance().logDebug("setDeleted"); setChanged(); } @@ -1546,8 +1573,10 @@ public class Island implements DataObject, MetaDataAble { if (cooldowns.containsKey(flag.getID()) && cooldowns.get(flag.getID()) > System.currentTimeMillis()) { return true; } - cooldowns.remove(flag.getID()); - setChanged(); + if (cooldowns.remove(flag.getID()) != null) { + BentoBox.getInstance().logDebug("isCooldown"); + setChanged(); + } return false; } @@ -1558,6 +1587,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setCooldown(Flag flag) { cooldowns.put(flag.getID(), flag.getCooldown() * 1000L + System.currentTimeMillis()); + BentoBox.getInstance().logDebug("setCooldown"); setChanged(); } @@ -1573,6 +1603,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setCooldowns(Map cooldowns) { this.cooldowns = cooldowns; + BentoBox.getInstance().logDebug("setCooldowns"); setChanged(); } @@ -1588,6 +1619,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setCommandRanks(Map commandRanks) { this.commandRanks = commandRanks; + BentoBox.getInstance().logDebug("setCommandRanks"); setChanged(); } @@ -1659,6 +1691,7 @@ public class Island implements DataObject, MetaDataAble { public void setReserved(boolean reserved) { if (this.reserved != reserved) { this.reserved = reserved; + BentoBox.getInstance().logDebug("setReserved"); setChanged(); } } @@ -1682,6 +1715,7 @@ public class Island implements DataObject, MetaDataAble { @Override public void setMetaData(Map metaData) { this.metaData = metaData; + BentoBox.getInstance().logDebug("setMetaData"); setChanged(); } @@ -1698,7 +1732,7 @@ public class Island implements DataObject, MetaDataAble { public void setChanged() { this.setUpdatedDate(System.currentTimeMillis()); this.changed = true; - //IslandsManager.updateIsland(this); + IslandsManager.updateIsland(this); } /** @@ -1737,6 +1771,7 @@ public class Island implements DataObject, MetaDataAble { } this.location = location; this.updateMaxEverProtectionRange(); + BentoBox.getInstance().logDebug("setProtectionCenter"); setChanged(); } @@ -1795,6 +1830,7 @@ public class Island implements DataObject, MetaDataAble { } } getHomes().put(name.toLowerCase(), location); + BentoBox.getInstance().logDebug("addHome"); setChanged(); } @@ -1865,6 +1901,7 @@ public class Island implements DataObject, MetaDataAble { public void setMaxHomes(@Nullable Integer maxHomes) { if (this.maxHomes != maxHomes) { this.maxHomes = maxHomes; + BentoBox.getInstance().logDebug("setMaxHomes"); setChanged(); } } @@ -1887,6 +1924,7 @@ public class Island implements DataObject, MetaDataAble { public void setMaxMembers(Map maxMembers) { if (this.maxMembers != maxMembers) { this.maxMembers = maxMembers; + BentoBox.getInstance().logDebug("setMaxMembers"); setChanged(); } } @@ -1937,6 +1975,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setBonusRanges(List bonusRanges) { this.bonusRanges = bonusRanges; + BentoBox.getInstance().logDebug("setBonusRanges"); setChanged(); } @@ -1973,6 +2012,7 @@ public class Island implements DataObject, MetaDataAble { public void addBonusRange(String id, int range, String message) { this.getBonusRanges().add(new BonusRangeRecord(id, range, message)); setMaxEverProtectionRange(this.getProtectionRange()); + BentoBox.getInstance().logDebug("addBonusRange"); setChanged(); } @@ -1983,6 +2023,7 @@ public class Island implements DataObject, MetaDataAble { */ public void clearBonusRange(String id) { if (this.getBonusRanges().removeIf(r -> r.getUniqueId().equals(id))) { + BentoBox.getInstance().logDebug("clearBonusRange"); setChanged(); } } @@ -1992,6 +2033,7 @@ public class Island implements DataObject, MetaDataAble { */ public void clearAllBonusRanges() { this.getBonusRanges().clear(); + BentoBox.getInstance().logDebug("clearAllBonusRanges"); setChanged(); } @@ -2008,6 +2050,7 @@ public class Island implements DataObject, MetaDataAble { */ public void setPrimary(UUID userID) { if (getPrimaries().add(userID)) { + BentoBox.getInstance().logDebug("setPrimary"); setChanged(); } } @@ -2018,6 +2061,7 @@ public class Island implements DataObject, MetaDataAble { */ public void removePrimary(UUID userID) { if (getPrimaries().remove(userID)) { + BentoBox.getInstance().logDebug("removePrimary"); setChanged(); } } @@ -2074,5 +2118,28 @@ public class Island implements DataObject, MetaDataAble { */ public void setPrimaries(Set primaries) { this.primaries = primaries; + BentoBox.getInstance().logDebug("setPrimaries"); + setChanged(); } + + @Override + public int hashCode() { + return Objects.hash(uniqueId); + } + + /** + * Islands are equal if they have the same uniqueId + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Island other = (Island) obj; + return Objects.equals(uniqueId, other.uniqueId); + } + } diff --git a/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java b/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java index 6d959c45f..102f2d306 100644 --- a/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java +++ b/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java @@ -21,6 +21,7 @@ import org.eclipse.jdt.annotation.Nullable; import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.flags.Flag; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.lists.Flags; import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.util.Util; @@ -54,15 +55,26 @@ public class IslandCache { grids = new HashMap<>(); } + /** + * Replace the island we have with this one + * @param island island + */ public void updateIsland(@NonNull Island island) { - if (island.getCenter() != null || island.getWorld() != null) { - islandsByLocation.put(island.getCenter(), island); - islandsById.put(island.getUniqueId(), island); - // Only add islands to this map if they are owned - if (island.isOwned()) { - islandsByUUID.computeIfAbsent(island.getOwner(), k -> new HashSet<>()).add(island); - island.getMemberSet().forEach(member -> addPlayer(member, island)); + BentoBox.getInstance().logDebug("sign editing value = " + island.getFlag(Flags.SIGN_EDITING)); + if (islandsByLocation.put(island.getCenter(), island) == null) { + BentoBox.getInstance().logDebug("islandsByLocation failed to update"); + } + if (islandsById.put(island.getUniqueId(), island) == null) { + BentoBox.getInstance().logDebug("islandsById failed to update"); + } + + // Only add islands to this map if they are owned + if (island.getOwner() != null) { + Set set = islandsByUUID.computeIfAbsent(island.getOwner(), k -> new HashSet<>()); + if (!set.remove(island)) { + BentoBox.getInstance().logDebug("islandsByUUID failed to remove"); } + set.add(island); } } @@ -107,7 +119,7 @@ public class IslandCache { * @return true if successfully added, false if not */ private boolean addToGrid(@NonNull Island newIsland) { - return grids.computeIfAbsent(newIsland.getWorld(), k -> new IslandGrid()).addToGrid(newIsland); + return grids.computeIfAbsent(newIsland.getWorld(), k -> new IslandGrid(this)).addToGrid(newIsland); } public void clear() { @@ -220,8 +232,13 @@ public class IslandCache { * @param island island to make primary */ public void setPrimaryIsland(@NonNull UUID uuid, @NonNull Island island) { + if (island.getPrimaries().contains(uuid)) { + return; + } for (Island is : getIslands(island.getWorld(), uuid)) { - is.removePrimary(uuid); + if (is.getPrimaries().contains(uuid)) { + is.removePrimary(uuid); + } if (is.equals(island)) { is.setPrimary(uuid); } @@ -396,7 +413,7 @@ public class IslandCache { public void removeIsland(@NonNull Island island) { islandsByLocation.values().removeIf(island::equals); islandsById.values().removeIf(island::equals); - islandsByUUID.values().removeIf(island::equals); + islandsByUUID.values().forEach(s -> s.removeIf(island::equals)); World w = Util.getWorld(island.getWorld()); if (w == null) { return; diff --git a/src/main/java/world/bentobox/bentobox/managers/island/IslandGrid.java b/src/main/java/world/bentobox/bentobox/managers/island/IslandGrid.java index 7fb73425d..fd47d3dde 100644 --- a/src/main/java/world/bentobox/bentobox/managers/island/IslandGrid.java +++ b/src/main/java/world/bentobox/bentobox/managers/island/IslandGrid.java @@ -12,7 +12,17 @@ import world.bentobox.bentobox.database.objects.Island; * */ class IslandGrid { - private final TreeMap> grid = new TreeMap<>(); + private final TreeMap> grid = new TreeMap<>(); + private final IslandCache im; + + /** + * @param im IslandsManager + */ + public IslandGrid(IslandCache im) { + super(); + this.im = im; + } + /** * Adds island to grid * @param island - island to add @@ -21,9 +31,9 @@ class IslandGrid { public boolean addToGrid(Island island) { // Check if we know about this island already if (grid.containsKey(island.getMinX())) { - TreeMap zEntry = grid.get(island.getMinX()); + TreeMap zEntry = grid.get(island.getMinX()); if (zEntry.containsKey(island.getMinZ())) { - if (island.getUniqueId().equals(zEntry.get(island.getMinZ()).getUniqueId())) { + if (island.getUniqueId().equals(zEntry.get(island.getMinZ()))) { BentoBox.getInstance().logDebug("I already know about this island"); return true; } @@ -31,13 +41,13 @@ class IslandGrid { return false; } else { // Add island - zEntry.put(island.getMinZ(), island); + zEntry.put(island.getMinZ(), island.getUniqueId()); grid.put(island.getMinX(), zEntry); } } else { // Add island - TreeMap zEntry = new TreeMap<>(); - zEntry.put(island.getMinZ(), island); + TreeMap zEntry = new TreeMap<>(); + zEntry.put(island.getMinZ(), island.getUniqueId()); grid.put(island.getMinX(), zEntry); } return true; @@ -54,7 +64,7 @@ class IslandGrid { int x = island.getMinX(); int z = island.getMinZ(); if (grid.containsKey(x)) { - TreeMap zEntry = grid.get(x); + TreeMap zEntry = grid.get(x); if (zEntry.containsKey(z)) { // Island exists - delete it zEntry.remove(z); @@ -67,25 +77,38 @@ class IslandGrid { } /** - * Returns the island at the x,z location or null if there is none. - * This includes the full island space, not just the protected area. + * Retrieves the island located at the specified x and z coordinates, covering both the protected area + * and the full island space. Returns null if no island exists at the given location. * - * @param x - x coordinate - * @param z - z coordinate - * @return Island or null + * @param x the x coordinate of the location + * @param z the z coordinate of the location + * @return the Island at the specified location, or null if no island is found */ public Island getIslandAt(int x, int z) { - Entry> en = grid.floorEntry(x); - if (en != null) { - Entry ent = en.getValue().floorEntry(z); - if (ent != null) { - // Check if in the island range - Island island = ent.getValue(); - if (island.inIslandSpace(x, z)) { - return island; - } - } + // Attempt to find the closest x-coordinate entry that does not exceed 'x' + Entry> xEntry = grid.floorEntry(x); + if (xEntry == null) { + return null; // No x-coordinate entry found, return null } + + // Attempt to find the closest z-coordinate entry that does not exceed 'z' within the found x-coordinate + Entry zEntry = xEntry.getValue().floorEntry(z); + if (zEntry == null) { + return null; // No z-coordinate entry found, return null + } + + // Retrieve the island using the id found in the z-coordinate entry + Island island = im.getIslandById(zEntry.getValue()); + if (island == null) { + return null; // No island found by the id, return null + } + // Check if the specified coordinates are within the island space + if (island.inIslandSpace(x, z)) { + return island; // Coordinates are within island space, return the island + } + + // Coordinates are outside the island space, return null return null; } + }