PaperMC/patches/server-remapped/PreCreatureSpawnEvent.patch
MiniDigger | Martin 95d25d98e8 Move patches around
2021-06-11 14:02:28 +02:00

215 lines
14 KiB
Diff

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
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
@@ -0,0 +0,0 @@ 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;
@@ -0,0 +0,0 @@ public class EntityType<T extends Entity> {
@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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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
@@ -0,0 +0,0 @@ public class GolemSensor extends Sensor<LivingEntity> {
Optional<List<LivingEntity>> 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) {
@@ -0,0 +0,0 @@ public class GolemSensor extends Sensor<LivingEntity> {
}
}
+ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -0,0 +0,0 @@ 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;
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -0,0 +0,0 @@ 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;
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
@@ -0,0 +0,0 @@ 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;
@@ -0,0 +0,0 @@ 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;
}
@@ -0,0 +0,0 @@ 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;
}