diff --git a/src/main/java/world/bentobox/limits/EntityGroup.java b/src/main/java/world/bentobox/limits/EntityGroup.java new file mode 100644 index 0000000..7f077f8 --- /dev/null +++ b/src/main/java/world/bentobox/limits/EntityGroup.java @@ -0,0 +1,72 @@ +package world.bentobox.limits; + +import java.util.Objects; +import java.util.Set; + +import org.bukkit.Material; +import org.bukkit.entity.EntityType; + +/** + * A named class representing a group of entities and their limits + * + */ +public class EntityGroup { + private final String name; + private final Set types; + private final int limit; + private final Material icon; + + public EntityGroup(String name, Set types, int limit, Material icon) { + this.name = name; + this.types = types; + this.limit = limit; + this.icon = icon; + } + + public boolean contains(EntityType type) { + return types.contains(type); + } + + public String getName() { + return name; + } + + public Set getTypes() { + return types; + } + + 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; + return Objects.equals(this.name, other.name); + } + + /** + * @return the icon + */ + public Material getIcon() { + return Objects.requireNonNullElse(icon, Material.BARRIER); + } + + @Override + public String toString() { + return "EntityGroup [name=" + name + ", types=" + types + ", limit=" + limit + ", icon=" + icon + "]"; + } +} \ No newline at end of file diff --git a/src/main/java/world/bentobox/limits/Settings.java b/src/main/java/world/bentobox/limits/Settings.java index db0f71e..bc93a41 100644 --- a/src/main/java/world/bentobox/limits/Settings.java +++ b/src/main/java/world/bentobox/limits/Settings.java @@ -1,8 +1,19 @@ package world.bentobox.limits; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; +import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; @@ -68,6 +79,14 @@ public class Settings { if (el != null) { for (String name : el.getKeys(false)) { int limit = el.getInt(name + ".limit"); + String iconName = el.getString(name + ".icon", "BARRIER"); + Material icon = Material.BARRIER; + try { + icon = Material.valueOf(iconName.toUpperCase(Locale.ENGLISH)); + } catch (Exception e) { + addon.logError("Invalid group icon name: " + iconName + ". Use a Bukkit Material."); + icon = Material.BARRIER; + } Set entities = el.getStringList(name + ".entities").stream().map(s -> { EntityType type = getType(s); if (type != null) { @@ -83,7 +102,7 @@ public class Settings { }).filter(Objects::nonNull).collect(Collectors.toCollection(LinkedHashSet::new)); if (entities.isEmpty()) continue; - EntityGroup group = new EntityGroup(name, entities, limit); + EntityGroup group = new EntityGroup(name, entities, limit, icon); entities.forEach(e -> { List groups = groupLimits.getOrDefault(e, new ArrayList<>()); groups.add(group); @@ -128,65 +147,6 @@ public class Settings { return gameModes; } - /** - * A named class representing a group of entities and their limits - * - */ - 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; - } - - @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; - return Objects.equals(this.name, other.name); - } - - @Override - public String toString() - { - return "EntityGroup{" + "name=" + name + ", types=" + types + ", limit=" + limit + '}'; - } - } - /** * @return the asyncGolums */ diff --git a/src/main/java/world/bentobox/limits/commands/admin/OffsetCommand.java b/src/main/java/world/bentobox/limits/commands/admin/OffsetCommand.java index b04b206..3ab71b9 100644 --- a/src/main/java/world/bentobox/limits/commands/admin/OffsetCommand.java +++ b/src/main/java/world/bentobox/limits/commands/admin/OffsetCommand.java @@ -7,13 +7,19 @@ package world.bentobox.limits.commands.admin; -import com.google.common.base.Enums; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.entity.EntityType; import org.eclipse.jdt.annotation.Nullable; -import java.util.*; -import java.util.stream.Collectors; + +import com.google.common.base.Enums; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; diff --git a/src/main/java/world/bentobox/limits/commands/player/LimitTab.java b/src/main/java/world/bentobox/limits/commands/player/LimitTab.java index 0d7b1cb..dfba93b 100644 --- a/src/main/java/world/bentobox/limits/commands/player/LimitTab.java +++ b/src/main/java/world/bentobox/limits/commands/player/LimitTab.java @@ -1,7 +1,13 @@ package world.bentobox.limits.commands.player; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; import org.bukkit.Material; @@ -18,8 +24,8 @@ import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.util.Util; +import world.bentobox.limits.EntityGroup; import world.bentobox.limits.Limits; -import world.bentobox.limits.Settings.EntityGroup; import world.bentobox.limits.objects.IslandBlockCount; /** @@ -32,8 +38,11 @@ public class LimitTab implements Tab { A2Z, Z2A } - // This maps the entity types to the icon that should be shown in the panel - // If the icon is null, then the entity type is not covered by the addon + + /** + * This maps the entity types to the icon that should be shown in the panel + * If the icon is null, then the entity type is not covered by the addon + */ private static final Map E2M = ImmutableMap.builder() .put(EntityType.MOOSHROOM, Material.MOOSHROOM_SPAWN_EGG).put(EntityType.SNOW_GOLEM, Material.SNOW_BLOCK) .put(EntityType.IRON_GOLEM, Material.IRON_BLOCK) @@ -110,24 +119,10 @@ public class LimitTab implements Tab { }); groupMap.forEach((v, limit) -> { PanelItemBuilder pib = new PanelItemBuilder(); - EntityType k = v.getTypes().iterator().next(); pib.name(v.getName()); String description = ""; description += "(" + prettyNames(v) + ")\n"; - Material m; - try { - if (E2M.containsKey(k)) { - m = E2M.get(k); - } else if (k.isAlive()) { - m = Material.valueOf(k + "_SPAWN_EGG"); - } else { - // Regular material - m = Material.valueOf(k.toString()); - } - } catch (Exception e) { - m = Material.BARRIER; - } - pib.icon(m); + pib.icon(v.getIcon()); long count = getCount(island, v); String color = count >= limit ? user.getTranslation("island.limits.max-color") : user.getTranslation("island.limits.regular-color"); description += color diff --git a/src/main/java/world/bentobox/limits/events/LimitsPermCheckEvent.java b/src/main/java/world/bentobox/limits/events/LimitsPermCheckEvent.java index aa700de..17d40e8 100644 --- a/src/main/java/world/bentobox/limits/events/LimitsPermCheckEvent.java +++ b/src/main/java/world/bentobox/limits/events/LimitsPermCheckEvent.java @@ -6,7 +6,7 @@ import org.bukkit.entity.Player; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import world.bentobox.limits.Settings.EntityGroup; +import world.bentobox.limits.EntityGroup; import world.bentobox.limits.objects.IslandBlockCount; /** diff --git a/src/main/java/world/bentobox/limits/listeners/BlockLimitsListener.java b/src/main/java/world/bentobox/limits/listeners/BlockLimitsListener.java index 5d64bd4..35e2ead 100644 --- a/src/main/java/world/bentobox/limits/listeners/BlockLimitsListener.java +++ b/src/main/java/world/bentobox/limits/listeners/BlockLimitsListener.java @@ -1,6 +1,14 @@ package world.bentobox.limits.listeners; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -15,7 +23,19 @@ import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.block.*; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockExplodeEvent; +import org.bukkit.event.block.BlockFadeEvent; +import org.bukkit.event.block.BlockFormEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockGrowEvent; +import org.bukkit.event.block.BlockMultiPlaceEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockSpreadEvent; +import org.bukkit.event.block.EntityBlockFormEvent; +import org.bukkit.event.block.LeavesDecayEvent; import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.player.PlayerInteractEvent; diff --git a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java index 593f3eb..31b21a1 100644 --- a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java +++ b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java @@ -17,11 +17,11 @@ import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Breedable; -import org.bukkit.entity.Villager; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.entity.Villager; import org.bukkit.event.Cancellable; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -38,9 +38,9 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.util.Util; +import world.bentobox.limits.EntityGroup; import world.bentobox.limits.Limits; import world.bentobox.limits.Settings; -import world.bentobox.limits.Settings.EntityGroup; import world.bentobox.limits.objects.IslandBlockCount; public class EntityLimitListener implements Listener { @@ -373,7 +373,7 @@ public class EntityLimitListener implements Listener { AtLimitResult atLimit(Island island, Entity ent) { // Check island settings first int limitAmount = -1; - Map groupsLimits = new HashMap<>(); + Map groupsLimits = new HashMap<>(); @Nullable IslandBlockCount ibc = addon.getBlockLimitListener().getIsland(island.getUniqueId()); @@ -381,7 +381,8 @@ public class EntityLimitListener implements Listener { // Get the limit amount for this type limitAmount = ibc.getEntityLimit(ent.getType()); // Handle entity groups - List groupdefs = addon.getSettings().getGroupLimits().getOrDefault(ent.getType(), new ArrayList<>()); + List groupdefs = addon.getSettings().getGroupLimits().getOrDefault(ent.getType(), + new ArrayList<>()); groupdefs.forEach(def -> { int limit = ibc.getEntityGroupLimit(def.getName()); if (limit >= 0) @@ -422,7 +423,7 @@ public class EntityLimitListener implements Listener { .forEach(e -> groupsLimits.put(groupbyname.get(e.getKey()), e.getValue())); } // Now do the group limits - for (Map.Entry group : groupsLimits.entrySet()) { //do not use lambda + for (Map.Entry group : groupsLimits.entrySet()) { //do not use lambda if (group.getValue() < 0) continue; // int count = (int) ent.getWorld().getEntities().stream() diff --git a/src/main/java/world/bentobox/limits/listeners/JoinListener.java b/src/main/java/world/bentobox/limits/listeners/JoinListener.java index e78d72f..9a32157 100644 --- a/src/main/java/world/bentobox/limits/listeners/JoinListener.java +++ b/src/main/java/world/bentobox/limits/listeners/JoinListener.java @@ -22,8 +22,8 @@ import world.bentobox.bentobox.api.events.island.IslandEvent; import world.bentobox.bentobox.api.events.island.IslandEvent.Reason; import world.bentobox.bentobox.api.events.team.TeamSetownerEvent; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.limits.EntityGroup; import world.bentobox.limits.Limits; -import world.bentobox.limits.Settings.EntityGroup; import world.bentobox.limits.events.LimitsJoinPermCheckEvent; import world.bentobox.limits.events.LimitsPermCheckEvent; import world.bentobox.limits.objects.IslandBlockCount; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 30f8c61..41b1b0f 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -40,4 +40,91 @@ worlds: entitylimits: ENDERMAN: 5 CHICKEN: 10 + +# Entity Groups +# Name the group anything you like +# Select an icon, which is a Bukkit Material +# Select the limit for the total group +# List the entities in the group using Bukkit EntityTypes +entitygrouplimits: + Monsters: + icon: ROTTEN_FLESH + limit: 250 + entities: + - SKELETON + - SILVERFISH + - STRAY + - ZOMBIE_VILLAGER + - WITHER + - WARDEN + - BLAZE + - DROWNED + - BREEZE + - ZOMBIFIED_PIGLIN + - EVOKER + - PILLAGER + - HUSK + - CREEPER + - VINDICATOR + - ZOMBIE + - ENDERMAN + - ELDER_GUARDIAN + - WITHER_SKELETON + - CAVE_SPIDER + - GUARDIAN + - RAVAGER + - PIGLIN + - BOGGED + - WITCH + - ENDERMITE + - ZOGLIN + - PIGLIN_BRUTE + - ILLUSIONER + - SPIDER + - VEX + Animals: + icon: SADDLE + limit: 200 + entities: + - SHEEP + - AXOLOTL + - DONKEY + - MOOSHROOM + - TRADER_LLAMA + - BEE + - HORSE + - ZOMBIE_HORSE + - PIG + - PARROT + - CHICKEN + - RABBIT + - SNIFFER + - FROG + - GOAT + - PANDA + - CAMEL + - STRIDER + - TURTLE + - CAT + - SKELETON_HORSE + - COW + - LLAMA + - ARMADILLO + - HOGLIN + - POLAR_BEAR + - WOLF + - MULE + - OCELOT + - FOX + - DOLPHIN + - COD + - PUFFERFISH + - TADPOLE + - SQUID + - SALMON + - TROPICAL_FISH + - GLOW_SQUID + + + diff --git a/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java b/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java index cb1ec03..f104607 100644 --- a/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java +++ b/src/test/java/bentobox/addon/limits/listeners/JoinListenerTest.java @@ -40,6 +40,7 @@ import world.bentobox.bentobox.api.events.island.IslandEvent; import world.bentobox.bentobox.api.events.team.TeamSetownerEvent; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.IslandsManager; +import world.bentobox.limits.EntityGroup; import world.bentobox.limits.Limits; import world.bentobox.limits.Settings; import world.bentobox.limits.listeners.BlockLimitsListener; @@ -87,7 +88,7 @@ public class JoinListenerTest { when(addon.getSettings()).thenReturn(settings); // Settings when(settings.getGroupLimitDefinitions()) - .thenReturn(new ArrayList<>(List.of(new Settings.EntityGroup("friendly", new HashSet<>(), -1)))); + .thenReturn(new ArrayList<>(List.of(new EntityGroup("friendly", new HashSet<>(), -1, null)))); // Island Manager when(island.getUniqueId()).thenReturn("unique_id"); when(im.getIsland(any(), any(UUID.class))).thenReturn(island);