aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0974-Don-t-fire-sync-events-during-worldgen.patch
blob: 52b64544043c0550598f08b354d3f8fcb0995d22 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
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 0e7811ae2a8731ae7475aabd2322e56ab364bc32..b5d6a7eaa24d9968e159d77a4295be00332a5457 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1220,6 +1220,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 55feebb8e75bdeab4d089a1d6f80be49996dfcb6..7fa7cb2a567c90a4bb7cf20c7182c45395b6ea32 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 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 fe8efe89c7d390ff9565f388685b57daeebfd08b..0f111b76ccbc260a1dad562c9c1d8a0465849dfe 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 f6eda18a0bcc398538c76bf4ca7c2a611523aa5d..be0fa9a9e91c87234b0cd7b63c4e7dba8629ebe5 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 d90da2f9e4d6214577bc81bd6c70ba8593788898..ffa4f34d964fbcc53e2dfe11677832db21a6eb93 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 e37c2d82ed606cbfe00c152b08c3ab99ac751f69..7ed861cd67889e525ab4987c0afed245aca08833 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) {