--- a/net/minecraft/util/SpawnUtil.java +++ b/net/minecraft/util/SpawnUtil.java @@ -16,6 +_,7 @@ import net.minecraft.world.level.block.state.BlockState; public class SpawnUtil { + public static Optional trySpawnMob( EntityType entityType, EntitySpawnReason spawnReason, @@ -27,6 +_,24 @@ SpawnUtil.Strategy strategy, boolean checkCollision ) { + // CraftBukkit start + return trySpawnMob(entityType, spawnReason, level, pos, attempts, range, yOffset, strategy, checkCollision, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT, null); // Paper - pre creature spawn event + } + + public static Optional trySpawnMob( + EntityType entityType, + EntitySpawnReason spawnReason, + ServerLevel level, + BlockPos pos, + int attempts, + int range, + int yOffset, + SpawnUtil.Strategy strategy, + boolean checkCollision, + org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason, + @javax.annotation.Nullable Runnable onAbort // Paper - pre creature spawn event + ) { + // CraftBukkit end BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); for (int i = 0; i < attempts; i++) { @@ -39,15 +_,32 @@ !checkCollision || level.noCollision(entityType.getSpawnAABB(mutableBlockPos.getX() + 0.5, mutableBlockPos.getY(), mutableBlockPos.getZ() + 0.5)) )) { + // Paper start - PreCreatureSpawnEvent + final com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( + io.papermc.paper.util.MCUtil.toLocation(level, pos), + org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(entityType), + reason + ); + if (!event.callEvent()) { + if (event.shouldAbortSpawn()) { + if (onAbort != null) { + onAbort.run(); + } + return Optional.empty(); + } + break; + } + // Paper end - PreCreatureSpawnEvent T mob = (T)entityType.create(level, null, mutableBlockPos, spawnReason, false, false); if (mob != null) { if (mob.checkSpawnRules(level, spawnReason) && mob.checkSpawnObstruction(level)) { - level.addFreshEntityWithPassengers(mob); + level.addFreshEntityWithPassengers(mob, reason); // CraftBukkit + if (mob.isRemoved()) return Optional.empty(); // CraftBukkit mob.playAmbientSound(); return Optional.of(mob); } - mob.discard(); + mob.discard(null); // CraftBukkit - add Bukkit remove cause } } }