Skip to content

Commit

Permalink
WIP try to use EntityBreedEvent to track breeding
Browse files Browse the repository at this point in the history
  • Loading branch information
tastybento committed Dec 22, 2021
1 parent 328a1a1 commit 14c3886
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 109 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<!-- Non-minecraft related dependencies -->
<powermock.version>2.0.9</powermock.version>
<!-- More visible way how to change dependency versions -->
<spigot.version>1.17.1-R0.1-SNAPSHOT</spigot.version>
<spigot.version>1.16.1-R0.1-SNAPSHOT</spigot.version>
<bentobox.version>1.18.0-SNAPSHOT</bentobox.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
Expand Down
169 changes: 62 additions & 107 deletions src/main/java/world/bentobox/limits/listeners/EntityLimitListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
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;

Expand All @@ -43,17 +44,7 @@ public class EntityLimitListener implements Listener {
private static final String MOD_BYPASS = "mod.bypass";
private final Limits addon;
private final List<UUID> justSpawned = new ArrayList<>();
private static final List<BlockFace> CARDINALS;
static {
List<BlockFace> 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<BlockFace> CARDINALS = List.of(BlockFace.UP, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.DOWN);

/**
* Handles entity and natural limitations
Expand All @@ -71,46 +62,34 @@ public EntityLimitListener(Limits addon) {
@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);
}
}

Expand All @@ -124,53 +103,20 @@ public void onCreatureSpawn(final CreatureSpawnEvent e) {
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
Expand Down Expand Up @@ -205,22 +151,22 @@ public void onBlock(HangingPlaceEvent e) {
/**
* 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(), () -> {
Expand All @@ -234,7 +180,7 @@ private void processIsland(Cancellable c, LivingEntity e, Location l, SpawnReaso
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);
}

});
Expand Down Expand Up @@ -378,28 +324,37 @@ private boolean isWither(Block body) {
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()));
}
}
});
}
}
});

}

Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/addon.yml
Original file line number Diff line number Diff line change
@@ -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

Expand Down

0 comments on commit 14c3886

Please sign in to comment.