diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 741b2a9..a5e5a69 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -7543,7 +7543,11 @@ public sealed class GameWindow : IDisposable // we always want it animated in player mode. if (!_animatedEntities.TryGetValue(pe.Id, out var ae)) { - var setup = _dats.Get(pe.SourceGfxObjOrSetupId); + // A.5 T10: lock around _dats.Get — worker thread may be + // building a landblock mesh concurrently. DatBinReader's + // shared buffer position would corrupt without serialization. + DatReaderWriter.DBObjs.Setup? setup; + lock (_datLock) { setup = _dats.Get(pe.SourceGfxObjOrSetupId); } if (setup is null) return; _physicsDataCache.CacheSetup(pe.SourceGfxObjOrSetupId, setup); @@ -8564,7 +8568,10 @@ public sealed class GameWindow : IDisposable // 0.4 m fallbacks. if (_dats is not null && (playerEntity.SourceGfxObjOrSetupId & 0xFF000000u) == 0x02000000u) { - var playerSetup = _dats.Get(playerEntity.SourceGfxObjOrSetupId); + // A.5 T10: lock around _dats.Get — worker thread may be + // building a landblock mesh concurrently. + DatReaderWriter.DBObjs.Setup? playerSetup; + lock (_datLock) { playerSetup = _dats.Get(playerEntity.SourceGfxObjOrSetupId); } if (playerSetup is not null) _physicsDataCache.CacheSetup(playerEntity.SourceGfxObjOrSetupId, playerSetup); _playerController.StepUpHeight = (playerSetup is not null && playerSetup.StepUpHeight > 0f)