diff --git a/patches/removed/1.17/0187-PreCreatureSpawnEvent.patch b/patches/removed/1.17/0187-PreCreatureSpawnEvent.patch deleted file mode 100644 index c3206f4317..0000000000 --- a/patches/removed/1.17/0187-PreCreatureSpawnEvent.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:01:31 -0500 -Subject: [PATCH] PreCreatureSpawnEvent -1.17: Has to be looked into more -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/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index e3d92d1d35911b2960a7ca82bd4f324d285d0533..e39d950783599b01271bdb7e67fe68b46af0c49c 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -17,6 +17,7 @@ import net.minecraft.nbt.ListTag; - import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.tags.BlockTags; -@@ -317,6 +318,20 @@ public class EntityType { - - @Nullable - public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // Paper start - Call PreCreatureSpawnEvent -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition), -+ type, -+ spawnReason -+ ); -+ if (!event.callEvent()) { -+ return null; -+ } -+ } -+ // Paper end - T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); - - if (t0 != null) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java -index f3a7807a20b279056d5640ab02aa77f7b1dabc2a..880d69bad933294a2cfdea9adb3e648e29eb42be 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/GolemSensor.java -@@ -33,8 +33,8 @@ public class GolemSensor extends Sensor { - Optional> optional = entityliving.getBrain().getMemory(MemoryModuleType.MOBS); - - if (optional.isPresent()) { -- boolean flag = ((List) optional.get()).stream().anyMatch((entityliving1) -> { -- return entityliving1.getEntityType().equals(EntityType.IRON_GOLEM); -+ boolean flag = optional.get().stream().anyMatch((entityliving1) -> { // Paper - decompile fixes -+ return entityliving1.getType().equals(EntityType.IRON_GOLEM); - }); - - if (flag) { -@@ -44,6 +44,7 @@ public class GolemSensor extends Sensor { - } - } - -+ public static void setDetectedRecently(LivingEntity entityLiving) { golemDetected(entityLiving); } // Paper - OBFHELPER - public static void golemDetected(LivingEntity entityliving) { - entityliving.getBrain().setMemoryWithExpiry(MemoryModuleType.GOLEM_DETECTED_RECENTLY, true, 600L); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index a66fab2e04a5d87ced139ed15d2434c5ffcec695..eed6265dc8275921a18fc5f4970ba131ba782132 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -30,6 +30,7 @@ import net.minecraft.network.protocol.game.DebugPackets; - import net.minecraft.network.syncher.EntityDataAccessor; - import net.minecraft.network.syncher.EntityDataSerializers; - import net.minecraft.network.syncher.SynchedEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.sounds.SoundEvent; -@@ -942,6 +943,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - BlockPos blockposition1 = this.findSpawnPositionForGolemInColumn(blockposition, d0, d1); - - if (blockposition1 != null) { -+ // Paper start - Call PreCreatureSpawnEvent -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(level, blockposition1), -+ org.bukkit.entity.EntityType.IRON_GOLEM, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ GolemSensor.golemDetected(this); // Set Golem Last Seen to stop it from spawning another one -+ return null; -+ } -+ break; -+ } -+ // Paper end - IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(world, (CompoundTag) null, (Component) null, (Player) null, blockposition1, MobSpawnType.MOB_SUMMONED, false, false); - - if (entityirongolem != null) { -diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 4582fc1bb767214241568fbc22b0ee2cbf3322e0..ac572eba10a7239d71dfae060f623b076d4252ce 100644 ---- a/src/main/java/net/minecraft/world/level/BaseSpawner.java -+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -12,6 +12,7 @@ import net.minecraft.core.particles.ParticleTypes; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.ListTag; - import net.minecraft.resources.ResourceLocation; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.StringUtil; - import net.minecraft.util.WeighedRandom; -@@ -125,6 +126,27 @@ public abstract class BaseSpawner { - ServerLevel worldserver = (ServerLevel) world; - - if (SpawnPlacements.checkSpawnRules((EntityType) optional.get(), worldserver, MobSpawnType.SPAWNER, new BlockPos(d3, d4, d5), world.getRandom())) { -+ // Paper start -+ EntityType entityType = optional.get(); -+ String key = EntityType.getKey(entityType).getPath(); -+ -+ 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 = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { - entity1.moveTo(d3, d4, d5, entity1.yRot, entity1.xRot); - return entity1; -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index a19ac1cb7e4d8d478648a048b2bfa0daf85a80c9..8a71eaf2855be0d415d1f7b18dbec98353fe5b47 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -15,6 +15,7 @@ import net.minecraft.core.Direction; - import net.minecraft.core.Position; - import net.minecraft.core.Registry; - import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.tags.BlockTags; - import net.minecraft.tags.FluidTags; -@@ -214,9 +215,16 @@ public final class NaturalSpawner { - j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); - } - -- if (isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { -+ // Paper start -+ Boolean doSpawning = a(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); -+ if (doSpawning == null) { -+ return; -+ } -+ if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { -+ // Paper end - Mob entityinsentient = getMobForSpawn(world, biomesettingsmobs_c.type); - -+ - if (entityinsentient == null) { - return; - } -@@ -269,17 +277,33 @@ public final class NaturalSpawner { - } - } - -- private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { -- EntityType entitytypes = spawnEntry.type; -+ private static Boolean a(ServerLevel worldserver, MobCategory enumcreaturetype, StructureFeatureManager structuremanager, ChunkGenerator chunkgenerator, MobSpawnSettings.SpawnerData biomesettingsmobs_c, BlockPos.MutableBlockPos blockposition_mutableblockposition, double d0) { // Paper -+ EntityType entitytypes = biomesettingsmobs_c.type; -+ // Paper start -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(entitytypes).getPath()); -+ 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.getCategory() == MobCategory.MISC) { - return false; -- } else if (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { -+ } else if (!entitytypes.canSpawnFarFromPlayer() && d0 > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { - return false; -- } else if (entitytypes.canSummon() && canSpawnMobAt(world, structureAccessor, chunkGenerator, group, spawnEntry, (BlockPos) pos)) { -+ } else if (entitytypes.canSummon() && canSpawnMobAt(worldserver, structuremanager, chunkgenerator, enumcreaturetype, biomesettingsmobs_c, (BlockPos) blockposition_mutableblockposition)) { - SpawnPlacements.Type entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); - -- return !isSpawnPositionOk(entitypositiontypes_surface, (LevelReader) world, pos, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, world, MobSpawnType.NATURAL, pos, world.random) ? false : world.noCollision(entitytypes.getAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D))); -+ return !isSpawnPositionOk(entitypositiontypes_surface, (LevelReader) worldserver, blockposition_mutableblockposition, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, worldserver, MobSpawnType.NATURAL, blockposition_mutableblockposition, worldserver.random) ? false : worldserver.noCollision(entitytypes.getAABB((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D))); - } else { - return false; - } diff --git a/patches/server/0330-PreCreatureSpawnEvent.patch b/patches/server/0330-PreCreatureSpawnEvent.patch new file mode 100644 index 0000000000..f15e5b7e00 --- /dev/null +++ b/patches/server/0330-PreCreatureSpawnEvent.patch @@ -0,0 +1,150 @@ +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/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 9f5f2bd9bdfce14da030b09f56c821ec1989e12f..872f92ac1a6bc86ce54700dbf555ceea4fab2057 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -333,6 +333,20 @@ public class EntityType implements EntityTypeTest { + + @Nullable + public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // Paper start - Call PreCreatureSpawnEvent ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(this).getPath()); ++ if (type != null) { ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ net.minecraft.server.MCUtil.toLocation(worldserver, blockposition), ++ type, ++ spawnReason ++ ); ++ if (!event.callEvent()) { ++ return null; ++ } ++ } ++ // Paper end + T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); + + if (t0 != null) { +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 6a9e2105b2d9a4ee83c0a2516d5ef26dc3b99053..aec77679584a2acab5818e26e2586b5316118e84 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -987,6 +987,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + BlockPos blockposition1 = this.findSpawnPositionForGolemInColumn(blockposition, d0, d1); + + if (blockposition1 != null) { ++ // Paper start - Call PreCreatureSpawnEvent ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ net.minecraft.server.MCUtil.toLocation(level, blockposition1), ++ org.bukkit.entity.EntityType.IRON_GOLEM, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ GolemSensor.golemDetected(this); // Set Golem Last Seen to stop it from spawning another one ++ return null; ++ } ++ break; ++ } ++ // Paper end + IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(world, (CompoundTag) null, (Component) null, (Player) null, blockposition1, MobSpawnType.MOB_SUMMONED, false, false); + + if (entityirongolem != null) { +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index c6298b12e4e0c20be20e7e493be728f028f9eb31..68ce2732dfdc25ddadc15c43c30a609f9b1eba86 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -132,6 +132,27 @@ public abstract class BaseSpawner { + double d2 = j >= 3 ? nbttaglist.getDouble(2) : (double) pos.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) this.spawnRange + 0.5D; + + if (world.noCollision(((EntityType) optional.get()).getAABB(d0, d1, d2)) && SpawnPlacements.checkSpawnRules((EntityType) optional.get(), world, MobSpawnType.SPAWNER, new BlockPos(d0, d1, d2), world.getRandom())) { ++ // Paper start ++ EntityType entityType = optional.get(); ++ String key = EntityType.getKey(entityType).getPath(); ++ ++ 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( ++ net.minecraft.server.MCUtil.toLocation(world, d0, d1, d2), ++ type, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ ); ++ if (!event.callEvent()) { ++ flag = true; ++ if (event.shouldAbortSpawn()) { ++ break; ++ } ++ continue; ++ } ++ } ++ // Paper end + Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { + entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot()); + return entity1; +@@ -349,3 +370,4 @@ public abstract class BaseSpawner { + return this.oSpin; + } + } ++ +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 30ba1e3cb75d994770b006b9dfd6669000a9c1a4..6204bf41d410df9784b32f993b46d7adb2af5f13 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -231,7 +231,13 @@ public final class NaturalSpawner { + j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); + } + +- if (NaturalSpawner.isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ // Paper start ++ Boolean doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); ++ if (doSpawning == null) { ++ return; ++ } ++ if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ // Paper end + Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type); + + if (entityinsentient == null) { +@@ -278,9 +284,25 @@ public final class NaturalSpawner { + return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || world.isPositionEntityTicking((BlockPos) pos)); + } + +- private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { ++ private static Boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { // Paper + EntityType entitytypes = spawnEntry.type; + ++ // Paper start ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(entitytypes).getPath()); ++ if (type != null) { ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ net.minecraft.server.MCUtil.toLocation(world, pos), ++ type, SpawnReason.NATURAL ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ return null; ++ } ++ return false; ++ } ++ } ++ // Paper end + if (entitytypes.getCategory() == MobCategory.MISC) { + return false; + } else if (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) {