From 14c38869dfdee0c9930a16caf86e0afc0eaf572c Mon Sep 17 00:00:00 2001 From: tastybento Date: Wed, 22 Dec 2021 09:19:00 -0800 Subject: [PATCH] WIP try to use EntityBreedEvent to track breeding --- pom.xml | 2 +- .../limits/listeners/EntityLimitListener.java | 169 +++++++----------- src/main/resources/addon.yml | 2 +- 3 files changed, 64 insertions(+), 109 deletions(-) diff --git a/pom.xml b/pom.xml index 3a66a60..e82c10d 100644 --- a/pom.xml +++ b/pom.xml @@ -57,7 +57,7 @@ 2.0.9 - 1.17.1-R0.1-SNAPSHOT + 1.16.1-R0.1-SNAPSHOT 1.18.0-SNAPSHOT ${build.version}-SNAPSHOT diff --git a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java index 00f2c79..7c9c91c 100644 --- a/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java +++ b/src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java @@ -27,6 +27,7 @@ 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.entity.EntityBreedEvent; import org.bukkit.event.hanging.HangingPlaceEvent; import org.bukkit.event.vehicle.VehicleCreateEvent; @@ -43,17 +44,7 @@ public class EntityLimitListener implements Listener { private static final String MOD_BYPASS = "mod.bypass"; private final Limits addon; private final List justSpawned = new ArrayList<>(); - private static final List CARDINALS; - static { - List cardinals = new ArrayList<>(); - cardinals.add(BlockFace.UP); - cardinals.add(BlockFace.NORTH); - cardinals.add(BlockFace.SOUTH); - cardinals.add(BlockFace.EAST); - cardinals.add(BlockFace.WEST); - cardinals.add(BlockFace.DOWN); - CARDINALS = Collections.unmodifiableList(cardinals); - } + private static final List CARDINALS = List.of(BlockFace.UP, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.DOWN); /** * Handles entity and natural limitations @@ -71,46 +62,34 @@ public class EntityLimitListener implements Listener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onMinecart(VehicleCreateEvent e) { // Return if not in a known world - if (!addon.inGameModeWorld(e.getVehicle().getWorld())) { return; } + // Debounce if (justSpawned.contains(e.getVehicle().getUniqueId())) { justSpawned.remove(e.getVehicle().getUniqueId()); return; } - // If someone in that area has the bypass permission, allow the spawning - for (Entity entity : Objects.requireNonNull(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 - 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(); - 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())); - } - } - } - } - }); + // Check island + addon.getIslands().getProtectedIslandAt(e.getVehicle().getLocation()) + // Ignore spawn + .filter(i -> !i.isSpawn()) + .ifPresent(island -> { + // Check if the player is at the limit + AtLimitResult res = atLimit(island, e.getVehicle()); + if (res.hit()) { + e.setCancelled(true); + this.tellPlayers(e.getVehicle().getLocation(), e.getVehicle(), SpawnReason.MOUNT, res); } + }); + } + + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBreed(final EntityBreedEvent e) { + if (e.getBreeder() != null && e.getBreeder() instanceof Player p && + !(p.isOp() || p.hasPermission(addon.getPlugin().getIWM().getPermissionPrefix(e.getEntity().getWorld()) + MOD_BYPASS))) { + checkLimit(e, e.getEntity(), SpawnReason.BREEDING, false); } } @@ -124,53 +103,20 @@ public class EntityLimitListener implements Listener { justSpawned.remove(e.getEntity().getUniqueId()); 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: - bypass = checkByPass(e.getLocation()); - break; - case SHOULDER_ENTITY: + if (e.getSpawnReason().equals(SpawnReason.SHOULDER_ENTITY)) { // Special case - do nothing - jumping around spawns parrots as they drop off player's shoulder return; - default: - // Other natural reasons - break; } // Some checks can be done async, some not - switch (e.getSpawnReason()) { - case BUILD_SNOWMAN: - case BUILD_IRONGOLEM: - checkLimit(e, e.getEntity(), e.getSpawnReason(), bypass, addon.getSettings().isAsyncGolums()); - default: + if (e.getSpawnReason().equals(SpawnReason.BUILD_SNOWMAN) || e.getSpawnReason().equals(SpawnReason.BUILD_IRONGOLEM)) { + checkLimit(e, e.getEntity(), e.getSpawnReason(), addon.getSettings().isAsyncGolums()); + } else { // Check limit sync - checkLimit(e, e.getEntity(), e.getSpawnReason(), bypass, false); - break; - + checkLimit(e, e.getEntity(), e.getSpawnReason(), false); } } - private boolean checkByPass(Location l) { - // If someone in that area has the bypass permission, allow the spawning - for (Entity entity : Objects.requireNonNull(l.getWorld()).getNearbyEntities(l, 5, 5, 5)) { - if (entity instanceof Player) { - Player player = (Player)entity; - if (player.isOp() || player.hasPermission(addon.getPlugin().getIWM().getPermissionPrefix(l.getWorld()) + MOD_BYPASS)) { - return true; - } - } - } - return false; - } - /** * handles paintings and item frames * @param e - event @@ -205,22 +151,22 @@ public class EntityLimitListener implements Listener { /** * Check if a creature is allowed to spawn or not * @param e - CreatureSpawnEvent - * @param bypass - true if the player involved can bypass the checks * @param async - true if check can be done async, false if not */ - private void checkLimit(Cancellable c, LivingEntity e, SpawnReason reason, boolean bypass, boolean async) { + private void checkLimit(Cancellable c, LivingEntity e, SpawnReason reason, boolean async) { + BentoBox.getInstance().logDebug("Event = " + c.toString() + " " + e + " " + reason + " "); Location l = e.getLocation(); if (async) { c.setCancelled(true); } - processIsland(c, e, l, reason, bypass, async); + processIsland(c, e, l, reason, async); } - private void processIsland(Cancellable c, LivingEntity e, Location l, SpawnReason reason, boolean bypass, boolean async) { + private void processIsland(Cancellable c, LivingEntity e, Location l, SpawnReason reason, boolean async) { addon.getIslands().getIslandAt(e.getLocation()).ifPresent(island -> { // Check if creature is allowed to spawn or not AtLimitResult res = atLimit(island, e); - if (bypass || island.isSpawn() || !res.hit()) { + if (island.isSpawn() || !res.hit()) { // Allowed if (async) { Bukkit.getScheduler().runTask(BentoBox.getInstance(), () -> { @@ -234,7 +180,7 @@ public class EntityLimitListener implements Listener { c.setCancelled(true); } // If the reason is anything but because of a spawner then tell players within range - tellPlayers(c, l, e, reason, res); + tellPlayers(l, e, reason, res); } }); @@ -378,28 +324,37 @@ public class EntityLimitListener implements Listener { return Tag.WITHER_SUMMON_BASE_BLOCKS.isTagged(body.getType()); } - private void tellPlayers(Cancellable e, Location l, LivingEntity entity, SpawnReason reason, AtLimitResult res) { - if (!reason.equals(SpawnReason.SPAWNER) && !reason.equals(SpawnReason.NATURAL) - && !reason.equals(SpawnReason.INFECTION) && !reason.equals(SpawnReason.NETHER_PORTAL) - && !reason.equals(SpawnReason.REINFORCEMENTS) && !reason.equals(SpawnReason.SLIME_SPLIT)) { - World w = l.getWorld(); - if (w == null) return; - Bukkit.getScheduler().runTask(addon.getPlugin(), () -> { - for (Entity ent : w.getNearbyEntities(l, 5, 5, 5)) { - if (ent instanceof Player) { - if (res.getTypelimit() != null) { - User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]", - Util.prettifyText(entity.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())); - } + /** + * Tell players within a 5 x 5 x 5 radius that the spawning was denied. Informing happens 1 tick after event + * @param l location + * @param entity entity spawned + * @param reason reason - some reasons are not reported + * @param res at limit result + */ + private void tellPlayers(Location l, Entity entity, SpawnReason reason, AtLimitResult res) { + if (reason.equals(SpawnReason.SPAWNER) || reason.equals(SpawnReason.NATURAL) + || reason.equals(SpawnReason.INFECTION) || reason.equals(SpawnReason.NETHER_PORTAL) + || reason.equals(SpawnReason.REINFORCEMENTS) || reason.equals(SpawnReason.SLIME_SPLIT)) { + return; + } + World w = l.getWorld(); + if (w == null) return; + Bukkit.getScheduler().runTask(addon.getPlugin(), () -> { + for (Entity ent : w.getNearbyEntities(l, 5, 5, 5)) { + if (ent instanceof Player p) { + p.updateInventory(); + if (res.getTypelimit() != null) { + User.getInstance(p).notify("entity-limits.hit-limit", "[entity]", + Util.prettifyText(entity.getType().toString()), + TextVariables.NUMBER, String.valueOf(res.getTypelimit().getValue())); + } else { + User.getInstance(p).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())); } } - }); - } + } + }); } diff --git a/src/main/resources/addon.yml b/src/main/resources/addon.yml index 1658901..201c10d 100755 --- a/src/main/resources/addon.yml +++ b/src/main/resources/addon.yml @@ -1,7 +1,7 @@ name: Limits main: world.bentobox.limits.Limits version: ${version}${build.number} -api-version: 1.18 +api-version: 1.16.5 authors: tastybento