Paper/patches/server/0909-Don-t-fire-sync-events-during-worldgen.patch
Bjarne Koll d1a72eac31
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#11405)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
1fc1020a PR-1049: Add MenuType API
8ae2e3be PR-1055: Expand riptiding API
cac68bfb SPIGOT-7890: AttributeModifier#getUniqueId() doesn't match the UUID passed to its constructor
7004fcf2 SPIGOT-7886: Fix mistake in AttributeModifier UUID shim
1ac7f950 PR-1054: Add FireworkMeta#hasPower
4cfb565f SPIGOT-7873: Add powered state for skulls

CraftBukkit Changes:
bbb30e7a8 SPIGOT-7894: NPE when sending tile entity update
ba21e9472 SPIGOT-7895: PlayerItemBreakEvent not firing
0fb24bbe0 SPIGOT-7875: Fix PlayerItemConsumeEvent cancellation causing client-side desync
815066449 SPIGOT-7891: Can't remove second ingredient of MerchantRecipe
45c206f2c PR-1458: Add MenuType API
19c8ef9ae SPIGOT-7867: Merchant instanceof AbstractVillager always returns false
4e006d28f PR-1468: Expand riptiding API
bd8aded7d Ignore checks in CraftPlayerProfile for ResolvableProfile used in profile components
8679620b5 SPIGOT-7889: Fix tool component deserialisation without speed and/or correct-for-drops
8d5222691 SPIGOT-7882, PR-1467: Fix conversion of name in Profile Component to empty if it is missing
63f91669a SPIGOT-7887: Remove duplicate ProjectileHitEvent for fireballs
7070de8c8 SPIGOT-7878: Server#getLootTable does not return null on invalid loot table
060ee6cae SPIGOT-7876: Can't kick player or disconnect player in PlayerLoginEvent when checking for cookies
7ccb86cc0 PR-1465: Add FireworkMeta#hasPower
804ad6491 SPIGOT-7873: Add powered state for skulls
f9610cdcb Improve minecart movement

Spigot Changes:
a759b629 Rebuild patches

Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-09-15 21:39:53 +02:00

209 lines
12 KiB
Diff

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 60c75f7c4258efb26c2595ca7724b08d3c046c9d..34ece37aee68e4d8eeaa919e8bd489a672756049 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 bd0e205c760414784ae483452fd02292939dcb5c..f163cb3c75e90b96b3794a7e0c5b803268814c8c 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -624,7 +624,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 04232f281ebd46954ef2259962c7bfc43b8a8aeb..0c67f04ae7eeaa10a90419031447ad5397c6b9e2 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 f91ea9ac5a0d0d3bae5d1eb0c409f4f9c4e5a62b..9045f18f49a5c6685597d0a77126d7cb35bc5e88 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) {