Fix bug in mob limiter

This commit is contained in:
mathiascode 2019-12-02 05:22:38 +02:00
parent 1a0962896a
commit 91b3b8c92d
2 changed files with 100 additions and 101 deletions

View file

@ -24,7 +24,6 @@ public class Main extends JavaPlugin {
static HashSet<Material> nonSolidSingularBlockList = new HashSet<>();
static HashSet<Material> nonSolidWallMountedBlockList = new HashSet<>();
static HashSet<Material> nonSolidWaterBlockList = new HashSet<>();
static HashSet<SpawnReason> spawnReasonList = new HashSet<>();
public void onLoad() {
/* Fill lists */
@ -653,15 +652,6 @@ public class Main extends JavaPlugin {
this.nonSolidBlockList.addAll(nonSolidSingularBlockList);
this.nonSolidBlockList.addAll(nonSolidWallMountedBlockList);
Collections.addAll(
spawnReasonList,
SpawnReason.CUSTOM,
SpawnReason.DEFAULT,
SpawnReason.DISPENSE_EGG,
SpawnReason.SPAWNER,
SpawnReason.SPAWNER_EGG
);
saveResource("config.yml", false);
}

View file

@ -29,7 +29,6 @@ import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.entity.AreaEffectCloudApplyEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.entity.SpawnerSpawnEvent;
@ -41,6 +40,10 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import com.destroystokyo.paper.event.block.TNTPrimeEvent;
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
@ -50,22 +53,83 @@ import com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent;
import org.bukkit.block.banner.Pattern;
class EntitySpawn implements Listener {
private boolean checkDragonWorldLimit(World world) {
final int dragonCount = world.getEntitiesByClass(EnderDragon.class).size();
private void applyEntityChanges(Entity entity) {
final World world = entity.getWorld();
if (dragonCount > 25) {
if (entity instanceof LivingEntity) {
final LivingEntity mob = (LivingEntity) entity;
limitFollowAttribute(mob);
}
switch (entity.getType()) {
case ARMOR_STAND:
case DROWNED:
case GIANT:
case HUSK:
case PIG_ZOMBIE:
case PLAYER:
case SKELETON:
case STRAY:
case WITHER_SKELETON:
case ZOMBIE:
case ZOMBIE_VILLAGER:
final LivingEntity mob = (LivingEntity) entity;
checkIllegalEquipment(mob);
break;
case AREA_EFFECT_CLOUD:
final AreaEffectCloud cloud = (AreaEffectCloud) entity;
limitAreaEffectCloudRadius(cloud);
break;
case PRIMED_TNT:
final int tntCount = world.getEntitiesByClass(TNTPrimed.class).size();
if (tntCount > 180) {
for (Entity tnt : world.getEntitiesByClass(TNTPrimed.class)) {
tnt.remove();
}
}
break;
case MAGMA_CUBE:
case SLIME:
final Slime slime = (Slime) entity;
limitSlimeSize(slime);
}
}
private boolean checkEntityLimits(EntityType entityType, Location location, boolean isAddToWorldEvent) {
final int chunkEntityCount = location.getChunk().getEntities().length;
final int chunkEntityCountLimit = 50;
final int worldDragonCount = location.getWorld().getEntitiesByClass(EnderDragon.class).size();
final int worldDragonCountLimit = 24;
if ((entityType != EntityType.PLAYER &&
isEntityLimitReached(location, chunkEntityCount, chunkEntityCountLimit, isAddToWorldEvent)) ||
(entityType == EntityType.ENDER_DRAGON &&
isEntityLimitReached(location, worldDragonCount, worldDragonCountLimit, isAddToWorldEvent))) {
return true;
}
return false;
}
private boolean checkEntityChunkLimit(Location location) {
if (location.isChunkLoaded()) {
final int count = location.getChunk().getEntities().length;
if (count > 50) {
return true;
private boolean isEntityLimitReached(Location location, int count, int countLimit, boolean isAddToWorldEvent) {
/*
Add 1 if EntitySpawnEvent triggered the method, due to the entity count being
one larger in EntityAddToWorldEvent compared to EntitySpawnEvent
This prevents EntityAddToWorldEvent from triggering an entity removal before
EntitySpawnEvent's event cancel
*/
if (!isAddToWorldEvent) {
count += 1;
}
if (count >= countLimit) {
return true;
}
return false;
}
@ -198,93 +262,38 @@ class EntitySpawn implements Listener {
}
}
@EventHandler
void onCreatureSpawn(CreatureSpawnEvent event) {
final LivingEntity mob = event.getEntity();
if (Main.spawnReasonList.contains(event.getSpawnReason())) {
limitFollowAttribute(mob);
}
switch (event.getEntityType()) {
case ARMOR_STAND:
case DROWNED:
case GIANT:
case HUSK:
case PIG_ZOMBIE:
case PLAYER:
case SKELETON:
case STRAY:
case WITHER_SKELETON:
case ZOMBIE:
case ZOMBIE_VILLAGER:
checkIllegalEquipment(mob);
break;
case ENDER_DRAGON:
final World world = event.getLocation().getWorld();
if (checkDragonWorldLimit(world)) {
event.setCancelled(true);
}
break;
case MAGMA_CUBE:
case SLIME:
final Slime slime = (Slime) mob;
limitSlimeSize(slime);
}
}
@EventHandler
void onEntityAddToWorld(EntityAddToWorldEvent event) {
if (event.getEntityType() != EntityType.PLAYER) {
final World world = event.getEntity().getWorld();
final Entity entity = event.getEntity();
if (!checkEntityWorldLimitRemove(world)) {
if (checkEntityChunkLimit(entity.getLocation())) {
final EntityType entityType = entity.getType();
final Location location = entity.getLocation();
final boolean isAddToWorldEvent = true;
if (checkEntityLimits(entityType, location, isAddToWorldEvent)) {
entity.remove();
return;
}
}
switch (event.getEntityType()) {
case ARMOR_STAND:
case DROWNED:
case GIANT:
case HUSK:
case PIG_ZOMBIE:
case PLAYER:
case SKELETON:
case STRAY:
case WITHER_SKELETON:
case ZOMBIE:
case ZOMBIE_VILLAGER:
final LivingEntity mob = (LivingEntity) entity;
checkIllegalEquipment(mob);
break;
case AREA_EFFECT_CLOUD:
final AreaEffectCloud cloud = (AreaEffectCloud) entity;
limitAreaEffectCloudRadius(cloud);
break;
case PRIMED_TNT:
if (world.getEntitiesByClass(TNTPrimed.class).size() > 180) {
for (Entity tnt : world.getEntitiesByClass(TNTPrimed.class)) {
tnt.remove();
}
}
}
}
applyEntityChanges(entity);
}
@EventHandler
void onEntitySpawn(EntitySpawnEvent event) {
if (event.getEntityType() != EntityType.PLAYER &&
checkEntityChunkLimit(event.getLocation())) {
final Entity entity = event.getEntity();
final EntityType entityType = entity.getType();
final Location location = event.getLocation();
final boolean isAddToWorldEvent = false;
if (checkEntityLimits(entityType, location, isAddToWorldEvent)) {
event.setCancelled(true);
return;
}
applyEntityChanges(entity);
}
@EventHandler
@ -298,11 +307,11 @@ class EntitySpawn implements Listener {
@EventHandler
void onPreCreatureSpawn(PreCreatureSpawnEvent event) {
if ((event.getType() != EntityType.PLAYER &&
checkEntityChunkLimit(event.getSpawnLocation())) ||
final EntityType mobType = event.getType();
final Location location = event.getSpawnLocation();
final boolean isAddToWorldEvent = false;
(event.getType() == EntityType.ENDER_DRAGON &&
checkDragonWorldLimit(event.getSpawnLocation().getWorld()))) {
if (checkEntityLimits(mobType, location, isAddToWorldEvent)) {
event.setCancelled(true);
}
}