PaperMC/paper-server/patches/sources/net/minecraft/world/level/BaseSpawner.java.patch
Aikar aebf9e869b Fix Entity Teleportation and cancel velocity if teleported
Uses correct setPositionRotation for Entity teleporting instead of setLocation
as this is how Vanilla teleports entities.

Cancel any pending motion when teleported.
2020-08-25 20:45:36 -04:00

166 lines
8.5 KiB
Diff

--- a/net/minecraft/world/level/BaseSpawner.java
+++ b/net/minecraft/world/level/BaseSpawner.java
@@ -49,15 +49,17 @@
public int maxNearbyEntities = 6;
public int requiredPlayerRange = 16;
public int spawnRange = 4;
+ private int tickDelay = 0; // Paper - Configurable mob spawner tick rate
public BaseSpawner() {}
public void setEntityId(EntityType<?> type, @Nullable Level world, RandomSource random, BlockPos pos) {
this.getOrCreateNextSpawnData(world, random, pos).getEntityToSpawn().putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(type).toString());
+ this.spawnPotentials = SimpleWeightedRandomList.empty(); // CraftBukkit - SPIGOT-3496, MC-92282
}
public boolean isNearPlayer(Level world, BlockPos pos) {
- return world.hasNearbyAlivePlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange);
+ return world.hasNearbyAlivePlayerThatAffectsSpawning((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper - Affects Spawning API
}
public void clientTick(Level world, BlockPos pos) {
@@ -82,13 +84,18 @@
}
public void serverTick(ServerLevel world, BlockPos pos) {
+ // Paper start - Configurable mob spawner tick rate
+ if (spawnDelay > 0 && --tickDelay > 0) return;
+ tickDelay = world.paperConfig().tickRates.mobSpawner;
+ if (tickDelay == -1) { return; } // If disabled
+ // Paper end - Configurable mob spawner tick rate
if (this.isNearPlayer(world, pos)) {
- if (this.spawnDelay == -1) {
+ if (this.spawnDelay < -tickDelay) { // Paper - Configurable mob spawner tick rate
this.delay(world, pos);
}
if (this.spawnDelay > 0) {
- --this.spawnDelay;
+ this.spawnDelay -= tickDelay; // Paper - Configurable mob spawner tick rate
} else {
boolean flag = false;
RandomSource randomsource = world.getRandom();
@@ -125,6 +132,20 @@
} else if (!SpawnPlacements.checkSpawnRules((EntityType) optional.get(), world, EntitySpawnReason.SPAWNER, blockposition1, world.getRandom())) {
continue;
}
+ // Paper start - PreCreatureSpawnEvent
+ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent(
+ io.papermc.paper.util.MCUtil.toLocation(world, d0, d1, d2),
+ org.bukkit.craftbukkit.entity.CraftEntityType.minecraftToBukkit(optional.get()),
+ io.papermc.paper.util.MCUtil.toLocation(world, pos)
+ );
+ 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());
@@ -143,6 +164,7 @@
return;
}
+ entity.preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; preserve entity motion from tag
entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), randomsource.nextFloat() * 360.0F, 0.0F);
if (entity instanceof Mob) {
Mob entityinsentient = (Mob) entity;
@@ -157,13 +179,27 @@
((Mob) entity).finalizeSpawn(world, world.getCurrentDifficultyAt(entity.blockPosition()), EntitySpawnReason.SPAWNER, (SpawnGroupData) null);
}
- Optional optional1 = mobspawnerdata.getEquipment();
+ Optional<net.minecraft.world.entity.EquipmentTable> optional1 = mobspawnerdata.getEquipment(); // CraftBukkit - decompile error
Objects.requireNonNull(entityinsentient);
optional1.ifPresent(entityinsentient::equip);
+ // Spigot Start
+ if ( entityinsentient.level().spigotConfig.nerfSpawnerMobs )
+ {
+ entityinsentient.aware = false;
+ }
+ // Spigot End
}
- if (!world.tryAddFreshEntityWithPassengers(entity)) {
+ entity.spawnedViaMobSpawner = true; // Paper
+ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper - Entity#getEntitySpawnReason
+ flag = true; // Paper
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) {
+ continue;
+ }
+ if (!world.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER)) {
+ // CraftBukkit end
this.delay(world, pos);
return;
}
@@ -174,7 +210,7 @@
((Mob) entity).spawnAnim();
}
- flag = true;
+ //flag = true; // Paper - moved up above cancellable event
}
}
@@ -202,7 +238,13 @@
}
public void load(@Nullable Level world, BlockPos pos, CompoundTag nbt) {
+ // Paper start - use larger int if set
+ if (nbt.contains("Paper.Delay")) {
+ this.spawnDelay = nbt.getInt("Paper.Delay");
+ } else {
this.spawnDelay = nbt.getShort("Delay");
+ }
+ // Paper end
boolean flag = nbt.contains("SpawnData", 10);
if (flag) {
@@ -225,9 +267,15 @@
this.spawnPotentials = SimpleWeightedRandomList.single(this.nextSpawnData != null ? this.nextSpawnData : new SpawnData());
}
+ // Paper start - use ints if set
+ if (nbt.contains("Paper.MinSpawnDelay", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ this.minSpawnDelay = nbt.getInt("Paper.MinSpawnDelay");
+ this.maxSpawnDelay = nbt.getInt("Paper.MaxSpawnDelay");
+ this.spawnCount = nbt.getShort("SpawnCount");
+ } else // Paper end
if (nbt.contains("MinSpawnDelay", 99)) {
- this.minSpawnDelay = nbt.getShort("MinSpawnDelay");
- this.maxSpawnDelay = nbt.getShort("MaxSpawnDelay");
+ this.minSpawnDelay = nbt.getInt("MinSpawnDelay"); // Paper - short -> int
+ this.maxSpawnDelay = nbt.getInt("MaxSpawnDelay"); // Paper - short -> int
this.spawnCount = nbt.getShort("SpawnCount");
}
@@ -244,9 +292,20 @@
}
public CompoundTag save(CompoundTag nbt) {
- nbt.putShort("Delay", (short) this.spawnDelay);
- nbt.putShort("MinSpawnDelay", (short) this.minSpawnDelay);
- nbt.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay);
+ // Paper start
+ if (spawnDelay > Short.MAX_VALUE) {
+ nbt.putInt("Paper.Delay", this.spawnDelay);
+ }
+ nbt.putShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay));
+
+ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) {
+ nbt.putInt("Paper.MinSpawnDelay", this.minSpawnDelay);
+ nbt.putInt("Paper.MaxSpawnDelay", this.maxSpawnDelay);
+ }
+
+ nbt.putShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay));
+ nbt.putShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay));
+ // Paper end
nbt.putShort("SpawnCount", (short) this.spawnCount);
nbt.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities);
nbt.putShort("RequiredPlayerRange", (short) this.requiredPlayerRange);