mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-30 16:19:03 +01:00
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
This commit is contained in:
parent
3620489699
commit
cad0c129c8
5 changed files with 115 additions and 17 deletions
|
@ -1,18 +1,18 @@
|
|||
--- a/net/minecraft/util/SpawnUtil.java
|
||||
+++ b/net/minecraft/util/SpawnUtil.java
|
||||
@@ -21,24 +21,31 @@
|
||||
@@ -21,24 +21,47 @@
|
||||
public SpawnUtil() {}
|
||||
|
||||
public static <T extends Mob> Optional<T> trySpawnMob(EntityType<T> entityType, EntitySpawnReason reason, ServerLevel world, BlockPos pos, int tries, int horizontalRange, int verticalRange, SpawnUtil.Strategy requirements, boolean requireEmptySpace) {
|
||||
- BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable();
|
||||
+ // CraftBukkit start
|
||||
+ return SpawnUtil.trySpawnMob(entityType, reason, world, pos, tries, horizontalRange, verticalRange, requirements, requireEmptySpace, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ return SpawnUtil.trySpawnMob(entityType, reason, world, pos, tries, horizontalRange, verticalRange, requirements, requireEmptySpace, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT, null); // Paper - pre creature spawn event
|
||||
+ }
|
||||
|
||||
- for (int l = 0; l < tries; ++l) {
|
||||
- int i1 = Mth.randomBetweenInclusive(world.random, -horizontalRange, horizontalRange);
|
||||
- int j1 = Mth.randomBetweenInclusive(world.random, -horizontalRange, horizontalRange);
|
||||
+ public static <T extends Mob> Optional<T> trySpawnMob(EntityType<T> entitytypes, EntitySpawnReason entityspawnreason, ServerLevel worldserver, BlockPos blockposition, int i, int j, int k, SpawnUtil.Strategy spawnutil_a, boolean flag, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
|
||||
+ public static <T extends Mob> Optional<T> trySpawnMob(EntityType<T> entitytypes, EntitySpawnReason entityspawnreason, ServerLevel worldserver, BlockPos blockposition, int i, int j, int k, SpawnUtil.Strategy spawnutil_a, boolean flag, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason, @javax.annotation.Nullable Runnable onAbort) { // Paper - pre creature spawn event
|
||||
+ // CraftBukkit end
|
||||
+ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable();
|
||||
|
||||
|
@ -25,6 +25,22 @@
|
|||
|
||||
+ blockposition_mutableblockposition.setWithOffset(blockposition, i1, k, j1);
|
||||
+ if (worldserver.getWorldBorder().isWithinBounds((BlockPos) blockposition_mutableblockposition) && SpawnUtil.moveToPossibleSpawnPosition(worldserver, k, blockposition_mutableblockposition, spawnutil_a) && (!flag || worldserver.noCollision(entitytypes.getSpawnAABB((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D)))) {
|
||||
+ // Paper start - PreCreatureSpawnEvent
|
||||
+ final com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ io.papermc.paper.util.MCUtil.toLocation(worldserver, blockposition),
|
||||
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(entitytypes),
|
||||
+ reason
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ if (event.shouldAbortSpawn()) {
|
||||
+ if (onAbort != null) {
|
||||
+ onAbort.run();
|
||||
+ }
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ // Paper end - PreCreatureSpawnEvent
|
||||
+ T t0 = entitytypes.create(worldserver, (Consumer<T>) null, blockposition_mutableblockposition, entityspawnreason, false, false); // CraftBukkit - decompile error
|
||||
+
|
||||
if (t0 != null) {
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
}
|
||||
|
||||
public static <T extends Entity> Consumer<T> createDefaultStackConfig(Level world, ItemStack stack, @Nullable Player player) {
|
||||
@@ -464,21 +472,40 @@
|
||||
@@ -464,21 +472,50 @@
|
||||
CustomData customdata = (CustomData) stack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY);
|
||||
|
||||
return !customdata.isEmpty() ? chained.andThen((entity) -> {
|
||||
|
@ -82,12 +82,22 @@
|
|||
+ // CraftBukkit start
|
||||
+ return this.spawn(world, afterConsumer, pos, reason, alignPosition, invertY, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
|
||||
+ }
|
||||
+
|
||||
|
||||
+ @Nullable
|
||||
+ public T spawn(ServerLevel worldserver, @Nullable Consumer<T> consumer, BlockPos blockposition, EntitySpawnReason entityspawnreason, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start - PreCreatureSpawnEvent
|
||||
+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ io.papermc.paper.util.MCUtil.toLocation(worldserver, blockposition),
|
||||
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(this),
|
||||
+ spawnReason
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end - PreCreatureSpawnEvent
|
||||
+ T t0 = this.create(worldserver, consumer, blockposition, entityspawnreason, flag, flag1);
|
||||
|
||||
+
|
||||
if (t0 != null) {
|
||||
- world.addFreshEntityWithPassengers(t0);
|
||||
+ // CraftBukkit start
|
||||
|
@ -99,7 +109,7 @@
|
|||
if (t0 instanceof Mob) {
|
||||
Mob entityinsentient = (Mob) t0;
|
||||
|
||||
@@ -657,7 +684,7 @@
|
||||
@@ -657,7 +694,7 @@
|
||||
}
|
||||
|
||||
return entity;
|
||||
|
@ -108,7 +118,7 @@
|
|||
}
|
||||
|
||||
public static Stream<Entity> loadEntitiesRecursive(final List<? extends Tag> entityNbtList, final Level world, final EntitySpawnReason reason) {
|
||||
@@ -718,7 +745,7 @@
|
||||
@@ -718,7 +755,7 @@
|
||||
|
||||
@Nullable
|
||||
public T tryCast(Entity obj) {
|
||||
|
@ -117,7 +127,7 @@
|
|||
}
|
||||
|
||||
@Override
|
||||
@@ -791,7 +818,7 @@
|
||||
@@ -791,7 +828,7 @@
|
||||
this.canSpawnFarFromPlayer = spawnGroup == MobCategory.CREATURE || spawnGroup == MobCategory.MISC;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@
|
|||
|
||||
if (list1.size() >= requiredCount) {
|
||||
- if (!SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, EntitySpawnReason.MOB_SUMMONED, world, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM, false).isEmpty()) {
|
||||
+ if (!SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, EntitySpawnReason.MOB_SUMMONED, world, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE).isEmpty()) { // CraftBukkit
|
||||
+ if (SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, EntitySpawnReason.MOB_SUMMONED, world, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE, () -> {GolemSensor.golemDetected(this);}).isPresent()) { // CraftBukkit // Paper - Set Golem Last Seen to stop it from spawning another one
|
||||
list.forEach(GolemSensor::golemDetected);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,30 @@
|
|||
} else {
|
||||
boolean flag = false;
|
||||
RandomSource randomsource = world.getRandom();
|
||||
@@ -157,13 +164,26 @@
|
||||
@@ -123,8 +130,22 @@
|
||||
continue;
|
||||
}
|
||||
} else if (!SpawnPlacements.checkSpawnRules((EntityType) optional.get(), world, EntitySpawnReason.SPAWNER, blockposition1, world.getRandom())) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper start - PreCreatureSpawnEvent
|
||||
+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ io.papermc.paper.util.MCUtil.toLocation(world, d0, d1, d2),
|
||||
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(optional.get()),
|
||||
+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ flag = true;
|
||||
+ if (event.shouldAbortSpawn()) {
|
||||
+ break;
|
||||
+ }
|
||||
continue;
|
||||
}
|
||||
+ // Paper end - PreCreatureSpawnEvent
|
||||
|
||||
Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, EntitySpawnReason.SPAWNER, (entity1) -> {
|
||||
entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot());
|
||||
@@ -157,13 +178,26 @@
|
||||
((Mob) entity).finalizeSpawn(world, world.getCurrentDifficultyAt(entity.blockPosition()), EntitySpawnReason.SPAWNER, (SpawnGroupData) null);
|
||||
}
|
||||
|
||||
|
@ -69,7 +92,7 @@
|
|||
this.delay(world, pos);
|
||||
return;
|
||||
}
|
||||
@@ -174,7 +194,7 @@
|
||||
@@ -174,7 +208,7 @@
|
||||
((Mob) entity).spawnAnim();
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,22 @@
|
|||
list.add(enumcreaturetype);
|
||||
}
|
||||
}
|
||||
@@ -217,10 +238,15 @@
|
||||
@@ -207,7 +228,13 @@
|
||||
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 - PreCreatureSpawnEvent
|
||||
+ PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
|
||||
+ if (doSpawning == PreSpawnStatus.ABORT) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (doSpawning == PreSpawnStatus.SUCCESS && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) {
|
||||
+ // Paper end - PreCreatureSpawnEvent
|
||||
Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type);
|
||||
|
||||
if (entityinsentient == null) {
|
||||
@@ -217,10 +244,15 @@
|
||||
entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F);
|
||||
if (NaturalSpawner.isValidPositionForMob(world, entityinsentient, d2)) {
|
||||
groupdataentity = entityinsentient.finalizeSpawn(world, world.getCurrentDifficultyAt(entityinsentient.blockPosition()), EntitySpawnReason.NATURAL, groupdataentity);
|
||||
|
@ -68,7 +83,41 @@
|
|||
if (j >= entityinsentient.getMaxSpawnClusterSize()) {
|
||||
return;
|
||||
}
|
||||
@@ -268,6 +294,7 @@
|
||||
@@ -250,10 +282,31 @@
|
||||
return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerToCenterThan(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.isNaturalSpawningAllowed((BlockPos) pos));
|
||||
}
|
||||
|
||||
- private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) {
|
||||
+ // Paper start - PreCreatureSpawnEvent
|
||||
+ private enum PreSpawnStatus {
|
||||
+ FAIL,
|
||||
+ SUCCESS,
|
||||
+ CANCELLED,
|
||||
+ ABORT
|
||||
+ }
|
||||
+ private static PreSpawnStatus isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) {
|
||||
+ // Paper end - PreCreatureSpawnEvent
|
||||
EntityType<?> entitytypes = spawnEntry.type;
|
||||
|
||||
- return entitytypes.getCategory() == MobCategory.MISC ? false : (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance()) ? false : (entitytypes.canSummon() && NaturalSpawner.canSpawnMobAt(world, structureAccessor, chunkGenerator, group, spawnEntry, pos) ? (!SpawnPlacements.isSpawnPositionOk(entitytypes, world, pos) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, world, EntitySpawnReason.NATURAL, pos, world.random) ? false : world.noCollision(entitytypes.getSpawnAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)))) : false));
|
||||
+ // Paper start - PreCreatureSpawnEvent
|
||||
+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent(
|
||||
+ io.papermc.paper.util.MCUtil.toLocation(world, pos),
|
||||
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(entitytypes), SpawnReason.NATURAL
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ if (event.shouldAbortSpawn()) {
|
||||
+ return PreSpawnStatus.ABORT;
|
||||
+ }
|
||||
+ return PreSpawnStatus.CANCELLED;
|
||||
+ }
|
||||
+ // Paper end - PreCreatureSpawnEvent
|
||||
+
|
||||
+ return entitytypes.getCategory() == MobCategory.MISC ? PreSpawnStatus.FAIL : (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance()) ? PreSpawnStatus.FAIL : (entitytypes.canSummon() && NaturalSpawner.canSpawnMobAt(world, structureAccessor, chunkGenerator, group, spawnEntry, pos) ? (!SpawnPlacements.isSpawnPositionOk(entitytypes, world, pos) ? PreSpawnStatus.FAIL : (!SpawnPlacements.checkSpawnRules(entitytypes, world, EntitySpawnReason.NATURAL, pos, world.random) ? PreSpawnStatus.FAIL : world.noCollision(entitytypes.getSpawnAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)) ? PreSpawnStatus.SUCCESS : PreSpawnStatus.FAIL)) : PreSpawnStatus.FAIL)); // Paper - PreCreatureSpawnEvent
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -268,6 +321,7 @@
|
||||
NaturalSpawner.LOGGER.warn("Can't spawn entity of type: {}", BuiltInRegistries.ENTITY_TYPE.getKey(type));
|
||||
} catch (Exception exception) {
|
||||
NaturalSpawner.LOGGER.warn("Failed to create mob", exception);
|
||||
|
@ -76,7 +125,7 @@
|
|||
}
|
||||
|
||||
return null;
|
||||
@@ -356,6 +383,7 @@
|
||||
@@ -356,6 +410,7 @@
|
||||
entity = biomesettingsmobs_c.type.create(world.getLevel(), EntitySpawnReason.NATURAL);
|
||||
} catch (Exception exception) {
|
||||
NaturalSpawner.LOGGER.warn("Failed to create mob", exception);
|
||||
|
@ -84,7 +133,7 @@
|
|||
continue;
|
||||
}
|
||||
|
||||
@@ -369,7 +397,7 @@
|
||||
@@ -369,7 +424,7 @@
|
||||
|
||||
if (entityinsentient.checkSpawnRules(world, EntitySpawnReason.CHUNK_GENERATION) && entityinsentient.checkSpawnObstruction(world)) {
|
||||
groupdataentity = entityinsentient.finalizeSpawn(world, world.getCurrentDifficultyAt(entityinsentient.blockPosition()), EntitySpawnReason.CHUNK_GENERATION, groupdataentity);
|
||||
|
@ -93,7 +142,7 @@
|
|||
flag = true;
|
||||
}
|
||||
}
|
||||
@@ -482,10 +510,12 @@
|
||||
@@ -482,10 +537,12 @@
|
||||
return this.unmodifiableMobCategoryCounts;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue