From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 14 Jan 2018 17:01:31 -0500 Subject: [PATCH] PreCreatureSpawnEvent Adds an event to fire before an Entity is created, so that plugins that need to cancel CreatureSpawnEvent can do so from this event instead. Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste as it's done after the Entity object has been fully created. Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event instead and save a lot of server resources. See: https://github.com/PaperMC/Paper/issues/917 diff --git a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java index 34ab03fce7ab5c7702234590ffc9ca7fec72a86a..2827026ba4bdd857f231028393726d6c95610072 100644 --- a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java +++ b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java @@ -108,6 +108,27 @@ public abstract class MobSpawnerAbstract { WorldServer worldserver = (WorldServer) world; if (EntityPositionTypes.a((EntityTypes) optional.get(), worldserver, EnumMobSpawn.SPAWNER, new BlockPosition(d3, d4, d5), world.getRandom())) { + // Paper start + EntityTypes entityType = optional.get(); + String key = EntityTypes.getName(entityType).getKey(); + + org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); + if (type != null) { + com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; + event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( + MCUtil.toLocation(world, d3, d4, d5), + type, + org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER + ); + if (!event.callEvent()) { + flag = true; + if (event.shouldAbortSpawn()) { + break; + } + continue; + } + } + // Paper end Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> { entity1.setPositionRotation(d3, d4, d5, entity1.yaw, entity1.pitch); return entity1; diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java index ca3dc5a113554381a2ff97cb3175eda1ec4034ae..eb637c32f7a4faa99d30596c273e62ebffe74f3b 100644 --- a/src/main/java/net/minecraft/server/SpawnerCreature.java +++ b/src/main/java/net/minecraft/server/SpawnerCreature.java @@ -184,9 +184,16 @@ public final class SpawnerCreature { j1 = biomesettingsmobs_c.d + worldserver.random.nextInt(1 + biomesettingsmobs_c.e - biomesettingsmobs_c.d); } - if (a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { + // Paper start + Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); + if (doSpawning == null) { + return; + } + if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { + // Paper end EntityInsentient entityinsentient = a(worldserver, biomesettingsmobs_c.c); + if (entityinsentient == null) { return; } @@ -238,8 +245,24 @@ public final class SpawnerCreature { } } - private static boolean a(WorldServer worldserver, EnumCreatureType enumcreaturetype, StructureManager structuremanager, ChunkGenerator chunkgenerator, BiomeSettingsMobs.c biomesettingsmobs_c, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { + private static Boolean a(WorldServer worldserver, EnumCreatureType enumcreaturetype, StructureManager structuremanager, ChunkGenerator chunkgenerator, BiomeSettingsMobs.c biomesettingsmobs_c, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { // Paper EntityTypes entitytypes = biomesettingsmobs_c.c; + // Paper start + com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; + org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(entitytypes).getKey()); + if (type != null) { + event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( + MCUtil.toLocation(worldserver, blockposition_mutableblockposition), + type, SpawnReason.NATURAL + ); + if (!event.callEvent()) { + if (event.shouldAbortSpawn()) { + return null; + } + return false; + } + } + // Paper end if (entitytypes.e() == EnumCreatureType.MISC) { return false;