diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 902ca5b..fee413b 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -65,7 +65,7 @@ public sealed class GameWindow : IDisposable // Phase A.1: streaming fields replacing the one-shot _entities list. private AcDream.App.Streaming.LandblockStreamer? _streamer; - private readonly AcDream.App.Streaming.GpuWorldState _worldState = new(); + private AcDream.App.Streaming.GpuWorldState _worldState = new(); private AcDream.App.Streaming.StreamingController? _streamingController; private int _streamingRadius = 2; // default 5×5 private uint? _lastLivePlayerLandblockId; @@ -1438,6 +1438,17 @@ public sealed class GameWindow : IDisposable Console.WriteLine("[N.4] WbFoundation flag is ENABLED — routing static content through ObjectMeshManager."); } + // Phase N.4 Task 12: construct LandblockSpawnAdapter under the feature flag + // and rebuild _worldState so it threads the adapter in. _worldState starts + // as an unadorned GpuWorldState (field initializer); here we replace it with + // one that carries the adapter so AddLandblock/RemoveLandblock notify WB. + { + AcDream.App.Rendering.Wb.LandblockSpawnAdapter? wbSpawnAdapter = null; + if (AcDream.App.Rendering.Wb.WbFoundationFlag.IsEnabled && _wbMeshAdapter is not null) + wbSpawnAdapter = new AcDream.App.Rendering.Wb.LandblockSpawnAdapter(_wbMeshAdapter); + _worldState = new AcDream.App.Streaming.GpuWorldState(wbSpawnAdapter); + } + _staticMesh = new InstancedMeshRenderer(_gl, _meshShader, _textureCache, _wbMeshAdapter); // Phase G.1 sky renderer — its own shader (sky.vert / sky.frag) diff --git a/src/AcDream.App/Streaming/GpuWorldState.cs b/src/AcDream.App/Streaming/GpuWorldState.cs index f3448ef..bad81dd 100644 --- a/src/AcDream.App/Streaming/GpuWorldState.cs +++ b/src/AcDream.App/Streaming/GpuWorldState.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using AcDream.App.Rendering.Wb; using AcDream.Core.World; namespace AcDream.App.Streaming; @@ -38,6 +39,13 @@ namespace AcDream.App.Streaming; /// public sealed class GpuWorldState { + private readonly LandblockSpawnAdapter? _wbSpawnAdapter; + + public GpuWorldState(LandblockSpawnAdapter? wbSpawnAdapter = null) + { + _wbSpawnAdapter = wbSpawnAdapter; + } + private readonly Dictionary _loaded = new(); private readonly Dictionary _aabbs = new(); @@ -132,6 +140,8 @@ public sealed class GpuWorldState } _loaded[landblock.LandblockId] = landblock; + if (WbFoundationFlag.IsEnabled && _wbSpawnAdapter is not null) + _wbSpawnAdapter.OnLandblockLoaded(_loaded[landblock.LandblockId]); RebuildFlatView(); } @@ -181,6 +191,9 @@ public sealed class GpuWorldState public void RemoveLandblock(uint landblockId) { + if (WbFoundationFlag.IsEnabled && _wbSpawnAdapter is not null) + _wbSpawnAdapter.OnLandblockUnloaded(landblockId); + // Rescue persistent entities before removal. These get appended // to the _persistentRescued list; the caller is responsible for // re-injecting them (via AppendLiveEntity) into whatever landblock