From ffeb4a73861905003cc696cdcf983f43921b8219 Mon Sep 17 00:00:00 2001 From: tastybento Date: Mon, 22 Apr 2019 15:50:15 -0700 Subject: [PATCH] Adds entity limits https://github.com/BentoBoxWorld/addon-limits/issues/15 --- pom.xml | 2 +- .../java/bentobox/addon/limits/Limits.java | 2 + .../java/bentobox/addon/limits/Settings.java | 12 +- .../addon/limits/commands/CalcCommand.java | 3 +- .../addon/limits/commands/LimitPanel.java | 78 ++++++ .../limits/listeners/EntityLimitListener.java | 145 ++++++++++ .../listeners/EntityLimitsListener.java | 257 ------------------ src/main/resources/config.yml | 9 + 8 files changed, 248 insertions(+), 260 deletions(-) create mode 100644 src/main/java/bentobox/addon/limits/listeners/EntityLimitListener.java delete mode 100644 src/main/java/bentobox/addon/limits/listeners/EntityLimitsListener.java diff --git a/pom.xml b/pom.xml index 94743cb..2a32c67 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 world.bentobox limits - 0.1.1-SNAPSHOT + 0.2.0-SNAPSHOT addon-limits An add-on for BentoBox that limits blocks and entities on islands. https://github.com/BentoBoxWorld/addon-level diff --git a/src/main/java/bentobox/addon/limits/Limits.java b/src/main/java/bentobox/addon/limits/Limits.java index d6d98ec..8064fef 100644 --- a/src/main/java/bentobox/addon/limits/Limits.java +++ b/src/main/java/bentobox/addon/limits/Limits.java @@ -8,6 +8,7 @@ import org.bukkit.World; import bentobox.addon.limits.commands.AdminCommand; import bentobox.addon.limits.commands.PlayerCommand; import bentobox.addon.limits.listeners.BlockLimitsListener; +import bentobox.addon.limits.listeners.EntityLimitListener; import bentobox.addon.limits.listeners.JoinListener; import world.bentobox.bentobox.api.addons.Addon; import world.bentobox.bentobox.api.addons.GameModeAddon; @@ -53,6 +54,7 @@ public class Limits extends Addon { blockLimitListener = new BlockLimitsListener(this); registerListener(blockLimitListener); registerListener(new JoinListener(this)); + registerListener(new EntityLimitListener(this)); // Done } diff --git a/src/main/java/bentobox/addon/limits/Settings.java b/src/main/java/bentobox/addon/limits/Settings.java index c48deef..07b9233 100644 --- a/src/main/java/bentobox/addon/limits/Settings.java +++ b/src/main/java/bentobox/addon/limits/Settings.java @@ -8,6 +8,8 @@ import java.util.Map; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; +import bentobox.addon.limits.commands.LimitPanel; + public class Settings { private final Map limits = new HashMap<>(); @@ -23,10 +25,18 @@ public class Settings { for (String key : el.getKeys(false)) { EntityType type = getType(key); if (type != null) { - limits.put(type, el.getInt(key, 0)); + if (!type.isSpawnable() || (LimitPanel.E2M.containsKey(type) && LimitPanel.E2M.get(type) == null)) { + addon.logError("Entity type: " + key + " is not supported - skipping..."); + } else { + limits.put(type, el.getInt(key, 0)); + } + } else { + addon.logError("Unknown entity type: " + key + " - skipping..."); } } } + addon.log("Entity limits:"); + limits.entrySet().stream().map(e -> "Limit " + e.getKey().toString() + " to " + e.getValue()).forEach(addon::log); } private EntityType getType(String key) { diff --git a/src/main/java/bentobox/addon/limits/commands/CalcCommand.java b/src/main/java/bentobox/addon/limits/commands/CalcCommand.java index 77dd80d..5e2b07e 100644 --- a/src/main/java/bentobox/addon/limits/commands/CalcCommand.java +++ b/src/main/java/bentobox/addon/limits/commands/CalcCommand.java @@ -1,10 +1,11 @@ package bentobox.addon.limits.commands; -import bentobox.addon.limits.Limits; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; + +import bentobox.addon.limits.Limits; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.util.Util; diff --git a/src/main/java/bentobox/addon/limits/commands/LimitPanel.java b/src/main/java/bentobox/addon/limits/commands/LimitPanel.java index ff10888..7fb1470 100644 --- a/src/main/java/bentobox/addon/limits/commands/LimitPanel.java +++ b/src/main/java/bentobox/addon/limits/commands/LimitPanel.java @@ -1,11 +1,13 @@ package bentobox.addon.limits.commands; +import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.entity.EntityType; import bentobox.addon.limits.Limits; import bentobox.addon.limits.objects.IslandBlockCount; @@ -24,6 +26,53 @@ import world.bentobox.bentobox.util.Util; public class LimitPanel { private final Limits addon; + public final static Map E2M = new HashMap<>(); + static { + E2M.put(EntityType.PIG_ZOMBIE, Material.ZOMBIE_PIGMAN_SPAWN_EGG); + E2M.put(EntityType.SNOWMAN, Material.SNOW_BLOCK); + E2M.put(EntityType.IRON_GOLEM, Material.IRON_BLOCK); + E2M.put(EntityType.ILLUSIONER, Material.VILLAGER_SPAWN_EGG); + E2M.put(EntityType.WITHER, Material.WITHER_SKELETON_SKULL); + E2M.put(EntityType.BOAT, Material.OAK_BOAT); + E2M.put(EntityType.ARMOR_STAND, Material.ARMOR_STAND); + + // Minecarts + E2M.put(EntityType.MINECART_TNT, Material.TNT_MINECART); + E2M.put(EntityType.MINECART_CHEST, Material.CHEST_MINECART); + E2M.put(EntityType.MINECART_COMMAND, Material.COMMAND_BLOCK_MINECART); + E2M.put(EntityType.MINECART_FURNACE, Material.FURNACE_MINECART); + E2M.put(EntityType.MINECART_HOPPER, Material.HOPPER_MINECART); + E2M.put(EntityType.MINECART_MOB_SPAWNER, Material.MINECART); + E2M.put(EntityType.MINECART_TNT, Material.TNT_MINECART); + // Disallowed + E2M.put(EntityType.PRIMED_TNT, null); + E2M.put(EntityType.EVOKER_FANGS, null); + E2M.put(EntityType.LLAMA_SPIT, null); + E2M.put(EntityType.DRAGON_FIREBALL, null); + E2M.put(EntityType.AREA_EFFECT_CLOUD, null); + E2M.put(EntityType.ENDER_SIGNAL, null); + E2M.put(EntityType.SMALL_FIREBALL, null); + E2M.put(EntityType.DRAGON_FIREBALL, null); + E2M.put(EntityType.FIREBALL, null); + E2M.put(EntityType.THROWN_EXP_BOTTLE, null); + E2M.put(EntityType.EXPERIENCE_ORB, null); + E2M.put(EntityType.SHULKER_BULLET, null); + E2M.put(EntityType.WITHER_SKULL, null); + E2M.put(EntityType.TRIDENT, null); + E2M.put(EntityType.ARROW, null); + E2M.put(EntityType.SPECTRAL_ARROW, null); + E2M.put(EntityType.TIPPED_ARROW, null); + E2M.put(EntityType.SNOWBALL, null); + E2M.put(EntityType.EGG, null); + E2M.put(EntityType.LEASH_HITCH, null); + E2M.put(EntityType.ITEM_FRAME, null); + E2M.put(EntityType.PAINTING, null); + E2M.put(EntityType.GIANT, null); + E2M.put(EntityType.ENDER_CRYSTAL, null); + E2M.put(EntityType.ENDER_PEARL, null); + E2M.put(EntityType.ENDER_DRAGON, null); + + } /** * @param addon - limit addon @@ -67,7 +116,36 @@ public class LimitPanel { "[limit]", String.valueOf(en.getValue()))); pb.item(pib.build()); } + addon.getSettings().getLimits().forEach((k,v) -> { + PanelItemBuilder pib = new PanelItemBuilder(); + pib.name(Util.prettifyText(k.toString())); + Material m = Material.BARRIER; + try { + if (E2M.containsKey(k)) { + m = E2M.get(k); + } else if (k.isAlive()) { + m = Material.valueOf(k.toString() + "_SPAWN_EGG"); + } else { + m = Material.valueOf(k.toString()); + } + } catch (Exception e) { + m = Material.BARRIER; + } + pib.icon(m); + long count = getCount(island, k); + String color = count >= v ? 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))); + pb.item(pib.build()); + }); pb.build(); } + private long getCount(Island island, EntityType ent) { + return island.getWorld().getEntities().stream() + .filter(e -> e.getType().equals(ent)) + .filter(e -> island.inIslandSpace(e.getLocation())).count(); + } } diff --git a/src/main/java/bentobox/addon/limits/listeners/EntityLimitListener.java b/src/main/java/bentobox/addon/limits/listeners/EntityLimitListener.java new file mode 100644 index 0000000..7e2d9e5 --- /dev/null +++ b/src/main/java/bentobox/addon/limits/listeners/EntityLimitListener.java @@ -0,0 +1,145 @@ +package bentobox.addon.limits.listeners; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.event.vehicle.VehicleCreateEvent; + +import bentobox.addon.limits.Limits; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.util.Util; + +public class EntityLimitListener implements Listener { + private final Limits addon; + + /** + * Handles entity and natural limitations + * @param addon - Limits object + */ + public EntityLimitListener(Limits addon) { + this.addon = addon; + } + + /** + * Handles minecart placing + * @param e - event + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onMinecart(VehicleCreateEvent e) { + // Return if not in a known world + if (!addon.getPlugin().getIWM().inWorld(e.getVehicle().getWorld())) { + return; + } + if (addon.getSettings().getLimits().containsKey(e.getVehicle().getType())) { + // If someone in that area has the bypass permission, allow the spawning + for (Entity entity : e.getVehicle().getLocation().getWorld().getNearbyEntities(e.getVehicle().getLocation(), 5, 5, 5)) { + if (entity instanceof Player) { + Player player = (Player)entity; + boolean bypass = (player.isOp() || player.hasPermission(addon.getPlugin().getIWM().getPermissionPrefix(e.getVehicle().getWorld()) + "mod.bypass")); + // Check island + addon.getIslands().getProtectedIslandAt(e.getVehicle().getLocation()).ifPresent(island -> { + // Ignore spawn + if (island.isSpawn()) { + return; + } + // Check if the player is at the limit + if (atLimit(island, bypass, e.getVehicle())) { + 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).sendMessage("limits.hit-limit", "[material]", + Util.prettifyText(e.getVehicle().getType().toString()) + ,"[number]", String.valueOf(addon.getSettings().getLimits().get(e.getVehicle().getType()))); + } + } + } + }); + } + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onCreatureSpawn(final CreatureSpawnEvent e) { + // Return if not in a known world + if (!addon.getPlugin().getIWM().inWorld(e.getLocation())) { + return; + } + if (!addon.getSettings().getLimits().containsKey(e.getEntityType())) { + // Unknown entity limit or unlimited + return; + } + boolean bypass = false; + // Check why it was spawned + switch (e.getSpawnReason()) { + // These reasons are due to a player being involved (usually) so there may be a bypass + case BREEDING: + case BUILD_IRONGOLEM: + case BUILD_SNOWMAN: + case BUILD_WITHER: + case CURED: + case EGG: + case SPAWNER_EGG: + // If someone in that area has the bypass permission, allow the spawning + for (Entity entity : e.getLocation().getWorld().getNearbyEntities(e.getLocation(), 5, 5, 5)) { + if (entity instanceof Player) { + Player player = (Player)entity; + if (player.isOp() || player.hasPermission(addon.getPlugin().getIWM().getPermissionPrefix(e.getEntity().getWorld()) + "mod.bypass")) { + bypass = true; + break; + } + } + } + break; + default: + // Other natural reasons + break; + } + // Tag the entity with the island spawn location + checkLimit(e, bypass); + + } + + private void checkLimit(CreatureSpawnEvent e, boolean bypass) { + addon.getIslands().getIslandAt(e.getLocation()).ifPresent(island -> { + // Check if creature is allowed to spawn or not + if (!island.isSpawn() && atLimit(island, bypass, e.getEntity())) { + // Not allowed + e.setCancelled(true); + // If the reason is anything but because of a spawner then tell players within range + if (!e.getSpawnReason().equals(SpawnReason.SPAWNER)) { + for (Entity ent : e.getLocation().getWorld().getNearbyEntities(e.getLocation(), 5, 5, 5)) { + if (ent instanceof Player) { + User.getInstance(ent).sendMessage("limits.hit-limit", "[material]", + Util.prettifyText(e.getEntityType().toString()), + "[number]", String.valueOf(addon.getSettings().getLimits().get(e.getEntityType()))); + } + } + } + + } + }); + + } + + /** + * Checks if new entities can be added to island + * @param island - island + * @param bypass - true if this is being done by a player with authorization to bypass limits + * @param ent - the entity + * @return true if at the limit, false if not + */ + private boolean atLimit(Island island, boolean bypass, Entity ent) { + return addon.getSettings().getLimits().getOrDefault(ent.getType(), -1) <= ent.getWorld().getEntities().stream() + .filter(e -> e.getType().equals(ent.getType())) + .filter(e -> island.inIslandSpace(e.getLocation())).count(); + } +} + + diff --git a/src/main/java/bentobox/addon/limits/listeners/EntityLimitsListener.java b/src/main/java/bentobox/addon/limits/listeners/EntityLimitsListener.java deleted file mode 100644 index 12bbbec..0000000 --- a/src/main/java/bentobox/addon/limits/listeners/EntityLimitsListener.java +++ /dev/null @@ -1,257 +0,0 @@ -package bentobox.addon.limits.listeners; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.bukkit.World; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; -import org.bukkit.event.vehicle.VehicleCreateEvent; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkUnloadEvent; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.metadata.MetadataValue; - -import bentobox.addon.limits.Limits; -import bentobox.addon.limits.objects.EntityLimitsDO; -import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.database.Database; -import world.bentobox.bentobox.database.objects.Island; -import world.bentobox.bentobox.util.Util; - -class EntityLimitsListener implements Listener { - private final Limits addon; - - private final Database handler; - - /** - * Handles entity and natural limitations - * @param addon - Limits object - */ - public EntityLimitsListener(Limits addon) { - this.addon = addon; - handler = new Database<>(addon, EntityLimitsDO.class); - } - - /** - * Add meta data to entities in the chunk - * @param e - event - */ - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void onChunkLoad(ChunkLoadEvent e) { - // Return if not in a known world - if (!addon.getPlugin().getIWM().inWorld(e.getWorld())) { - return; - } - String uniqueId = e.getWorld().getName() + "." + e.getChunk().getX() + "." + e.getChunk().getZ(); - if (handler.objectExists(uniqueId)) { - EntityLimitsDO eld = handler.loadObject(uniqueId); - if (eld != null) { - for (Entity entity : e.getChunk().getEntities()) { - if (eld.getSpawnLoc().containsKey(entity.getUniqueId())) { - entity.setMetadata("spawnLoc", new FixedMetadataValue(addon.getPlugin(), eld.getSpawnLoc().get(entity.getUniqueId()))); - } - } - // Delete chunk - handler.deleteObject(eld); - } - } - } - - /** - * Save meta data on entities in the chunk - * @param e - event - */ - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void onChunkUnload(ChunkUnloadEvent e) { - // Return if not in a known world - if (!addon.getPlugin().getIWM().inWorld(e.getWorld())) { - return; - } - // Save chunk entities spawn loc meta data - EntityLimitsDO eld = new EntityLimitsDO(e.getWorld().getName() + "." + e.getChunk().getX() + "." + e.getChunk().getZ()); - Map spawnLoc = new HashMap<>(); - Arrays.stream(e.getChunk().getEntities()).filter(x -> x.hasMetadata("spawnLoc")).forEach(entity -> { - // Get the meta data - entity.getMetadata("spawnLoc").stream().filter(y -> y.getOwningPlugin().equals(addon.getPlugin())).forEach(v -> spawnLoc.put(entity.getUniqueId(), v.asString())); - }); - if (!spawnLoc.isEmpty()) { - eld.setSpawnLoc(spawnLoc); - handler.saveObject(eld); - } - } - - /** - * Save all the entity meta data for world - * @param world - world being saved - */ - public void disable(World world) { - HashMap chunkMeta = new HashMap<>(); - world.getEntities().stream().filter(x -> x.hasMetadata("spawnLoc")).forEach(entity -> { - // Get the meta data - entity.getMetadata("spawnLoc").stream().filter(y -> y.getOwningPlugin().equals(addon.getPlugin())).forEach(v -> { - String uniqueId = entity.getWorld().getName() + "." + entity.getLocation().getChunk().getX() + "." + entity.getLocation().getChunk().getZ(); - chunkMeta.putIfAbsent(uniqueId, new EntityLimitsDO(uniqueId)); - chunkMeta.get(uniqueId).getSpawnLoc().put(entity.getUniqueId(), v.asString()); - }); - }); - // Save all the chunks - chunkMeta.values().forEach(handler::saveObject); - } - - /** - * Handles minecart placing - * @param e - event - */ - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onMinecart(VehicleCreateEvent e) { - // Return if not in a known world - if (!addon.getPlugin().getIWM().inWorld(e.getVehicle().getWorld())) { - return; - } - if (addon.getSettings().getLimits().containsKey(e.getVehicle().getType())) { - // If someone in that area has the bypass permission, allow the spawning - for (Entity entity : e.getVehicle().getLocation().getWorld().getNearbyEntities(e.getVehicle().getLocation(), 5, 5, 5)) { - if (entity instanceof Player) { - Player player = (Player)entity; - boolean bypass = (player.isOp() || player.hasPermission(addon.getPlugin().getIWM().getPermissionPrefix(e.getVehicle().getWorld()) + "mod.bypass")); - // Check island - addon.getIslands().getProtectedIslandAt(e.getVehicle().getLocation()).ifPresent(island -> { - // Ignore spawn - if (island.isSpawn()) { - return; - } - // Check if the player is at the limit - if (atLimit(island, bypass, e.getVehicle())) { - e.setCancelled(true); - for (Entity ent : e.getVehicle().getLocation().getWorld().getNearbyEntities(e.getVehicle().getLocation(), 5, 5, 5)) { - if (ent instanceof Player) { - User.getInstance(ent).sendMessage("entityLimitReached", "[entity]", - Util.prettifyText(e.getVehicle().getType().toString()) - ,"[number]", String.valueOf(addon.getSettings().getLimits().get(e.getVehicle().getType()))); - } - } - } - }); - } - } - } - } - - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onCreatureSpawn(final CreatureSpawnEvent e) { - // Return if not in a known world - if (!addon.getPlugin().getIWM().inWorld(e.getLocation())) { - return; - } - if (!addon.getSettings().getLimits().containsKey(e.getEntityType())) { - // Unknown entity limit or unlimited - return; - } - boolean bypass = false; - // Check why it was spawned - switch (e.getSpawnReason()) { - // These reasons are due to a player being involved (usually) so there may be a bypass - case BREEDING: - case BUILD_IRONGOLEM: - case BUILD_SNOWMAN: - case BUILD_WITHER: - case CURED: - case EGG: - case SPAWNER_EGG: - // If someone in that area has the bypass permission, allow the spawning - for (Entity entity : e.getLocation().getWorld().getNearbyEntities(e.getLocation(), 5, 5, 5)) { - if (entity instanceof Player) { - Player player = (Player)entity; - if (player.isOp() || player.hasPermission(addon.getPlugin().getIWM().getPermissionPrefix(e.getEntity().getWorld()) + "mod.bypass")) { - bypass = true; - break; - } - } - } - break; - default: - // Other natural reasons - break; - } - // Tag the entity with the island spawn location - tag(e, bypass); - - } - - private void tag(CreatureSpawnEvent e, boolean bypass) { - addon.getIslands().getIslandAt(e.getLocation()).ifPresent(island -> { - // Check if creature is allowed to spawn or not - if (!island.isSpawn() && atLimit(island, bypass, e.getEntity())) { - // Not allowed - e.setCancelled(true); - // If the reason is anything but because of a spawner then tell players within range - if (!e.getSpawnReason().equals(SpawnReason.SPAWNER)) { - for (Entity ent : e.getLocation().getWorld().getNearbyEntities(e.getLocation(), 5, 5, 5)) { - if (ent instanceof Player) { - User.getInstance(ent).sendMessage("entityLimitReached", "[entity]", - Util.prettifyText(e.getEntityType().toString()), - "[number]", String.valueOf(addon.getSettings().getLimits().get(e.getEntityType()))); - } - } - } - - } - }); - - } - - /** - * Checks if new entities can be added to island - * @param island - island - * @param bypass - true if this is being done by a player with authorization to bypass limits - * @param ent - the entity - * @return true if at the limit, false if not - */ - private boolean atLimit(Island island, boolean bypass, Entity ent) { - int count = 0; - checkLimits: - if (bypass || addon.getSettings().getLimits().get(ent.getType()) > 0) { - // If bypass, just tag the creature. If not, then we need to count creatures - if (!bypass) { - // Run through all the current entities on this world - for (Entity entity: ent.getWorld().getEntities()) { - // If it is the right one - if (entity.getType().equals(ent.getType())) { - // Check spawn location - if (entity.hasMetadata("spawnLoc")) { - // Get the meta data - List values = entity.getMetadata("spawnLoc"); - for (MetadataValue v : values) { - // There is a chance another plugin also uses the meta data spawnLoc - if (v.getOwningPlugin().equals(addon.getPlugin())) { - if (island.getUniqueId().equals(v.asString())) { - // Entity is on this island - count++; - if (count >= addon.getSettings().getLimits().get(ent.getType())) { - // No more allowed! - break checkLimits; - } - } - } - } - } - } - } - } - // Okay to spawn, but tag it - ent.setMetadata("spawnLoc", new FixedMetadataValue(addon.getPlugin(), island.getUniqueId())); - return false; - } - // Cancel - no spawning - tell nearby players - return true; - } -} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 5ce7782..9c2eb74 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -23,3 +23,12 @@ worlds: AcidIsland_world: HOPPER: 11 +# Default entity limits within a player's island space (protected area and to island limit). +# A limit of 5 will allow up to 5 entites in over world, 5 in nether and 5 in the end. +# Affects all types of creature spawning. Also includes entities like MINECARTS. +# Note: Only the first 49 limited blocks and entities are shown in the limits GUI. +entitylimits: + ENDERMAN: 5 + CHICKEN: 10 + pig_ZOMbIe: 15 + \ No newline at end of file