2021-06-14 05:40:21 +00:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Aikar <aikar@aikar.co>
|
|
|
|
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
|
2021-11-23 14:03:50 +00:00
|
|
|
index 20cfdba68c200e87d00995a6a4e25a5fa8171f6c..05ca012854100013714e3d6e8803a2959938cba4 100644
|
2021-06-14 05:40:21 +00:00
|
|
|
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
|
2021-11-23 14:03:50 +00:00
|
|
|
@@ -334,6 +334,20 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T> {
|
2021-06-14 05:40:21 +00:00
|
|
|
|
|
|
|
@Nullable
|
2021-11-23 14:03:50 +00:00
|
|
|
public T spawn(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) {
|
2021-06-14 05:40:21 +00:00
|
|
|
+ // 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
|
2021-11-23 14:03:50 +00:00
|
|
|
index 8d76fe0154f31445a889dfe4cca716cb658053f6..55e4e7fcefc60e66239035e72ad44e0c796bf300 100644
|
2021-06-14 05:40:21 +00:00
|
|
|
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
2021-11-23 14:03:50 +00:00
|
|
|
@@ -990,6 +990,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
2021-06-14 05:40:21 +00:00
|
|
|
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
|
2021-11-30 07:32:30 +00:00
|
|
|
index 9c27f69f5b8e95ee56428a597e67dc4e8beb6d29..33e7a9eb613a4984ebcb5f3cde5a1fa584f1695e 100644
|
2021-06-14 05:40:21 +00:00
|
|
|
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
|
2021-11-23 14:03:50 +00:00
|
|
|
@@ -122,6 +122,27 @@ public abstract class BaseSpawner {
|
|
|
|
} else if (!SpawnPlacements.checkSpawnRules((EntityType) optional.get(), world, MobSpawnType.SPAWNER, blockposition1, world.getRandom())) {
|
|
|
|
continue;
|
|
|
|
}
|
2021-06-14 05:40:21 +00:00
|
|
|
+ // 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
|
2021-11-23 14:03:50 +00:00
|
|
|
|
2021-06-14 05:40:21 +00:00
|
|
|
Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> {
|
|
|
|
entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot());
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
2021-11-23 14:03:50 +00:00
|
|
|
index 28a7c53d98450cc79bee953411a18f50cfed26c2..831799937d4e1f31dbf7caaf0c6b38762ccec127 100644
|
2021-06-14 05:40:21 +00:00
|
|
|
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
2021-11-23 14:03:50 +00:00
|
|
|
@@ -239,7 +239,13 @@ public final class NaturalSpawner {
|
2021-06-14 05:40:21 +00:00
|
|
|
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) {
|
2021-11-23 14:03:50 +00:00
|
|
|
@@ -286,9 +292,25 @@ public final class NaturalSpawner {
|
2021-06-14 05:40:21 +00:00
|
|
|
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())) {
|