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.
This commit is contained in:
Jake Potrebic
2023-11-23 10:33:25 -08:00
parent 5f134afc4b
commit fff5d44a12
8 changed files with 252 additions and 218 deletions

View File

@@ -80,7 +80,7 @@
+ public final UUID uuid;
+ public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
+ public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
+
+ public LevelChunk getChunkIfLoaded(int x, int z) {
+ return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
+ }
@@ -142,7 +142,7 @@
+
+ this.loadChunks(minChunkX, minChunkZ, maxChunkX, maxChunkZ, priority, onLoad);
+ }
+
+ public final void loadChunks(int minChunkX, int minChunkZ, int maxChunkX, int maxChunkZ,
+ ca.spottedleaf.concurrentutil.util.Priority priority,
+ java.util.function.Consumer<List<net.minecraft.world.level.chunk.ChunkAccess>> onLoad) {
@@ -638,7 +638,7 @@
}
}
@@ -939,41 +1192,104 @@
@@ -939,41 +1192,105 @@
this.entityManager.addNewEntity(player);
}
@@ -646,6 +646,7 @@
+ // 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());
@@ -748,7 +749,7 @@
while (iterator.hasNext()) {
ServerPlayer entityplayer = (ServerPlayer) iterator.next();
@@ -982,6 +1298,12 @@
@@ -982,6 +1299,12 @@
double d1 = (double) pos.getY() - entityplayer.getY();
double d2 = (double) pos.getZ() - entityplayer.getZ();
@@ -761,7 +762,7 @@
if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) {
entityplayer.connection.send(new ClientboundBlockDestructionPacket(entityId, pos, progress));
}
@@ -1030,7 +1352,7 @@
@@ -1030,7 +1353,7 @@
@Override
public void levelEvent(@Nullable Player player, int eventId, BlockPos pos, int data) {
@@ -770,7 +771,7 @@
}
public int getLogicalHeight() {
@@ -1039,6 +1361,11 @@
@@ -1039,6 +1362,11 @@
@Override
public void gameEvent(Holder<GameEvent> event, Vec3 emitterPos, GameEvent.Context emitter) {
@@ -782,7 +783,7 @@
this.gameEventDispatcher.post(event, emitterPos, emitter);
}
@@ -1052,6 +1379,7 @@
@@ -1052,6 +1380,7 @@
this.getChunkSource().blockChanged(pos);
this.pathTypesByPosCache.invalidate(pos);
@@ -790,7 +791,7 @@
VoxelShape voxelshape = oldState.getCollisionShape(this, pos);
VoxelShape voxelshape1 = newState.getCollisionShape(this, pos);
@@ -1060,7 +1388,18 @@
@@ -1060,7 +1389,18 @@
Iterator iterator = this.navigatingMobs.iterator();
while (iterator.hasNext()) {
@@ -810,7 +811,7 @@
PathNavigation navigationabstract = entityinsentient.getNavigation();
if (navigationabstract.shouldRecomputePath(pos)) {
@@ -1082,15 +1421,18 @@
@@ -1082,15 +1422,18 @@
}
}
@@ -829,7 +830,7 @@
this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, (Direction) null, orientation);
}
@@ -1126,9 +1468,20 @@
@@ -1126,9 +1469,20 @@
@Override
public void explode(@Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator behavior, double x, double y, double z, float power, boolean createFire, Level.ExplosionInteraction explosionSourceType, ParticleOptions smallParticle, ParticleOptions largeParticle, Holder<SoundEvent> soundEvent) {
@@ -851,7 +852,7 @@
case NONE:
explosion_effect = Explosion.BlockInteraction.KEEP;
break;
@@ -1144,16 +1497,27 @@
@@ -1144,16 +1498,27 @@
case TRIGGER:
explosion_effect = Explosion.BlockInteraction.TRIGGER_BLOCK;
break;
@@ -882,7 +883,7 @@
Iterator iterator = this.players.iterator();
while (iterator.hasNext()) {
@@ -1162,10 +1526,11 @@
@@ -1162,10 +1527,11 @@
if (entityplayer.distanceToSqr(vec3d) < 4096.0D) {
Optional<Vec3> optional = Optional.ofNullable((Vec3) serverexplosion.getHitPlayers().get(entityplayer));
@@ -895,7 +896,7 @@
}
private Explosion.BlockInteraction getDestroyType(GameRules.Key<GameRules.BooleanValue> decayRule) {
@@ -1226,17 +1591,29 @@
@@ -1226,17 +1592,29 @@
}
public <T extends ParticleOptions> int sendParticles(T parameters, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double speed) {
@@ -930,7 +931,7 @@
++j;
}
}
@@ -1292,7 +1669,7 @@
@@ -1292,7 +1670,7 @@
@Nullable
public BlockPos findNearestMapStructure(TagKey<Structure> structureTag, BlockPos pos, int radius, boolean skipReferencedStructures) {
@@ -939,7 +940,7 @@
return null;
} else {
Optional<HolderSet.Named<Structure>> optional = this.registryAccess().lookupOrThrow(Registries.STRUCTURE).get(structureTag);
@@ -1334,11 +1711,38 @@
@@ -1334,11 +1712,38 @@
@Nullable
@Override
public MapItemSavedData getMapData(MapId id) {
@@ -979,7 +980,7 @@
this.getServer().overworld().getDataStorage().set(id.key(), state);
}
@@ -1352,7 +1756,9 @@
@@ -1352,7 +1757,9 @@
float f1 = this.levelData.getSpawnAngle();
if (!blockposition1.equals(pos) || f1 != angle) {
@@ -989,7 +990,7 @@
this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(pos, angle));
}
@@ -1419,6 +1825,11 @@
@@ -1419,6 +1826,11 @@
});
optional1.ifPresent((holder) -> {
this.getServer().execute(() -> {
@@ -1001,7 +1002,7 @@
this.getPoiManager().add(blockposition1, holder);
DebugPackets.sendPoiAddedPacket(this, blockposition1);
});
@@ -1649,6 +2060,11 @@
@@ -1649,6 +2061,11 @@
@Override
public void blockUpdated(BlockPos pos, Block block) {
if (!this.isDebug()) {
@@ -1013,7 +1014,7 @@
this.updateNeighborsAt(pos, block);
}
@@ -1668,12 +2084,12 @@
@@ -1668,12 +2085,12 @@
}
public boolean isFlat() {
@@ -1028,7 +1029,7 @@
}
@Nullable
@@ -1696,7 +2112,7 @@
@@ -1696,7 +2113,7 @@
private static <T> String getTypeCount(Iterable<T> items, Function<T, String> classifier) {
try {
Object2IntOpenHashMap<String> object2intopenhashmap = new Object2IntOpenHashMap();
@@ -1037,7 +1038,7 @@
while (iterator.hasNext()) {
T t0 = iterator.next();
@@ -1705,7 +2121,7 @@
@@ -1705,7 +2122,7 @@
object2intopenhashmap.addTo(s, 1);
}
@@ -1046,7 +1047,7 @@
String s1 = (String) entry.getKey();
return s1 + ":" + entry.getIntValue();
@@ -1717,6 +2133,7 @@
@@ -1717,6 +2134,7 @@
@Override
public LevelEntityGetter<Entity> getEntities() {
@@ -1054,10 +1055,12 @@
return this.entityManager.getEntityGetter();
}
@@ -1802,6 +2219,27 @@
return this.serverLevelData.getGameRules();
}
@@ -1800,7 +2218,28 @@
public GameRules getGameRules() {
return this.serverLevelData.getGameRules();
+ }
+
+ // Paper start - respect global sound events gamerule
+ public List<net.minecraft.server.level.ServerPlayer> getPlayersForGlobalSoundGamerule() {
+ return this.getGameRules().getBoolean(GameRules.RULE_GLOBAL_SOUND_EVENTS) ? ((ServerLevel) this).getServer().getPlayerList().players : ((ServerLevel) this).players();
@@ -1076,13 +1079,12 @@
+ if (craftBlockState.getPosition().getY() == pos.getY() && this.getBlockState(craftBlockState.getPosition()) == craftBlockState.getHandle()) {
+ this.notifyAndUpdatePhysics(craftBlockState.getPosition(), null, craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getFlag(), 512);
+ }
+ }
}
+ // Paper end - notify observers even if grow failed
+
@Override
public CrashReportCategory fillReportDetails(CrashReport report) {
CrashReportCategory crashreportsystemdetails = super.fillReportDetails(report);
@@ -1828,6 +2266,7 @@
@@ -1828,6 +2267,7 @@
}
public void onTickingStart(Entity entity) {
@@ -1090,7 +1092,7 @@
ServerLevel.this.entityTickList.add(entity);
}
@@ -1836,14 +2275,15 @@
@@ -1836,14 +2276,15 @@
}
public void onTrackingStart(Entity entity) {
@@ -1108,7 +1110,7 @@
String s = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration"));
@@ -1864,9 +2304,58 @@
@@ -1864,9 +2305,58 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
@@ -1167,7 +1169,7 @@
ServerLevel.this.getChunkSource().removeEntity(entity);
if (entity instanceof ServerPlayer entityplayer) {
ServerLevel.this.players.remove(entityplayer);
@@ -1874,7 +2363,7 @@
@@ -1874,7 +2364,7 @@
}
if (entity instanceof Mob entityinsentient) {
@@ -1176,7 +1178,7 @@
String s = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration"));
@@ -1895,10 +2384,27 @@
@@ -1895,10 +2385,27 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);