diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index b81d484..14463e8 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -33,6 +33,7 @@ public sealed class GameWindow : IDisposable /// after OnLoad completes (modern path is mandatory as of N.5). private AcDream.App.Rendering.Wb.WbMeshAdapter? _wbMeshAdapter; private AcDream.App.Rendering.Wb.EntitySpawnAdapter? _wbEntitySpawnAdapter; + private AcDream.App.Rendering.Vfx.EntityScriptActivator? _entityScriptActivator; private AcDream.App.Rendering.Wb.WbDrawDispatcher? _wbDrawDispatcher; /// Phase N.5: ARB_bindless_texture + ARB_shader_draw_parameters /// support. Required at startup — missing bindless throws @@ -1612,6 +1613,30 @@ public sealed class GameWindow : IDisposable var wbEntitySpawnAdapter = new AcDream.App.Rendering.Wb.EntitySpawnAdapter( _textureCache!, SequencerFactory, _wbMeshAdapter!); _wbEntitySpawnAdapter = wbEntitySpawnAdapter; + + // Phase C.1.5a: construct EntityScriptActivator so server-spawned static + // entities (portals first) fire Setup.DefaultScript through the + // PhysicsScriptRunner on enter-world. _scriptRunner and _particleSink + // are initialised earlier in OnLoad (line ~1083); both are non-null + // here. The resolver lambda captures _dats and swallows dat-lookup + // throws — see C.1.5a spec §6 (error handling) for rationale. + var capturedDatsForActivator = _dats; + uint ResolveDefaultScript(AcDream.Core.World.WorldEntity e) + { + try + { + var setup = capturedDatsForActivator?.Get(e.SourceGfxObjOrSetupId); + return setup?.DefaultScript.DataId ?? 0u; + } + catch + { + return 0u; + } + } + var entityScriptActivator = new AcDream.App.Rendering.Vfx.EntityScriptActivator( + _scriptRunner!, _particleSink!, ResolveDefaultScript); + _entityScriptActivator = entityScriptActivator; + // Phase Post-A.5 #53 (Task 12): wire EntityClassificationCache.InvalidateLandblock // so Tier 1 cache entries get swept on LB demote (Near to Far) and unload. // Per spec §5.3 W3b. The callback receives the canonical landblock id @@ -1619,7 +1644,8 @@ public sealed class GameWindow : IDisposable _worldState = new AcDream.App.Streaming.GpuWorldState( wbSpawnAdapter, wbEntitySpawnAdapter, - onLandblockUnloaded: _classificationCache.InvalidateLandblock); + onLandblockUnloaded: _classificationCache.InvalidateLandblock, + entityScriptActivator: entityScriptActivator); _wbDrawDispatcher = new AcDream.App.Rendering.Wb.WbDrawDispatcher( _gl, _meshShader!, _textureCache!, _wbMeshAdapter!, _wbEntitySpawnAdapter, _bindlessSupport!,