diff --git a/pom.xml b/pom.xml index bfcac7b..13f4c21 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ -LOCAL - 1.24.0 + 1.25.0 BentoBoxWorld_Limits bentobox-world https://sonarcloud.io diff --git a/src/main/java/world/bentobox/limits/Settings.java b/src/main/java/world/bentobox/limits/Settings.java index bc93a41..dea309d 100644 --- a/src/main/java/world/bentobox/limits/Settings.java +++ b/src/main/java/world/bentobox/limits/Settings.java @@ -19,6 +19,11 @@ public class Settings { + enum GeneralGroup { + ANIMALS, MOBS + } + + private final Map general = new EnumMap<>(GeneralGroup.class); private final Map limits = new EnumMap<>(EntityType.class); private final Map> groupLimits = new EnumMap<>(EntityType.class); private final List gameModes; @@ -56,15 +61,21 @@ public Settings(Limits addon) { ConfigurationSection el = addon.getConfig().getConfigurationSection("entitylimits"); if (el != null) { for (String key : el.getKeys(false)) { - EntityType type = getType(key); - if (type != null) { - if (DISALLOWED.contains(type)) { - addon.logError("Entity type: " + key + " is not supported - skipping..."); + if (key.equalsIgnoreCase("ANIMALS")) { + general.put(GeneralGroup.ANIMALS, el.getInt(key, 0)); + } else if (key.equalsIgnoreCase("MOBS")) { + general.put(GeneralGroup.MOBS, el.getInt(key, 0)); + } else { + EntityType type = getType(key); + if (type != null) { + if (DISALLOWED.contains(type)) { + addon.logError("Entity type: " + key + " is not supported - skipping..."); + } else { + limits.put(type, el.getInt(key, 0)); + } } else { - limits.put(type, el.getInt(key, 0)); + addon.logError("Unknown entity type: " + key + " - skipping..."); } - } else { - addon.logError("Unknown entity type: " + key + " - skipping..."); } } } @@ -153,4 +164,11 @@ public List getGameModes() { public boolean isAsyncGolums() { return asyncGolums; } + + /** + * @return the general coverage map + */ + public Map getGeneral() { + return general; + } } diff --git a/src/main/java/world/bentobox/limits/commands/player/PlayerCommand.java b/src/main/java/world/bentobox/limits/commands/player/PlayerCommand.java index 590b9e2..642e3fc 100644 --- a/src/main/java/world/bentobox/limits/commands/player/PlayerCommand.java +++ b/src/main/java/world/bentobox/limits/commands/player/PlayerCommand.java @@ -1,10 +1,12 @@ package world.bentobox.limits.commands.player; import java.util.List; +import java.util.Optional; import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.objects.Island; import world.bentobox.limits.Limits; /** @@ -46,7 +48,22 @@ public boolean execute(User user, String label, List args) { showHelp(this, user); return false; } else { - new LimitPanel(addon).showLimits((GameModeAddon)getAddon(), user, user.getUniqueId()); + // Report the limit for the island, which is governed by the owner of the island + Optional opIsland = getIslands().getIslandAt(user.getLocation()); + if (opIsland.isEmpty()) { + user.sendMessage("general.errors.no-island"); + return false; + } + Island island = opIsland.get(); + if (!island.getWorld().equals(getWorld())) { + user.sendMessage("general.errors.wrong-world"); + return false; + } + if (island.getOwner() == null) { + user.sendMessage("general.errors.no-owner"); + return false; + } + new LimitPanel(addon).showLimits((GameModeAddon) getAddon(), user, island.getOwner()); return true; } } diff --git a/src/main/java/world/bentobox/limits/listeners/JoinListener.java b/src/main/java/world/bentobox/limits/listeners/JoinListener.java index 9a32157..3bc93ae 100644 --- a/src/main/java/world/bentobox/limits/listeners/JoinListener.java +++ b/src/main/java/world/bentobox/limits/listeners/JoinListener.java @@ -39,7 +39,7 @@ public class JoinListener implements Listener { private final Limits addon; public JoinListener(Limits addon) { - this.addon = addon; + this.addon = addon; } /** @@ -52,126 +52,126 @@ public JoinListener(Limits addon) { * @param gameMode - game mode string doing the checking */ public void checkPerms(Player player, String permissionPrefix, String islandId, String gameMode) { - IslandBlockCount ibc = addon.getBlockLimitListener().getIsland(islandId); - // Check permissions - if (ibc != null) { - // Clear permission limits - ibc.getEntityLimits().clear(); - ibc.getEntityGroupLimits().clear(); - ibc.getBlockLimits().clear(); - } - for (PermissionAttachmentInfo perms : player.getEffectivePermissions()) { - if (!perms.getValue() || !perms.getPermission().startsWith(permissionPrefix) - || badSyntaxCheck(perms, player.getName(), permissionPrefix)) { - continue; - } - // Check formatting - String[] split = perms.getPermission().split("\\."); - // Entities & materials - EntityType et = Arrays.stream(EntityType.values()).filter(t -> t.name().equalsIgnoreCase(split[3])) - .findFirst().orElse(null); - Material m = Arrays.stream(Material.values()).filter(t -> t.name().equalsIgnoreCase(split[3])).findFirst() - .orElse(null); - EntityGroup entgroup = addon.getSettings().getGroupLimitDefinitions().stream() - .filter(t -> t.getName().equalsIgnoreCase(split[3])).findFirst().orElse(null); + IslandBlockCount ibc = addon.getBlockLimitListener().getIsland(islandId); + // Check permissions + if (ibc != null) { + // Clear permission limits + ibc.getEntityLimits().clear(); + ibc.getEntityGroupLimits().clear(); + ibc.getBlockLimits().clear(); + } + for (PermissionAttachmentInfo perms : player.getEffectivePermissions()) { + if (!perms.getValue() || !perms.getPermission().startsWith(permissionPrefix) + || badSyntaxCheck(perms, player.getName(), permissionPrefix)) { + continue; + } + // Check formatting + String[] split = perms.getPermission().split("\\."); + // Entities & materials + EntityType et = Arrays.stream(EntityType.values()).filter(t -> t.name().equalsIgnoreCase(split[3])) + .findFirst().orElse(null); + Material m = Arrays.stream(Material.values()).filter(t -> t.name().equalsIgnoreCase(split[3])).findFirst() + .orElse(null); + EntityGroup entgroup = addon.getSettings().getGroupLimitDefinitions().stream() + .filter(t -> t.getName().equalsIgnoreCase(split[3])).findFirst().orElse(null); - if (entgroup == null && et == null && m == null) { - logError(player.getName(), perms.getPermission(), - split[3].toUpperCase(Locale.ENGLISH) + " is not a valid material or entity type/group."); - break; - } - // Make an ibc if required - if (ibc == null) { - ibc = new IslandBlockCount(islandId, gameMode); - } - // Get the value - int value = Integer.parseInt(split[4]); - addon.log("Setting login limit via perm for " + player.getName() + "..."); + if (entgroup == null && et == null && m == null) { + logError(player.getName(), perms.getPermission(), + split[3].toUpperCase(Locale.ENGLISH) + " is not a valid material or entity type/group."); + break; + } + // Make an ibc if required + if (ibc == null) { + ibc = new IslandBlockCount(islandId, gameMode); + } + // Get the value + int value = Integer.parseInt(split[4]); + addon.log("Setting login limit via perm for " + player.getName() + "..."); - // Fire perm check event - LimitsPermCheckEvent l = new LimitsPermCheckEvent(player, islandId, ibc, entgroup, et, m, value); - Bukkit.getPluginManager().callEvent(l); - if (l.isCancelled()) { - addon.log("Permissions not set because another addon/plugin canceled setting."); - continue; - } - // Use event values - ibc = l.getIbc(); - // Make an ibc if required - if (ibc == null) { - ibc = new IslandBlockCount(islandId, gameMode); - } - // Run null checks and set ibc - runNullCheckAndSet(ibc, l); - } - // Check removed permissions - // If any changes have been made then store it - don't make files unless they - // are needed - if (ibc != null) - addon.getBlockLimitListener().setIsland(islandId, ibc); + // Fire perm check event + LimitsPermCheckEvent l = new LimitsPermCheckEvent(player, islandId, ibc, entgroup, et, m, value); + Bukkit.getPluginManager().callEvent(l); + if (l.isCancelled()) { + addon.log("Permissions not set because another addon/plugin canceled setting."); + continue; + } + // Use event values + ibc = l.getIbc(); + // Make an ibc if required + if (ibc == null) { + ibc = new IslandBlockCount(islandId, gameMode); + } + // Run null checks and set ibc + runNullCheckAndSet(ibc, l); + } + // Check removed permissions + // If any changes have been made then store it - don't make files unless they + // are needed + if (ibc != null) + addon.getBlockLimitListener().setIsland(islandId, ibc); } private boolean badSyntaxCheck(PermissionAttachmentInfo perms, String name, String permissionPrefix) { - // No wildcards - if (perms.getPermission().contains(permissionPrefix + "*")) { - logError(name, perms.getPermission(), "wildcards are not allowed."); - return true; - } - // Check formatting - String[] split = perms.getPermission().split("\\."); - if (split.length != 5) { - logError(name, perms.getPermission(), "format must be '" + permissionPrefix + "MATERIAL.NUMBER', '" - + permissionPrefix + "ENTITY-TYPE.NUMBER', or '" + permissionPrefix + "ENTITY-GROUP.NUMBER'"); - return true; - } - // Check value - try { - Integer.parseInt(split[4]); - } catch (Exception e) { - logError(name, perms.getPermission(), "the last part MUST be an integer!"); - return true; - } - return false; + // No wildcards + if (perms.getPermission().contains(permissionPrefix + "*")) { + logError(name, perms.getPermission(), "wildcards are not allowed."); + return true; + } + // Check formatting + String[] split = perms.getPermission().split("\\."); + if (split.length != 5) { + logError(name, perms.getPermission(), "format must be '" + permissionPrefix + "MATERIAL.NUMBER', '" + + permissionPrefix + "ENTITY-TYPE.NUMBER', or '" + permissionPrefix + "ENTITY-GROUP.NUMBER'"); + return true; + } + // Check value + try { + Integer.parseInt(split[4]); + } catch (Exception e) { + logError(name, perms.getPermission(), "the last part MUST be an integer!"); + return true; + } + return false; } private void runNullCheckAndSet(@NonNull IslandBlockCount ibc, @NonNull LimitsPermCheckEvent l) { - EntityGroup entgroup = l.getEntityGroup(); - EntityType et = l.getEntityType(); - Material m = l.getMaterial(); - int value = l.getValue(); - if (entgroup != null) { - // Entity group limit - int v = Math.max(ibc.getEntityGroupLimit(entgroup.getName()), value); - ibc.setEntityGroupLimit(entgroup.getName(), v); - addon.log("Setting group limit " + entgroup.getName() + " " + v); - } else if (et != null && m == null) { - // Entity limit - int v = Math.max(ibc.getEntityLimit(et), value); - ibc.setEntityLimit(et, v); - addon.log("Setting entity limit " + et + " " + v); - } else if (m != null && et == null) { - // Block limit - int v = Math.max(ibc.getBlockLimit(m), value); - addon.log("Setting block limit " + m + " " + v); - ibc.setBlockLimit(m, v); - } else { - if (m != null && m.isBlock()) { - int v = Math.max(ibc.getBlockLimit(m), value); - addon.log("Setting block limit " + m + " " + v); - // Material limit - ibc.setBlockLimit(m, v); - } else if (et != null) { - int v = Math.max(ibc.getEntityLimit(et), value); - addon.log("Setting entity limit " + et + " " + v); - // This is an entity setting - ibc.setEntityLimit(et, v); - } - } + EntityGroup entgroup = l.getEntityGroup(); + EntityType et = l.getEntityType(); + Material m = l.getMaterial(); + int value = l.getValue(); + if (entgroup != null) { + // Entity group limit + int v = Math.max(ibc.getEntityGroupLimit(entgroup.getName()), value); + ibc.setEntityGroupLimit(entgroup.getName(), v); + addon.log("Setting group limit " + entgroup.getName() + " " + v); + } else if (et != null && m == null) { + // Entity limit + int v = Math.max(ibc.getEntityLimit(et), value); + ibc.setEntityLimit(et, v); + addon.log("Setting entity limit " + et + " " + v); + } else if (m != null && et == null) { + // Block limit + int v = Math.max(ibc.getBlockLimit(m), value); + addon.log("Setting block limit " + m + " " + v); + ibc.setBlockLimit(m, v); + } else { + if (m != null && m.isBlock()) { + int v = Math.max(ibc.getBlockLimit(m), value); + addon.log("Setting block limit " + m + " " + v); + // Material limit + ibc.setBlockLimit(m, v); + } else if (et != null) { + int v = Math.max(ibc.getEntityLimit(et), value); + addon.log("Setting entity limit " + et + " " + v); + // This is an entity setting + ibc.setEntityLimit(et, v); + } + } } private void logError(String name, String perm, String error) { - addon.logError("Player " + name + " has permission: '" + perm + "' but " + error + " Ignoring..."); + addon.logError("Player " + name + " has permission: '" + perm + "' but " + error + " Ignoring..."); } /* @@ -180,32 +180,33 @@ private void logError(String name, String perm, String error) { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onNewIsland(IslandEvent e) { - if (!e.getReason().equals(Reason.CREATED) && !e.getReason().equals(Reason.RESETTED) - && !e.getReason().equals(Reason.REGISTERED)) { - return; - } - setOwnerPerms(e.getIsland(), e.getOwner()); + if (!e.getReason().equals(Reason.CREATED) && !e.getReason().equals(Reason.RESETTED) + && !e.getReason().equals(Reason.REGISTERED)) { + return; + } + setOwnerPerms(e.getIsland(), e.getOwner()); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onOwnerChange(TeamSetownerEvent e) { - removeOwnerPerms(e.getIsland()); - setOwnerPerms(e.getIsland(), e.getNewOwner()); + removeOwnerPerms(e.getIsland()); + setOwnerPerms(e.getIsland(), e.getNewOwner()); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onPlayerJoin(PlayerJoinEvent e) { - // Check if player has any islands in the game modes - addon.getGameModes().forEach(gm -> { - addon.getIslands().getIslands(gm.getOverWorld(), e.getPlayer().getUniqueId()).stream() - .map(Island::getUniqueId).forEach(islandId -> { - IslandBlockCount ibc = addon.getBlockLimitListener().getIsland(islandId); - if (!joinEventCheck(e.getPlayer(), islandId, ibc)) { - checkPerms(e.getPlayer(), gm.getPermissionPrefix() + "island.limit.", islandId, - gm.getDescription().getName()); - } - }); - }); + // Check if player has any islands in the game modes + addon.getGameModes().forEach(gm -> { + addon.getIslands().getIslands(gm.getOverWorld(), e.getPlayer().getUniqueId()).stream() + .filter(island -> e.getPlayer().getUniqueId().equals(island.getOwner())) + .map(Island::getUniqueId).forEach(islandId -> { + IslandBlockCount ibc = addon.getBlockLimitListener().getIsland(islandId); + if (!joinEventCheck(e.getPlayer(), islandId, ibc)) { + checkPerms(e.getPlayer(), gm.getPermissionPrefix() + "island.limit.", islandId, + gm.getDescription().getName()); + } + }); + }); } /** @@ -217,29 +218,29 @@ public void onPlayerJoin(PlayerJoinEvent e) { * @return true if canceled */ private boolean joinEventCheck(Player player, String islandId, IslandBlockCount ibc) { - // Fire event, so other addons can cancel this permissions change - LimitsJoinPermCheckEvent e = new LimitsJoinPermCheckEvent(player, islandId, ibc); - Bukkit.getPluginManager().callEvent(e); - if (e.isCancelled()) { - return true; - } - // Get ibc from event if it has changed - ibc = e.getIbc(); - // If perms should be ignored, but the IBC given in the event used, then set it - // and return - if (e.isIgnorePerms() && ibc != null) { - addon.getBlockLimitListener().setIsland(islandId, ibc); - return true; - } - return false; + // Fire event, so other addons can cancel this permissions change + LimitsJoinPermCheckEvent e = new LimitsJoinPermCheckEvent(player, islandId, ibc); + Bukkit.getPluginManager().callEvent(e); + if (e.isCancelled()) { + return true; + } + // Get ibc from event if it has changed + ibc = e.getIbc(); + // If perms should be ignored, but the IBC given in the event used, then set it + // and return + if (e.isIgnorePerms() && ibc != null) { + addon.getBlockLimitListener().setIsland(islandId, ibc); + return true; + } + return false; } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onUnregisterIsland(IslandEvent e) { - if (!e.getReason().equals(Reason.UNREGISTERED)) { - return; - } - removeOwnerPerms(e.getIsland()); + if (!e.getReason().equals(Reason.UNREGISTERED)) { + return; + } + removeOwnerPerms(e.getIsland()); } /* @@ -247,30 +248,30 @@ public void onUnregisterIsland(IslandEvent e) { */ private void removeOwnerPerms(Island island) { - World world = island.getWorld(); - if (addon.inGameModeWorld(world)) { - IslandBlockCount ibc = addon.getBlockLimitListener().getIsland(island.getUniqueId()); - if (ibc != null) { - ibc.getBlockLimits().clear(); - } - } + World world = island.getWorld(); + if (addon.inGameModeWorld(world)) { + IslandBlockCount ibc = addon.getBlockLimitListener().getIsland(island.getUniqueId()); + if (ibc != null) { + ibc.getBlockLimits().clear(); + } + } } private void setOwnerPerms(Island island, UUID ownerUUID) { - World world = island.getWorld(); - if (addon.inGameModeWorld(world)) { - // Check if owner is online - OfflinePlayer owner = Bukkit.getOfflinePlayer(ownerUUID); - if (owner.isOnline()) { - // Set perm-based limits - String prefix = addon.getGameModePermPrefix(world); - String name = addon.getGameModeName(world); - if (!prefix.isEmpty() && !name.isEmpty() && owner.getPlayer() != null) { - checkPerms(Objects.requireNonNull(owner.getPlayer()), prefix + "island.limit.", - island.getUniqueId(), name); - } - } - } + World world = island.getWorld(); + if (addon.inGameModeWorld(world)) { + // Check if owner is online + OfflinePlayer owner = Bukkit.getOfflinePlayer(ownerUUID); + if (owner.isOnline()) { + // Set perm-based limits + String prefix = addon.getGameModePermPrefix(world); + String name = addon.getGameModeName(world); + if (!prefix.isEmpty() && !name.isEmpty() && owner.getPlayer() != null) { + checkPerms(Objects.requireNonNull(owner.getPlayer()), prefix + "island.limit.", + island.getUniqueId(), name); + } + } + } } } diff --git a/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java b/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java index f104607..8655abb 100644 --- a/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java +++ b/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java @@ -25,6 +25,7 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.permissions.PermissionAttachmentInfo; import org.bukkit.plugin.PluginManager; +import org.eclipse.jdt.annotation.Nullable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -77,6 +78,7 @@ public class JoinListenerTest { private Island island; @Mock private PluginManager pim; + private @Nullable UUID uuid = UUID.randomUUID(); @Before public void setUp() { @@ -91,12 +93,13 @@ public void setUp() { .thenReturn(new ArrayList<>(List.of(new EntityGroup("friendly", new HashSet<>(), -1, null)))); // Island Manager when(island.getUniqueId()).thenReturn("unique_id"); + when(island.getOwner()).thenReturn(uuid); when(im.getIsland(any(), any(UUID.class))).thenReturn(island); when(im.getIslands(any(), any(UUID.class))).thenReturn(List.of(island)); // Default is that player has island when(addon.getIslands()).thenReturn(im); // Player - when(player.getUniqueId()).thenReturn(UUID.randomUUID()); + when(player.getUniqueId()).thenReturn(uuid); when(player.getName()).thenReturn("tastybento"); // No permissions by default when(player.getEffectivePermissions()).thenReturn(Collections.emptySet()); @@ -117,8 +120,6 @@ public void setUp() { when(Bukkit.getOfflinePlayer(any(UUID.class))).thenReturn(owner); when(Bukkit.getPluginManager()).thenReturn(pim); - // Island - when(island.getOwner()).thenReturn(UUID.randomUUID()); } /**