Found during review of #53 (same class as the bug fixed there, not worsened by it).
SyncEngine.computeBroadcastDiffFromSnapshot / computePerPlayerDiffFromSnapshot (.cached baseline): when the cache is nil, the first call seeds it with whatever snapshot it was given and returns []. If that first call uses a .dirtyTracking(...) extraction (only some fields present) and happens before any player join has populated the cache via lateJoinSnapshot, the cache holds a partial snapshot and populateCacheIfNeeded does not repair it on the later join. Later diffs then treat the missing fields as new (.set) or as vanished.
Not reachable by EncodingBenchmark or the demo servers (players always join before the first sync), hence a follow-up rather than part of #53.
Fix sketch: seed a nil cache from an .all extraction (the regular path already does this at the runSyncNowCycle call site), or let populateCacheIfNeeded overwrite a partially seeded cache.
Found during review of #53 (same class as the bug fixed there, not worsened by it).
SyncEngine.computeBroadcastDiffFromSnapshot/computePerPlayerDiffFromSnapshot(.cachedbaseline): when the cache is nil, the first call seeds it with whatever snapshot it was given and returns[]. If that first call uses a.dirtyTracking(...)extraction (only some fields present) and happens before any player join has populated the cache vialateJoinSnapshot, the cache holds a partial snapshot andpopulateCacheIfNeededdoes not repair it on the later join. Later diffs then treat the missing fields as new (.set) or as vanished.Not reachable by EncodingBenchmark or the demo servers (players always join before the first sync), hence a follow-up rather than part of #53.
Fix sketch: seed a nil cache from an
.allextraction (the regular path already does this at therunSyncNowCyclecall site), or letpopulateCacheIfNeededoverwrite a partially seeded cache.