Recalculate limits every time Limits GUI is shown.

This commit is contained in:
tastybento 2021-03-07 09:20:28 -08:00
parent e7d6d799f1
commit f525ae80a5
6 changed files with 131 additions and 59 deletions

View File

@ -24,6 +24,7 @@ public class Limits extends Addon {
private Settings settings;
private List<GameModeAddon> 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;
}
}

View File

@ -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 {

View File

@ -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<Material, Integer> matLimits = addon.getBlockLimitListener().getMaterialLimits(world, island.getUniqueId());

View File

@ -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;
}
}

View File

@ -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)) {

View File

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