PaperMC/patches/server/0976-Don-t-fire-sync-events-during-worldgen.patch

209 lines
12 KiB
Diff
Raw Normal View History

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 23 Nov 2023 10:33:25 -0800
Subject: [PATCH] Don't fire sync events during worldgen
Fixes EntityPotionEffectEvent
Fixes EntityPoseChangeEvent
Asynchronous chunk generation provides an opportunity for things
to happen async that previously fired synchronous-only events. This
patch is for mitigating those issues by various methods.
Also fixes correctly marking/clearing the entity generation flag.
This patch sets the generation flag anytime an entity is created
via StructureTemplate before loading from NBT to catch uses of
the flag during the loading logic. This patch clears the generation
flag from an entity when added to a ServerLevel for the situation
where generation happened directly to a ServerLevel and the
entity still has the flag set.
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 2ab478e0940eae27e6e886a36ed3c1278b3f8ae1..b54e89d68ba32f2a79e16d49f86a258b5f6df133 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1490,6 +1490,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
// CraftBukkit start
private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
+ entity.generation = false; // Paper - Don't fire sync event during generation; Reset flag if it was added during a ServerLevel generation process
// Paper start - extra debug info
if (entity.valid) {
MinecraftServer.LOGGER.error("Attempted Double World add on {}", entity, new Throwable());
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index ba9a1f9bd38f8ac58449787a9697c28fe300193a..3c3f9a51256acb6ee4f005a08757d7ae0d27860e 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -676,7 +676,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
if (pose == this.getPose()) {
return;
}
- this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[pose.ordinal()]));
+ // Paper start - Don't fire sync event during generation
+ if (!this.generation) {
+ this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[pose.ordinal()]));
+ }
+ // Paper end - Don't fire sync event during generation
// CraftBukkit end
this.entityData.set(Entity.DATA_POSE, pose);
}
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
index a6e20b5ee4fe1841dfc2350264b5935b968fe3f3..9da8d56ff3768fb37d1ab89300da4eca19e6218d 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
@@ -588,9 +588,15 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
}
public static Optional<Entity> create(CompoundTag nbt, Level world) {
+ // Paper start - Don't fire sync event during generation
+ return create(nbt, world, false);
+ }
+ public static Optional<Entity> create(CompoundTag nbt, Level world, boolean generation) {
+ // Paper end - Don't fire sync event during generation
return Util.ifElse(EntityType.by(nbt).map((entitytypes) -> {
return entitytypes.create(world);
}), (entity) -> {
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
entity.load(nbt);
}, () -> {
EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id"));
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 60841e31c65ba8e95fbb3b5a16a7a0d1c2eb831d..5e1d02d67c56644c0aa7060d567515fd88b72c9d 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -1134,6 +1134,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) {
+ // Paper start - Don't fire sync event during generation
+ return this.addEffect(mobeffect, entity, cause, true);
+ }
+ public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) {
+ // Paper end - Don't fire sync event during generation
// org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API
if (this.isTickingEffects) {
this.effectsToProcess.add(new ProcessableEffect(mobeffect, cause));
@@ -1153,10 +1158,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
override = new MobEffectInstance(mobeffect1).update(mobeffect);
}
+ if (fireEvent) { // Paper - Don't fire sync event during generation
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect1, mobeffect, cause, override);
+ override = event.isOverride(); // Paper - Don't fire sync event during generation
if (event.isCancelled()) {
return false;
}
+ } // Paper - Don't fire sync event during generation
// CraftBukkit end
if (mobeffect1 == null) {
@@ -1164,7 +1172,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.onEffectAdded(mobeffect, entity);
flag = true;
// CraftBukkit start
- } else if (event.isOverride()) {
+ } else if (override) { // Paper - Don't fire sync event during generation
mobeffect1.update(mobeffect);
this.onEffectUpdated(mobeffect1, true, entity);
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/entity/monster/Spider.java b/src/main/java/net/minecraft/world/entity/monster/Spider.java
index ff004d5c0dee027acea51aa4886065636335e2a9..0c68ed759421d6bce4435399f1b4980510081cac 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Spider.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java
@@ -182,7 +182,7 @@ public class Spider extends Monster {
MobEffect mobeffectlist = entityspider_groupdataspider.effect;
if (mobeffectlist != null) {
- this.addEffect(new MobEffectInstance(mobeffectlist, -1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN); // CraftBukkit
+ this.addEffect(new MobEffectInstance(mobeffectlist, -1), null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN, world instanceof net.minecraft.server.level.ServerLevel); // CraftBukkit // Paper - Don't fire sync event during generation; only if this is happening in a ServerLevel
}
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
index ae8a42261337bf736d0cc1bbe18da2b773417ca4..471e8493622c89d44a82f42f135cb308c9e0fbfe 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
@@ -518,7 +518,7 @@ public class StructureTemplate {
private static Optional<Entity> createEntityIgnoreException(ServerLevelAccessor world, CompoundTag nbt) {
// CraftBukkit start
// try {
- return EntityType.create(nbt, world.getLevel());
+ return EntityType.create(nbt, world.getLevel(), true); // Paper - Don't fire sync event during generation
// } catch (Exception exception) {
// return Optional.empty();
// }
diff --git a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
index a650411e3fa7e2a045ac55502c77028be348acf1..86a20c91beff6b27e6ec886e49ba902b216106f2 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
@@ -93,15 +93,17 @@ public abstract class DelegatedGeneratorAccess implements WorldGenLevel {
return this.handle.getLevel();
}
- @Override
- public void addFreshEntityWithPassengers(Entity arg0, CreatureSpawnEvent.SpawnReason arg1) {
- this.handle.addFreshEntityWithPassengers(arg0, arg1);
- }
-
- @Override
- public void addFreshEntityWithPassengers(Entity entity) {
- this.handle.addFreshEntityWithPassengers(entity);
- }
+ // Paper start - Don't fire sync event during generation; don't override these methods so all entities are run through addFreshEntity
+ // @Override
+ // public void addFreshEntityWithPassengers(Entity arg0, CreatureSpawnEvent.SpawnReason arg1) {
+ // this.handle.addFreshEntityWithPassengers(arg0, arg1);
+ // }
+ //
+ // @Override
+ // public void addFreshEntityWithPassengers(Entity entity) {
+ // this.handle.addFreshEntityWithPassengers(entity);
+ // }
+ // Paper end - Don't fire sync event during generation; don't override these methods
@Override
public ServerLevel getMinecraftWorld() {
diff --git a/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java
index b4b297945fb601701aac845d09e88fb74b09c3fa..7482dfe64458320d44089c0778591694202e9f70 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java
@@ -39,21 +39,23 @@ public class TransformerGeneratorAccess extends DelegatedGeneratorAccess {
return super.addFreshEntity(arg0, arg1);
}
- @Override
- public void addFreshEntityWithPassengers(Entity entity) {
- if (this.structureTransformer != null && !this.structureTransformer.transformEntity(entity)) {
- return;
- }
- super.addFreshEntityWithPassengers(entity);
- }
-
- @Override
- public void addFreshEntityWithPassengers(Entity arg0, SpawnReason arg1) {
- if (this.structureTransformer != null && !this.structureTransformer.transformEntity(arg0)) {
- return;
- }
- super.addFreshEntityWithPassengers(arg0, arg1);
- }
+ // Paper start - Don't fire sync event during generation; don't override these methods so all entities are run through addFreshEntity
+ // @Override
+ // public void addFreshEntityWithPassengers(Entity entity) {
+ // if (this.structureTransformer != null && !this.structureTransformer.transformEntity(entity)) {
+ // return;
+ // }
+ // super.addFreshEntityWithPassengers(entity);
+ // }
+ //
+ // @Override
+ // public void addFreshEntityWithPassengers(Entity arg0, SpawnReason arg1) {
+ // if (this.structureTransformer != null && !this.structureTransformer.transformEntity(arg0)) {
+ // return;
+ // }
+ // super.addFreshEntityWithPassengers(arg0, arg1);
+ // }
+ // Paper end - Don't fire sync event during generation; don't override these methods
public boolean setCraftBlock(BlockPos position, CraftBlockState craftBlockState, int i, int j) {
if (this.structureTransformer != null) {