aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0913-Don-t-fire-sync-events-during-worldgen.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0913-Don-t-fire-sync-events-during-worldgen.patch')
-rw-r--r--patches/server/0913-Don-t-fire-sync-events-during-worldgen.patch208
1 files changed, 208 insertions, 0 deletions
diff --git a/patches/server/0913-Don-t-fire-sync-events-during-worldgen.patch b/patches/server/0913-Don-t-fire-sync-events-during-worldgen.patch
new file mode 100644
index 0000000000..9ee1999a85
--- /dev/null
+++ b/patches/server/0913-Don-t-fire-sync-events-during-worldgen.patch
@@ -0,0 +1,208 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jake Potrebic <[email protected]>
+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 c5e404dcdab14dc0b972aa3286b05e21d9ea67e0..aaaf5b91402a1562311dfdc287193a1aefbaf9a7 100644
+--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
+@@ -1224,6 +1224,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 23442e0f887cec3c3a65b3dd3d0f4f40db0e54b1..24aacf9997c9ea0bd68ef3803f4a3ee4a920ab44 100644
+--- a/src/main/java/net/minecraft/world/entity/Entity.java
++++ b/src/main/java/net/minecraft/world/entity/Entity.java
+@@ -625,7 +625,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+ 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 5fb3279342506611882b5780cfbee0371919c93c..b98f9246b60daf31460f41ce214dfa7c011f5684 100644
+--- a/src/main/java/net/minecraft/world/entity/EntityType.java
++++ b/src/main/java/net/minecraft/world/entity/EntityType.java
+@@ -592,9 +592,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 2ad88bc281861f53b5d65ce81448a334849ffff0..2cbb4ff57117382791eefa4881fc0b328c77d58a 100644
+--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
+@@ -1138,6 +1138,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));
+@@ -1157,10 +1162,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) {
+@@ -1169,7 +1177,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+ flag = true;
+ mobeffect.onEffectAdded(this);
+ // 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 6006480d9f6d60bb7b5628eabe6740013066cde4..f0127f1b55999aa4a841341ad02cbcde45702b50 100644
+--- a/src/main/java/net/minecraft/world/entity/monster/Spider.java
++++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java
+@@ -172,7 +172,7 @@ public class Spider extends Monster {
+ Holder<MobEffect> holder = entityspider_groupdataspider.effect;
+
+ if (holder != null) {
+- this.addEffect(new MobEffectInstance(holder, -1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN); // CraftBukkit
++ this.addEffect(new MobEffectInstance(holder, -1), null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN, world instanceof net.minecraft.server.level.ServerLevel); // CraftBukkit
+ }
+ }
+
+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 cf8258e8d46ca7286a66c38fa24af369bd9a279f..0555abfda468c343af8244a122ebe769e70a0292 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
+@@ -525,7 +525,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 524b51a0ab808a0629c871ad813115abd4b49dbd..fceed3d08ee6f4c171685986bb19d2be592eedc6 100644
+--- a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
++++ b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
+@@ -92,15 +92,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 35ecf6f824aca56a20280dd683123df1d0c7d66e..1d1fdcf10498c421f106158254e052da6d68d8a5 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) {