From e0c208e049f3d04f5a6eff1d5f23a48ee64c6612 Mon Sep 17 00:00:00 2001 From: wea_ondara Date: Fri, 10 Apr 2020 15:01:37 +0200 Subject: [PATCH 1/8] added entity group limit settings --- .../java/world/bentobox/limits/Settings.java | 66 +++++++++++++++++++ .../limits/listeners/EntityLimitListener.java | 27 +++++++- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/main/java/world/bentobox/limits/Settings.java b/src/main/java/world/bentobox/limits/Settings.java index c781c33..230be6e 100644 --- a/src/main/java/world/bentobox/limits/Settings.java +++ b/src/main/java/world/bentobox/limits/Settings.java @@ -1,9 +1,13 @@ package world.bentobox.limits; +import java.util.ArrayList; import java.util.Arrays; import java.util.EnumMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; @@ -11,6 +15,7 @@ import org.bukkit.entity.EntityType; public class Settings { private final Map limits = new EnumMap<>(EntityType.class); + private final Map> groupLimits = new EnumMap<>(EntityType.class); private final List gameModes; private static final List DISALLOWED = Arrays.asList( EntityType.PRIMED_TNT, @@ -60,6 +65,33 @@ public class Settings { } addon.log("Entity limits:"); limits.entrySet().stream().map(e -> "Limit " + e.getKey().toString() + " to " + e.getValue()).forEach(addon::log); + + //group limits + el = addon.getConfig().getConfigurationSection("entitygrouplimits"); + if (el != null) { + for (String name : el.getKeys(false)) { + int limit = el.getInt(name + ".limit"); + Set entities = el.getStringList(name + ".entities").stream().map(s -> { + EntityType type = getType(s); + if (type != null) { + if (DISALLOWED.contains(type)) { + addon.logError("Entity type: " + s + " is not supported - skipping..."); + } else { + return type; + } + } else { + addon.logError("Unknown entity type: " + s + " - skipping..."); + } + return null; + }).filter(e -> e != null).collect(Collectors.toSet()); + EntityGroup group = new EntityGroup(name, entities, limit); + entities.forEach(e -> { + List groups = groupLimits.getOrDefault(e, new ArrayList()); + groups.add(group); + groupLimits.put(e, groups); + }); + } + } } private EntityType getType(String key) { @@ -73,6 +105,13 @@ public class Settings { return limits; } + /** + * @return the group limits + */ + public Map> getGroupLimits() { + return groupLimits; + } + /** * @return the gameModes */ @@ -80,4 +119,31 @@ public class Settings { return gameModes; } + public static class EntityGroup { + private final String name; + private final Set types; + private final int limit; + + public EntityGroup(String name, Set types, int limit) { + this.name = name; + this.types = types; + this.limit = limit; + } + + public boolean contains(EntityType type) { + return types.contains(type); + } + + public String getName() { + return name; + } + + public Set getTypes() { + return types; + } + + public int getLimit() { + return limit; + } + } } diff --git a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java index 5d5cf5a..04168da 100644 --- a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java +++ b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java @@ -1,5 +1,7 @@ package world.bentobox.limits.listeners; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import org.bukkit.Location; @@ -19,6 +21,7 @@ import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.util.Util; import world.bentobox.limits.Limits; +import world.bentobox.limits.Settings; public class EntityLimitListener implements Listener { private static final String MOD_BYPASS = "mod.bypass"; @@ -166,6 +169,7 @@ public class EntityLimitListener implements Listener { private boolean atLimit(Island island, Entity ent) { // Check island settings first int limitAmount = -1; + List groups = new ArrayList(); if (addon.getBlockLimitListener().getIsland(island.getUniqueId()) != null) { limitAmount = addon.getBlockLimitListener().getIsland(island.getUniqueId()).getEntityLimit(ent.getType()); } @@ -173,11 +177,28 @@ public class EntityLimitListener implements Listener { if (limitAmount < 0 && addon.getSettings().getLimits().containsKey(ent.getType())) { limitAmount = addon.getSettings().getLimits().get(ent.getType()); } - if (limitAmount < 0) return false; + if (groups.isEmpty() && addon.getSettings().getGroupLimits().containsKey(ent.getType())) { + groups = addon.getSettings().getGroupLimits().get(ent.getType()); + } + if (limitAmount < 0 && groups.isEmpty()) return false; + // We have to count the entities - return ent.getWorld().getEntities().stream() + int count = (int) ent.getWorld().getEntities().stream() .filter(e -> e.getType().equals(ent.getType())) - .filter(e -> island.inIslandSpace(e.getLocation())).count() >= limitAmount; + .filter(e -> island.inIslandSpace(e.getLocation())).count(); + if (count >= limitAmount) + return true; + + // Now do the group limits + for (Settings.EntityGroup group : groups) //do not use lambda + { + count = (int) ent.getWorld().getEntities().stream() + .filter(e -> group.contains(e.getType())) + .filter(e -> island.inIslandSpace(e.getLocation())).count(); + if (count >= group.getLimit()) + return true; + } + return false; } } From 625bbe3a9fb8e71742f2fdb0cda5a8542d5ca147 Mon Sep 17 00:00:00 2001 From: wea_ondara Date: Fri, 10 Apr 2020 16:57:55 +0200 Subject: [PATCH 2/8] show limits in limit command --- .../java/world/bentobox/limits/Settings.java | 30 +++++++++++ .../bentobox/limits/commands/LimitPanel.java | 54 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/src/main/java/world/bentobox/limits/Settings.java b/src/main/java/world/bentobox/limits/Settings.java index 230be6e..82ea0ff 100644 --- a/src/main/java/world/bentobox/limits/Settings.java +++ b/src/main/java/world/bentobox/limits/Settings.java @@ -6,6 +6,7 @@ import java.util.EnumMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -84,6 +85,8 @@ public class Settings { } return null; }).filter(e -> e != null).collect(Collectors.toSet()); + if (entities.isEmpty()) + continue; EntityGroup group = new EntityGroup(name, entities, limit); entities.forEach(e -> { List groups = groupLimits.getOrDefault(e, new ArrayList()); @@ -111,6 +114,10 @@ public class Settings { public Map> getGroupLimits() { return groupLimits; } + + public List getGroupLimitDefinitions() { + return groupLimits.values().stream().flatMap(e -> e.stream()).distinct().collect(Collectors.toList()); + } /** * @return the gameModes @@ -145,5 +152,28 @@ public class Settings { public int getLimit() { return limit; } + + @Override + public int hashCode() + { + int hash = 7; + hash = 83 * hash + Objects.hashCode(this.name); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final EntityGroup other = (EntityGroup) obj; + if (!Objects.equals(this.name, other.name)) + return false; + return true; + } } } diff --git a/src/main/java/world/bentobox/limits/commands/LimitPanel.java b/src/main/java/world/bentobox/limits/commands/LimitPanel.java index c3d3613..f3eb28f 100644 --- a/src/main/java/world/bentobox/limits/commands/LimitPanel.java +++ b/src/main/java/world/bentobox/limits/commands/LimitPanel.java @@ -11,6 +11,8 @@ import org.bukkit.World; import org.bukkit.entity.EntityType; import com.google.common.collect.ImmutableMap; +import java.util.List; +import java.util.stream.Collectors; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.panels.builders.PanelBuilder; @@ -19,6 +21,8 @@ import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.util.Util; import world.bentobox.limits.Limits; +import world.bentobox.limits.Settings; +import world.bentobox.limits.Settings.EntityGroup; import world.bentobox.limits.objects.IslandBlockCount; /** @@ -133,6 +137,37 @@ public class LimitPanel { "[limit]", String.valueOf(v))); pb.item(pib.build()); }); + + // Entity group limits + List groupmap = addon.getSettings().getGroupLimitDefinitions(); + // Merge in any permission-based limits +// if (ibc != null) ibc.getEntityLimits().forEach(map::put); + groupmap.forEach(v -> { + PanelItemBuilder pib = new PanelItemBuilder(); + EntityType k = v.getTypes().iterator().next(); + pib.name(v.getName() + " (" + v.getTypes().stream().map(e -> Util.prettifyText(e.toString())).collect(Collectors.joining(", ")) + ")"); + Material m; + try { + if (E2M.containsKey(k)) { + m = E2M.get(k); + } else if (k.isAlive()) { + m = Material.valueOf(k.toString() + "_SPAWN_EGG"); + } else { + // Regular material + m = Material.valueOf(k.toString()); + } + } catch (Exception e) { + m = Material.BARRIER; + } + pib.icon(m); + long count = getCount(island, v); + String color = count >= v.getLimit() ? user.getTranslation("island.limits.max-color") : user.getTranslation("island.limits.regular-color"); + pib.description(color + + user.getTranslation("island.limits.block-limit-syntax", + TextVariables.NUMBER, String.valueOf(count), + "[limit]", String.valueOf(v.getLimit()))); + pb.item(pib.build()); + }); pb.build(); } @@ -154,4 +189,23 @@ public class LimitPanel { } return count; } + + long getCount(Island island, EntityGroup group) { + long count = island.getWorld().getEntities().stream() + .filter(e -> group.contains(e.getType())) + .filter(e -> island.inIslandSpace(e.getLocation())).count(); + // Nether + if (addon.getPlugin().getIWM().isNetherIslands(island.getWorld()) && addon.getPlugin().getIWM().getNetherWorld(island.getWorld()) != null) { + count += addon.getPlugin().getIWM().getNetherWorld(island.getWorld()).getEntities().stream() + .filter(e -> group.contains(e.getType())) + .filter(e -> island.inIslandSpace(e.getLocation())).count(); + } + // End + if (addon.getPlugin().getIWM().isEndIslands(island.getWorld()) && addon.getPlugin().getIWM().getEndWorld(island.getWorld()) != null) { + count += addon.getPlugin().getIWM().getEndWorld(island.getWorld()).getEntities().stream() + .filter(e -> group.contains(e.getType())) + .filter(e -> island.inIslandSpace(e.getLocation())).count(); + } + return count; + } } From f77c48218a58161568097fd3ea4ce381b91fa1dc Mon Sep 17 00:00:00 2001 From: wea_ondara Date: Sat, 11 Apr 2020 13:53:28 +0200 Subject: [PATCH 3/8] added entity group limits via permissions to islands --- .../java/world/bentobox/limits/Settings.java | 9 +++- .../limits/listeners/EntityLimitListener.java | 26 ++++++++---- .../limits/listeners/JoinListener.java | 8 +++- .../limits/objects/IslandBlockCount.java | 41 +++++++++++++++++++ 4 files changed, 73 insertions(+), 11 deletions(-) diff --git a/src/main/java/world/bentobox/limits/Settings.java b/src/main/java/world/bentobox/limits/Settings.java index 82ea0ff..aa4b194 100644 --- a/src/main/java/world/bentobox/limits/Settings.java +++ b/src/main/java/world/bentobox/limits/Settings.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.EnumMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -84,7 +85,7 @@ public class Settings { addon.logError("Unknown entity type: " + s + " - skipping..."); } return null; - }).filter(e -> e != null).collect(Collectors.toSet()); + }).filter(e -> e != null).collect(Collectors.toCollection(LinkedHashSet::new)); if (entities.isEmpty()) continue; EntityGroup group = new EntityGroup(name, entities, limit); @@ -95,6 +96,9 @@ public class Settings { }); } } + + addon.log("Entity group limits:"); + getGroupLimitDefinitions().stream().map(e -> "Limit " + e.getName() + " to " + e.getLimit()).forEach(addon::log); } private EntityType getType(String key) { @@ -115,6 +119,9 @@ public class Settings { return groupLimits; } + /** + * @return the group limit definitions + */ public List getGroupLimitDefinitions() { return groupLimits.values().stream().flatMap(e -> e.stream()).distinct().collect(Collectors.toList()); } diff --git a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java index 04168da..15df9af 100644 --- a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java +++ b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java @@ -1,8 +1,11 @@ package world.bentobox.limits.listeners; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; import org.bukkit.Location; import org.bukkit.World; @@ -169,18 +172,26 @@ public class EntityLimitListener implements Listener { private boolean atLimit(Island island, Entity ent) { // Check island settings first int limitAmount = -1; - List groups = new ArrayList(); + Map groupsLimits = new HashMap<>(); if (addon.getBlockLimitListener().getIsland(island.getUniqueId()) != null) { limitAmount = addon.getBlockLimitListener().getIsland(island.getUniqueId()).getEntityLimit(ent.getType()); + List groupdefs = addon.getSettings().getGroupLimits().getOrDefault(ent.getType(), new ArrayList()); + groupdefs.forEach(def -> { + int limit = addon.getBlockLimitListener().getIsland(island.getUniqueId()).getEntityGroupLimit(def.getName()); + if (limit >= 0) + groupsLimits.put(def, limit); + }); } // If no island settings then try global settings if (limitAmount < 0 && addon.getSettings().getLimits().containsKey(ent.getType())) { limitAmount = addon.getSettings().getLimits().get(ent.getType()); } - if (groups.isEmpty() && addon.getSettings().getGroupLimits().containsKey(ent.getType())) { - groups = addon.getSettings().getGroupLimits().get(ent.getType()); + if (addon.getSettings().getGroupLimits().containsKey(ent.getType())) { + addon.getSettings().getGroupLimits().getOrDefault(ent.getType(), new ArrayList<>()).stream() + .filter(group -> !groupsLimits.containsKey(group) || groupsLimits.get(group) > group.getLimit()) + .forEach(group -> groupsLimits.put(group, group.getLimit())); } - if (limitAmount < 0 && groups.isEmpty()) return false; + if (limitAmount < 0 && groupsLimits.isEmpty()) return false; // We have to count the entities int count = (int) ent.getWorld().getEntities().stream() @@ -190,12 +201,11 @@ public class EntityLimitListener implements Listener { return true; // Now do the group limits - for (Settings.EntityGroup group : groups) //do not use lambda - { + for (Map.Entry group : groupsLimits.entrySet()) { //do not use lambda count = (int) ent.getWorld().getEntities().stream() - .filter(e -> group.contains(e.getType())) + .filter(e -> group.getKey().contains(e.getType())) .filter(e -> island.inIslandSpace(e.getLocation())).count(); - if (count >= group.getLimit()) + if (count >= group.getValue()) return true; } return false; diff --git a/src/main/java/world/bentobox/limits/listeners/JoinListener.java b/src/main/java/world/bentobox/limits/listeners/JoinListener.java index 612a5de..724b3e8 100644 --- a/src/main/java/world/bentobox/limits/listeners/JoinListener.java +++ b/src/main/java/world/bentobox/limits/listeners/JoinListener.java @@ -23,6 +23,7 @@ import world.bentobox.bentobox.api.events.island.IslandEvent.Reason; import world.bentobox.bentobox.api.events.team.TeamEvent.TeamSetownerEvent; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.limits.Limits; +import world.bentobox.limits.Settings.EntityGroup; import world.bentobox.limits.objects.IslandBlockCount; /** @@ -55,7 +56,7 @@ public class JoinListener implements Listener { // Check formatting String[] split = perms.getPermission().split("\\."); if (split.length != 5) { - logError(player.getName(), perms.getPermission(), "format must be '" + permissionPrefix + "MATERIAL.NUMBER' or '" + permissionPrefix + "ENTITY-TYPE.NUMBER'"); + logError(player.getName(), perms.getPermission(), "format must be '" + permissionPrefix + "MATERIAL.NUMBER', '" + permissionPrefix + "ENTITY-TYPE.NUMBER', or '" + permissionPrefix + "ENTITY-GROUP.NUMBER'"); return; } // Check value @@ -66,6 +67,7 @@ public class JoinListener implements Listener { // 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(e -> e.getName().equalsIgnoreCase(split[3])).findFirst().orElse(null); if (et == null && m == null) { logError(player.getName(), perms.getPermission(), split[3].toUpperCase(Locale.ENGLISH) + " is not a valid material or entity type."); @@ -75,7 +77,9 @@ public class JoinListener implements Listener { if (ibc == null) { ibc = new IslandBlockCount(islandId, gameMode); } - if (et != null && m == null) { + if (entgroup != null) { + ibc.setEntityGroupLimit(entgroup.getName(), Math.max(ibc.getEntityGroupLimit(entgroup.getName()), Integer.valueOf(split[4]))); + } else if (et != null && m == null) { // Entity limit ibc.setEntityLimit(et, Math.max(ibc.getEntityLimit(et), Integer.valueOf(split[4]))); } else if (m != null && et == null) { diff --git a/src/main/java/world/bentobox/limits/objects/IslandBlockCount.java b/src/main/java/world/bentobox/limits/objects/IslandBlockCount.java index b94b265..f9ac2db 100644 --- a/src/main/java/world/bentobox/limits/objects/IslandBlockCount.java +++ b/src/main/java/world/bentobox/limits/objects/IslandBlockCount.java @@ -1,6 +1,7 @@ package world.bentobox.limits.objects; import java.util.EnumMap; +import java.util.HashMap; import java.util.Map; import org.bukkit.Material; @@ -32,6 +33,8 @@ public class IslandBlockCount implements DataObject { private Map blockLimits = new EnumMap<>(Material.class); @Expose private Map entityLimits = new EnumMap<>(EntityType.class); + @Expose + private Map entityGroupLimits = new HashMap<>(); // Required for YAML database public IslandBlockCount() {} @@ -201,4 +204,42 @@ public class IslandBlockCount implements DataObject { entityLimits.clear(); } + /** + * @return the entityGroupLimits + */ + public Map getEntityGroupLimits() { + return entityGroupLimits; + } + + /** + * @param entityGroupLimits the entityGroupLimits to set + */ + public void setEntityGroupLimits(Map entityGroupLimits) { + this.entityGroupLimits = entityGroupLimits; + } + + /** + * Set an island-specific entity group limit + * @param name - entity group + * @param limit - limit + */ + public void setEntityGroupLimit(String name, int limit) { + entityGroupLimits.put(name, limit); + } + + /** + * Get the limit for an entity group + * @param name - entity group + * @return limit or -1 for unlimited + */ + public int getEntityGroupLimit(String name) { + return entityGroupLimits.getOrDefault(name, -1); + } + + /** + * Clear all island-specific entity group limits + */ + public void clearEntityGroupLimits() { + entityGroupLimits.clear(); + } } From f25c027a2b721a3ec443cfb52c17d39edbd80a25 Mon Sep 17 00:00:00 2001 From: wea_ondara Date: Sat, 11 Apr 2020 17:42:18 +0200 Subject: [PATCH 4/8] adjust test cases to previous changes --- .../java/world/bentobox/limits/Settings.java | 6 ++++ .../limits/listeners/JoinListener.java | 6 ++-- .../limits/listeners/JoinListenerTest.java | 29 +++++++++++++++++-- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/main/java/world/bentobox/limits/Settings.java b/src/main/java/world/bentobox/limits/Settings.java index aa4b194..8905480 100644 --- a/src/main/java/world/bentobox/limits/Settings.java +++ b/src/main/java/world/bentobox/limits/Settings.java @@ -182,5 +182,11 @@ public class Settings { return false; return true; } + + @Override + public String toString() + { + return "EntityGroup{" + "name=" + name + ", types=" + types + ", limit=" + limit + '}'; + } } } diff --git a/src/main/java/world/bentobox/limits/listeners/JoinListener.java b/src/main/java/world/bentobox/limits/listeners/JoinListener.java index 724b3e8..e2fbf4f 100644 --- a/src/main/java/world/bentobox/limits/listeners/JoinListener.java +++ b/src/main/java/world/bentobox/limits/listeners/JoinListener.java @@ -44,6 +44,7 @@ public class JoinListener implements Listener { if (ibc != null) { // Clear permission limits ibc.getEntityLimits().clear(); + ibc.getEntityGroupLimits().clear(); ibc.getBlockLimits().clear(); } for (PermissionAttachmentInfo perms : player.getEffectivePermissions()) { @@ -69,8 +70,8 @@ public class JoinListener implements Listener { Material m = Arrays.stream(Material.values()).filter(t -> t.name().equalsIgnoreCase(split[3])).findFirst().orElse(null); EntityGroup entgroup = addon.getSettings().getGroupLimitDefinitions().stream().filter(e -> e.getName().equalsIgnoreCase(split[3])).findFirst().orElse(null); - if (et == null && m == null) { - logError(player.getName(), perms.getPermission(), split[3].toUpperCase(Locale.ENGLISH) + " is not a valid material or entity type."); + 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 @@ -78,6 +79,7 @@ public class JoinListener implements Listener { ibc = new IslandBlockCount(islandId, gameMode); } if (entgroup != null) { + // Entity group limit ibc.setEntityGroupLimit(entgroup.getName(), Math.max(ibc.getEntityGroupLimit(entgroup.getName()), Integer.valueOf(split[4]))); } else if (et != null && m == null) { // Entity limit diff --git a/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java b/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java index 366bf5f..be1c84a 100644 --- a/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java +++ b/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java @@ -1,5 +1,7 @@ package bentobox.addon.limits.listeners; +import java.util.ArrayList; +import java.util.Arrays; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -38,6 +40,7 @@ import world.bentobox.bentobox.api.events.team.TeamEvent.TeamSetownerEvent; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.limits.Limits; +import world.bentobox.limits.Settings; import world.bentobox.limits.listeners.BlockLimitsListener; import world.bentobox.limits.listeners.JoinListener; import world.bentobox.limits.objects.IslandBlockCount; @@ -53,6 +56,8 @@ public class JoinListenerTest { @Mock private Limits addon; @Mock + private Settings settings; + @Mock private GameModeAddon bskyblock; @Mock private Player player; @@ -76,6 +81,9 @@ public class JoinListenerTest { when(addon.getGameModes()).thenReturn(Collections.singletonList(bskyblock)); when(addon.getGameModeName(any())).thenReturn("bskyblock"); when(addon.getGameModePermPrefix(any())).thenReturn("bskyblock."); + when(addon.getSettings()).thenReturn(settings); + // Settings + when(settings.getGroupLimitDefinitions()).thenReturn(new ArrayList(Arrays.asList(new Settings.EntityGroup("friendly", new HashSet<>(), -1)))); // Island Manager when(im.hasIsland(any(), any(UUID.class))).thenReturn(true); when(island.getUniqueId()).thenReturn("unique_id"); @@ -244,7 +252,7 @@ public class JoinListenerTest { when(player.getEffectivePermissions()).thenReturn(perms); PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); jl.onPlayerJoin(e); - verify(addon).logError("Player tastybento has permission: 'bskyblock.island.limit.my.perm.for.game' but format must be 'bskyblock.island.limit.MATERIAL.NUMBER' or 'bskyblock.island.limit.ENTITY-TYPE.NUMBER' Ignoring..."); + verify(addon).logError("Player tastybento has permission: 'bskyblock.island.limit.my.perm.for.game' but format must be 'bskyblock.island.limit.MATERIAL.NUMBER', 'bskyblock.island.limit.ENTITY-TYPE.NUMBER', or 'bskyblock.island.limit.ENTITY-GROUP.NUMBER' Ignoring..."); } /** @@ -260,7 +268,7 @@ public class JoinListenerTest { when(player.getEffectivePermissions()).thenReturn(perms); PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); jl.onPlayerJoin(e); - verify(addon).logError("Player tastybento has permission: 'bskyblock.island.limit.mumbo.34' but MUMBO is not a valid material or entity type. Ignoring..."); + verify(addon).logError("Player tastybento has permission: 'bskyblock.island.limit.mumbo.34' but MUMBO is not a valid material or entity type/group. Ignoring..."); } /** @@ -328,6 +336,23 @@ public class JoinListenerTest { verify(addon, never()).logError(anyString()); verify(ibc).setEntityLimit(eq(EntityType.BAT), eq(24)); } + + /** + * Test method for {@link world.bentobox.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. + */ + @Test + public void testOnPlayerJoinWithPermLimitsSuccessEntityGroup() { + Set perms = new HashSet<>(); + PermissionAttachmentInfo permAtt = mock(PermissionAttachmentInfo.class); + when(permAtt.getPermission()).thenReturn("bskyblock.island.limit.friendly.24"); + when(permAtt.getValue()).thenReturn(true); + perms.add(permAtt); + when(player.getEffectivePermissions()).thenReturn(perms); + PlayerJoinEvent e = new PlayerJoinEvent(player, "welcome"); + jl.onPlayerJoin(e); + verify(addon, never()).logError(anyString()); + verify(ibc).setEntityGroupLimit(eq("friendly"), eq(24)); + } /** * Test method for {@link world.bentobox.limits.listeners.JoinListener#onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent)}. From 346f2b8ed83dd38a1276fd9a504ec6d583880c59 Mon Sep 17 00:00:00 2001 From: wea_ondara Date: Sat, 11 Apr 2020 20:59:54 +0200 Subject: [PATCH 5/8] integrate group limits into limit messages in entity listener --- .../limits/listeners/EntityLimitListener.java | 86 +++++++++++++++---- 1 file changed, 68 insertions(+), 18 deletions(-) diff --git a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java index 15df9af..c385c4b 100644 --- a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java +++ b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java @@ -1,5 +1,6 @@ package world.bentobox.limits.listeners; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -10,6 +11,7 @@ import java.util.stream.Collectors; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -25,6 +27,7 @@ import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.util.Util; import world.bentobox.limits.Limits; import world.bentobox.limits.Settings; +import world.bentobox.limits.Settings.EntityGroup; public class EntityLimitListener implements Listener { private static final String MOD_BYPASS = "mod.bypass"; @@ -60,14 +63,21 @@ public class EntityLimitListener implements Listener { return; } // Check if the player is at the limit - if (!bypass && atLimit(island, e.getVehicle())) { + AtLimitResult res; + if (!bypass && (res = atLimit(island, e.getVehicle())).hit()) { e.setCancelled(true); for (Entity ent : e.getVehicle().getLocation().getWorld().getNearbyEntities(e.getVehicle().getLocation(), 5, 5, 5)) { if (ent instanceof Player) { ((Player) ent).updateInventory(); - User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]", - Util.prettifyText(e.getVehicle().getType().toString()) - , TextVariables.NUMBER, String.valueOf(addon.getSettings().getLimits().get(e.getVehicle().getType()))); + if (res.getTypelimit() != null) { + User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]", + Util.prettifyText(e.getVehicle().getType().toString()), + TextVariables.NUMBER, String.valueOf(res.getTypelimit().getValue())); + } else { + User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]", + res.getGrouplimit().getKey().getName() + " (" + res.getGrouplimit().getKey().getTypes().stream().map(x -> Util.prettifyText(x.toString())).collect(Collectors.joining(", ")) + ")", + TextVariables.NUMBER, String.valueOf(res.getGrouplimit().getValue())); + } } } } @@ -128,13 +138,19 @@ public class EntityLimitListener implements Listener { addon.getIslands().getIslandAt(e.getEntity().getLocation()).ifPresent(island -> { boolean bypass = Objects.requireNonNull(player).isOp() || player.hasPermission(addon.getPlugin().getIWM().getPermissionPrefix(e.getEntity().getWorld()) + MOD_BYPASS); // Check if entity can be hung - if (!bypass && !island.isSpawn() && atLimit(island, e.getEntity())) { + AtLimitResult res; + if (!bypass && !island.isSpawn() && (res = atLimit(island, e.getEntity())).hit()) { // Not allowed e.setCancelled(true); - User.getInstance(player).notify("block-limits.hit-limit", "[material]", - Util.prettifyText(e.getEntity().getType().toString()), - TextVariables.NUMBER, String.valueOf(addon.getSettings().getLimits().getOrDefault(e.getEntity().getType(), -1))); - + if (res.getTypelimit() != null) { + User.getInstance(player).notify("block-limits.hit-limit", "[material]", + Util.prettifyText(e.getEntity().getType().toString()), + TextVariables.NUMBER, String.valueOf(res.getTypelimit().getValue())); + } else { + User.getInstance(player).notify("block-limits.hit-limit", "[material]", + res.getGrouplimit().getKey().getName() + " (" + res.getGrouplimit().getKey().getTypes().stream().map(x -> Util.prettifyText(x.toString())).collect(Collectors.joining(", ")) + ")", + TextVariables.NUMBER, String.valueOf(res.getGrouplimit().getValue())); + } } }); } @@ -142,7 +158,8 @@ public class EntityLimitListener implements Listener { private void checkLimit(CreatureSpawnEvent e, boolean bypass) { addon.getIslands().getIslandAt(e.getLocation()).ifPresent(island -> { // Check if creature is allowed to spawn or not - if (!bypass && !island.isSpawn() && atLimit(island, e.getEntity())) { + AtLimitResult res; + if (!bypass && !island.isSpawn() && (res = atLimit(island, e.getEntity())).hit()) { // Not allowed e.setCancelled(true); // If the reason is anything but because of a spawner then tell players within range @@ -151,9 +168,15 @@ public class EntityLimitListener implements Listener { if (w == null) return; for (Entity ent : w.getNearbyEntities(e.getLocation(), 5, 5, 5)) { if (ent instanceof Player) { - User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]", - Util.prettifyText(e.getEntityType().toString()), - TextVariables.NUMBER, String.valueOf(addon.getSettings().getLimits().get(e.getEntityType()))); + if (res.getTypelimit() != null) { + User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]", + Util.prettifyText(e.getEntityType().toString()), + TextVariables.NUMBER, String.valueOf(res.getTypelimit().getValue())); + } else { + User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]", + res.getGrouplimit().getKey().getName() + " (" + res.getGrouplimit().getKey().getTypes().stream().map(x -> Util.prettifyText(x.toString())).collect(Collectors.joining(", ")) + ")", + TextVariables.NUMBER, String.valueOf(res.getGrouplimit().getValue())); + } } } } @@ -169,7 +192,7 @@ public class EntityLimitListener implements Listener { * @param ent - the entity * @return true if at the limit, false if not */ - private boolean atLimit(Island island, Entity ent) { + private AtLimitResult atLimit(Island island, Entity ent) { // Check island settings first int limitAmount = -1; Map groupsLimits = new HashMap<>(); @@ -191,14 +214,14 @@ public class EntityLimitListener implements Listener { .filter(group -> !groupsLimits.containsKey(group) || groupsLimits.get(group) > group.getLimit()) .forEach(group -> groupsLimits.put(group, group.getLimit())); } - if (limitAmount < 0 && groupsLimits.isEmpty()) return false; + if (limitAmount < 0 && groupsLimits.isEmpty()) return new AtLimitResult(); // We have to count the entities int count = (int) ent.getWorld().getEntities().stream() .filter(e -> e.getType().equals(ent.getType())) .filter(e -> island.inIslandSpace(e.getLocation())).count(); if (count >= limitAmount) - return true; + return new AtLimitResult(ent.getType(), limitAmount); // Now do the group limits for (Map.Entry group : groupsLimits.entrySet()) { //do not use lambda @@ -206,9 +229,36 @@ public class EntityLimitListener implements Listener { .filter(e -> group.getKey().contains(e.getType())) .filter(e -> island.inIslandSpace(e.getLocation())).count(); if (count >= group.getValue()) - return true; + return new AtLimitResult(group.getKey(), group.getValue()); + } + return new AtLimitResult(); + } + + private class AtLimitResult { + private Map.Entry typelimit; + private Map.Entry grouplimit; + + public AtLimitResult() {} + + public AtLimitResult(EntityType type, int limit) { + typelimit = new AbstractMap.SimpleEntry<>(type, limit); + } + + public AtLimitResult(EntityGroup type, int limit) { + grouplimit = new AbstractMap.SimpleEntry<>(type, limit); + } + + public boolean hit() { + return typelimit != null || grouplimit != null; + } + + public Map.Entry getTypelimit() { + return typelimit; + } + + public Map.Entry getGrouplimit() { + return grouplimit; } - return false; } } From cc6781bf4446f7a41300e55e5411e695ce080327 Mon Sep 17 00:00:00 2001 From: wea_ondara Date: Sun, 12 Apr 2020 13:38:21 +0200 Subject: [PATCH 6/8] fix group limits when limit is -1 --- .../world/bentobox/limits/listeners/EntityLimitListener.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java index c385c4b..58964c4 100644 --- a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java +++ b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java @@ -225,6 +225,8 @@ public class EntityLimitListener implements Listener { // Now do the group limits for (Map.Entry group : groupsLimits.entrySet()) { //do not use lambda + if (group.getValue() < 0) + continue; count = (int) ent.getWorld().getEntities().stream() .filter(e -> group.getKey().contains(e.getType())) .filter(e -> island.inIslandSpace(e.getLocation())).count(); From 54cb8b3a10eb3825d60dd3087d657ae9c56a4adc Mon Sep 17 00:00:00 2001 From: wea_ondara Date: Sun, 12 Apr 2020 14:39:19 +0200 Subject: [PATCH 7/8] fix limits for simple entity limit --- src/main/java/world/bentobox/limits/Settings.java | 2 +- .../limits/listeners/EntityLimitListener.java | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/world/bentobox/limits/Settings.java b/src/main/java/world/bentobox/limits/Settings.java index 8905480..d753e65 100644 --- a/src/main/java/world/bentobox/limits/Settings.java +++ b/src/main/java/world/bentobox/limits/Settings.java @@ -98,7 +98,7 @@ public class Settings { } addon.log("Entity group limits:"); - getGroupLimitDefinitions().stream().map(e -> "Limit " + e.getName() + " to " + e.getLimit()).forEach(addon::log); + getGroupLimitDefinitions().stream().map(e -> "Limit " + e.getName() + " (" + e.getTypes().stream().map(x -> x.name()).collect(Collectors.joining(", ")) + ") to " + e.getLimit()).forEach(addon::log); } private EntityType getType(String key) { diff --git a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java index 58964c4..2d99b6a 100644 --- a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java +++ b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java @@ -217,17 +217,20 @@ public class EntityLimitListener implements Listener { if (limitAmount < 0 && groupsLimits.isEmpty()) return new AtLimitResult(); // We have to count the entities - int count = (int) ent.getWorld().getEntities().stream() - .filter(e -> e.getType().equals(ent.getType())) - .filter(e -> island.inIslandSpace(e.getLocation())).count(); - if (count >= limitAmount) - return new AtLimitResult(ent.getType(), limitAmount); + if (limitAmount >= 0) + { + int count = (int) ent.getWorld().getEntities().stream() + .filter(e -> e.getType().equals(ent.getType())) + .filter(e -> island.inIslandSpace(e.getLocation())).count(); + if (count >= limitAmount) + return new AtLimitResult(ent.getType(), limitAmount); + } // Now do the group limits for (Map.Entry group : groupsLimits.entrySet()) { //do not use lambda if (group.getValue() < 0) continue; - count = (int) ent.getWorld().getEntities().stream() + int count = (int) ent.getWorld().getEntities().stream() .filter(e -> group.getKey().contains(e.getType())) .filter(e -> island.inIslandSpace(e.getLocation())).count(); if (count >= group.getValue()) From dafc710c486c465c7c4577858f1fef982d025f9f Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 21 Jun 2020 19:50:46 +0200 Subject: [PATCH 8/8] move entities from Name to description to add a newline after 5 entries --- .../bentobox/limits/commands/LimitPanel.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/java/world/bentobox/limits/commands/LimitPanel.java b/src/main/java/world/bentobox/limits/commands/LimitPanel.java index f2b5b2b..16704b3 100644 --- a/src/main/java/world/bentobox/limits/commands/LimitPanel.java +++ b/src/main/java/world/bentobox/limits/commands/LimitPanel.java @@ -12,8 +12,8 @@ import org.bukkit.World; import org.bukkit.entity.EntityType; import com.google.common.collect.ImmutableMap; +import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.panels.builders.PanelBuilder; @@ -146,7 +146,9 @@ public class LimitPanel { groupmap.forEach(v -> { PanelItemBuilder pib = new PanelItemBuilder(); EntityType k = v.getTypes().iterator().next(); - pib.name(v.getName() + " (" + v.getTypes().stream().map(e -> Util.prettifyText(e.toString())).collect(Collectors.joining(", ")) + ")"); + pib.name(v.getName()); + String description = ""; + description += "(" + prettyNames(v) + ")\n"; Material m; try { if (E2M.containsKey(k)) { @@ -163,10 +165,11 @@ public class LimitPanel { pib.icon(m); long count = getCount(island, v); String color = count >= v.getLimit() ? user.getTranslation("island.limits.max-color") : user.getTranslation("island.limits.regular-color"); - pib.description(color - + user.getTranslation("island.limits.block-limit-syntax", + description += color + + user.getTranslation("island.limits.block-limit-syntax", TextVariables.NUMBER, String.valueOf(count), - "[limit]", String.valueOf(v.getLimit()))); + "[limit]", String.valueOf(v.getLimit())); + pib.description(description); pb.item(pib.build()); }); pb.build(); @@ -209,4 +212,18 @@ public class LimitPanel { } return count; } + + private String prettyNames(EntityGroup v) { + StringBuilder sb = new StringBuilder(); + List l = new ArrayList<>(v.getTypes()); + for(int i = 0; i < l.size(); i++) + { + sb.append(Util.prettifyText(l.get(i).toString())); + if (i + 1 < l.size()) + sb.append(", "); + if((i+1) % 5 == 0) + sb.append("\n"); + } + return sb.toString(); + } }