From f525ae80a583bd015cd4a3c6dcb52be49f805a5c Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 7 Mar 2021 09:20:28 -0800 Subject: [PATCH] Recalculate limits every time Limits GUI is shown. --- .../java/world/bentobox/limits/Limits.java | 11 +- .../limits/commands/AdminCommand.java | 3 +- .../bentobox/limits/commands/LimitPanel.java | 19 ++- .../limits/commands/PlayerCommand.java | 3 +- .../limits/listeners/JoinListener.java | 143 +++++++++++------- .../limits/objects/IslandBlockCount.java | 11 +- 6 files changed, 131 insertions(+), 59 deletions(-) diff --git a/src/main/java/world/bentobox/limits/Limits.java b/src/main/java/world/bentobox/limits/Limits.java index bb822a3..b4ed394 100644 --- a/src/main/java/world/bentobox/limits/Limits.java +++ b/src/main/java/world/bentobox/limits/Limits.java @@ -24,6 +24,7 @@ public class Limits extends Addon { private Settings settings; private List gameModes; private BlockLimitsListener blockLimitListener; + private JoinListener joinListener; @Override public void onDisable(){ @@ -53,7 +54,8 @@ public class Limits extends Addon { // Register listener blockLimitListener = new BlockLimitsListener(this); registerListener(blockLimitListener); - registerListener(new JoinListener(this)); + joinListener = new JoinListener(this); + registerListener(joinListener); registerListener(new EntityLimitListener(this)); // Done } @@ -116,4 +118,11 @@ public class Limits extends Addon { return gameModes.stream().anyMatch(gm -> gm.getDescription().getName().equals(gameMode)); } + /** + * @return the joinListener + */ + public JoinListener getJoinListener() { + return joinListener; + } + } diff --git a/src/main/java/world/bentobox/limits/commands/AdminCommand.java b/src/main/java/world/bentobox/limits/commands/AdminCommand.java index e28ead0..bf9bf3e 100644 --- a/src/main/java/world/bentobox/limits/commands/AdminCommand.java +++ b/src/main/java/world/bentobox/limits/commands/AdminCommand.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Optional; import java.util.UUID; +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.util.Util; @@ -53,7 +54,7 @@ public class AdminCommand extends CompositeCommand { user.sendMessage("general.errors.unknown-player", args.get(0)); return true; } else { - new LimitPanel(addon).showLimits(getWorld(), user, playerUUID); + new LimitPanel(addon).showLimits((GameModeAddon)getAddon(), user, playerUUID); } return true; } else { diff --git a/src/main/java/world/bentobox/limits/commands/LimitPanel.java b/src/main/java/world/bentobox/limits/commands/LimitPanel.java index aaf3ce3..6eb0744 100644 --- a/src/main/java/world/bentobox/limits/commands/LimitPanel.java +++ b/src/main/java/world/bentobox/limits/commands/LimitPanel.java @@ -3,9 +3,12 @@ package world.bentobox.limits.commands; import java.util.Map; import java.util.UUID; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.entity.Player; +import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.panels.builders.TabbedPanelBuilder; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; @@ -28,7 +31,15 @@ public class LimitPanel { this.addon = addon; } - public void showLimits(World world, User user, UUID target) { + /** + * Show the limits panel + * @param gm - game mode + * @param user - user asking + * @param target - target uuid + */ + public void showLimits(GameModeAddon gm, User user, UUID target) { + // Get world + World world = gm.getOverWorld(); // Get the island for the target Island island = addon.getIslands().getIsland(world, target); if (island == null) { @@ -39,6 +50,12 @@ public class LimitPanel { } return; } + // See if the target is online + Player targetPlayer = Bukkit.getPlayer(target); + if (targetPlayer != null) { + // Update perms + addon.getJoinListener().checkPerms(targetPlayer, gm.getPermissionPrefix(), island.getUniqueId(), gm.getDescription().getName()); + } // Get the limits for this island IslandBlockCount ibc = addon.getBlockLimitListener().getIsland(island.getUniqueId()); Map matLimits = addon.getBlockLimitListener().getMaterialLimits(world, island.getUniqueId()); diff --git a/src/main/java/world/bentobox/limits/commands/PlayerCommand.java b/src/main/java/world/bentobox/limits/commands/PlayerCommand.java index 4edb10f..7f070f2 100644 --- a/src/main/java/world/bentobox/limits/commands/PlayerCommand.java +++ b/src/main/java/world/bentobox/limits/commands/PlayerCommand.java @@ -2,6 +2,7 @@ package world.bentobox.limits.commands; import java.util.List; +import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; import world.bentobox.limits.Limits; @@ -45,7 +46,7 @@ public class PlayerCommand extends CompositeCommand { showHelp(this, user); return false; } else { - new LimitPanel(addon).showLimits(getWorld(), user, user.getUniqueId()); + new LimitPanel(addon).showLimits((GameModeAddon)getAddon(), user, user.getUniqueId()); 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 7a1bc00..bd69343 100644 --- a/src/main/java/world/bentobox/limits/listeners/JoinListener.java +++ b/src/main/java/world/bentobox/limits/listeners/JoinListener.java @@ -17,6 +17,8 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.permissions.PermissionAttachmentInfo; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import world.bentobox.bentobox.api.events.island.IslandEvent; import world.bentobox.bentobox.api.events.island.IslandEvent.Reason; @@ -41,19 +43,15 @@ public class JoinListener implements Listener { this.addon = addon; } - private void checkPerms(Player player, String permissionPrefix, String islandId, String gameMode) { + /** + * Check and set the permissions of the player and how they affect the island limits + * @param player - player + * @param permissionPrefix - permission prefix for this game mode + * @param islandId - island string id + * @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); - // Fire event, so other addons can cancel this permissions change - LimitsJoinPermCheckEvent e = new LimitsJoinPermCheckEvent(player, gameMode, ibc); - Bukkit.getPluginManager().callEvent(e); - if (e.isCancelled()) return; - // 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; - } // Check permissions if (ibc != null) { // Clear permission limits @@ -62,27 +60,18 @@ public class JoinListener implements Listener { ibc.getBlockLimits().clear(); } for (PermissionAttachmentInfo perms : player.getEffectivePermissions()) { - if (!perms.getValue() || !perms.getPermission().startsWith(permissionPrefix)) continue; - // No wildcards - if (perms.getPermission().contains(permissionPrefix + "*")) { - logError(player.getName(), perms.getPermission(), "wildcards are not allowed."); - return; + if (!perms.getValue() + || !perms.getPermission().startsWith(permissionPrefix) + || badSyntaxCheck(perms, player.getName(), permissionPrefix)) { + continue; } // Check formatting String[] split = perms.getPermission().split("\\."); - if (split.length != 5) { - logError(player.getName(), perms.getPermission(), "format must be '" + permissionPrefix + "MATERIAL.NUMBER', '" + permissionPrefix + "ENTITY-TYPE.NUMBER', or '" + permissionPrefix + "ENTITY-GROUP.NUMBER'"); - return; - } - // Check value - if (!NumberUtils.isDigits(split[4])) { - logError(player.getName(), perms.getPermission(), "the last part MUST be a number!"); - return; - } // 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); + 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."); @@ -92,37 +81,16 @@ public class JoinListener implements Listener { if (ibc == null) { ibc = new IslandBlockCount(islandId, gameMode); } - + // Get the value int value = Integer.parseInt(split[4]); // Fire perm check event - LimitsPermCheckEvent l = new LimitsPermCheckEvent(player, gameMode, ibc, entgroup, et, m, value); + LimitsPermCheckEvent l = new LimitsPermCheckEvent(player, islandId, ibc, entgroup, et, m, value); Bukkit.getPluginManager().callEvent(l); if (l.isCancelled()) continue; // Use event values ibc = l.getIbc(); - entgroup = l.getEntityGroup(); - et = l.getEntityType(); - m = l.getMaterial(); - value = l.getValue(); - - if (entgroup != null) { - // Entity group limit - ibc.setEntityGroupLimit(entgroup.getName(), Math.max(ibc.getEntityGroupLimit(entgroup.getName()), value)); - } else if (et != null && m == null) { - // Entity limit - ibc.setEntityLimit(et, Math.max(ibc.getEntityLimit(et), value)); - } else if (m != null && et == null) { - // Material limit - ibc.setBlockLimit(m, Math.max(ibc.getBlockLimit(m), value)); - } else { - if (m != null && m.isBlock()) { - // Material limit - ibc.setBlockLimit(m, Math.max(ibc.getBlockLimit(m), value)); - } else if (et != null){ - // This is an entity setting - ibc.setEntityLimit(et, Math.max(ibc.getEntityLimit(et), value)); - } - } + // Run null checks and set ibc + runNullCheckAndSet(ibc, l); } // Check removed permissions @@ -130,6 +98,56 @@ public class JoinListener implements Listener { 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 + if (!NumberUtils.isDigits(split[4])) { + logError(name, perms.getPermission(), "the last part MUST be a number!"); + return true; + } + + return false; + } + + private void runNullCheckAndSet(@Nullable IslandBlockCount ibc, @NonNull LimitsPermCheckEvent l) { + if (ibc == null) { + return; + } + EntityGroup entgroup = l.getEntityGroup(); + EntityType et = l.getEntityType(); + Material m = l.getMaterial(); + int value = l.getValue(); + if (entgroup != null) { + // Entity group limit + ibc.setEntityGroupLimit(entgroup.getName(), Math.max(ibc.getEntityGroupLimit(entgroup.getName()), value)); + } else if (et != null && m == null) { + // Entity limit + ibc.setEntityLimit(et, Math.max(ibc.getEntityLimit(et), value)); + } else if (m != null && et == null) { + // Material limit + ibc.setBlockLimit(m, Math.max(ibc.getBlockLimit(m), value)); + } else { + if (m != null && m.isBlock()) { + // Material limit + ibc.setBlockLimit(m, Math.max(ibc.getBlockLimit(m), value)); + } else if (et != null){ + // This is an entity setting + ibc.setEntityLimit(et, Math.max(ibc.getEntityLimit(et), value)); + } + } + + } + private void logError(String name, String perm, String error) { addon.logError("Player " + name + " has permission: '" + perm + "' but " + error + " Ignoring..."); } @@ -161,11 +179,32 @@ public class JoinListener implements Listener { addon.getGameModes().forEach(gm -> { if (addon.getIslands().hasIsland(gm.getOverWorld(), e.getPlayer().getUniqueId())) { String islandId = Objects.requireNonNull(addon.getIslands().getIsland(gm.getOverWorld(), e.getPlayer().getUniqueId())).getUniqueId(); + IslandBlockCount ibc = addon.getBlockLimitListener().getIsland(islandId); + if (joinEventCheck(e.getPlayer(), islandId, ibc)) { + return; + } checkPerms(e.getPlayer(), gm.getPermissionPrefix() + "island.limit.", islandId, gm.getDescription().getName()); } }); } + 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; + } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onUnregisterIsland(IslandEvent e) { if (!e.getReason().equals(Reason.UNREGISTERED)) { diff --git a/src/main/java/world/bentobox/limits/objects/IslandBlockCount.java b/src/main/java/world/bentobox/limits/objects/IslandBlockCount.java index 448daed..df79857 100644 --- a/src/main/java/world/bentobox/limits/objects/IslandBlockCount.java +++ b/src/main/java/world/bentobox/limits/objects/IslandBlockCount.java @@ -43,9 +43,14 @@ public class IslandBlockCount implements DataObject { // Required for YAML database public IslandBlockCount() {} - public IslandBlockCount(String uniqueId2, String gameMode2) { - this.uniqueId = uniqueId2; - this.gameMode = gameMode2; + /** + * Create an island block count object + * @param islandId - unique Island ID string + * @param gameMode - Game mode name from gm.getDescription().getName() + */ + public IslandBlockCount(String islandId, String gameMode) { + this.uniqueId = islandId; + this.gameMode = gameMode; setChanged(); }