feat(vfx #C.1.5b): activator handles dat-hydrated entities + per-part transforms
Resolver returns ScriptActivationInfo(ScriptId, PartTransforms) — one dat lookup per spawn yields both pieces of info. The C.1.5a ServerGuid==0 guard is relaxed: activator now keys by ServerGuid when nonzero, else entity.Id, so dat-hydrated entities (EnvCell statics, exterior stabs) flow through the same code path as server-spawned ones. PartTransforms pushed into ParticleHookSink before scheduling Play, closing the activator side of #56. GameWindow resolver lambda upgraded: now constructs ScriptActivationInfo from setup.DefaultScript.DataId + SetupPartTransforms.Compute(setup), swallowing dat-lookup throws the same way C.1.5a did. Tests: 4 existing tests updated for new ScriptActivationInfo signature; 3 new tests cover entity.Id keying for dat-hydrated entities, end-to-end part-transform pipeline (resolver → sink → particle world position), and OnRemove with an arbitrary caller-picked key. 77 Vfx+Meshing+Activator tests green. GpuWorldState fire-site wiring (Task 4) lands next. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
11521f4418
commit
5ca5827abe
3 changed files with 216 additions and 53 deletions
|
|
@ -1614,26 +1614,32 @@ public sealed class GameWindow : IDisposable
|
|||
_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.
|
||||
uint ResolveDefaultScript(AcDream.Core.World.WorldEntity e)
|
||||
// Phase C.1.5a/b: construct EntityScriptActivator so static entities
|
||||
// (server-spawned AND dat-hydrated) fire Setup.DefaultScript through
|
||||
// the PhysicsScriptRunner on enter-world. C.1.5b adds per-part
|
||||
// transforms via SetupPartTransforms.Compute so multi-emitter scripts
|
||||
// distribute across mesh parts (closes #56). _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.
|
||||
AcDream.App.Rendering.Vfx.ScriptActivationInfo? ResolveActivation(AcDream.Core.World.WorldEntity e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var setup = capturedDats?.Get<DatReaderWriter.DBObjs.Setup>(e.SourceGfxObjOrSetupId);
|
||||
return setup?.DefaultScript.DataId ?? 0u;
|
||||
if (setup is null) return null;
|
||||
uint scriptId = setup.DefaultScript.DataId;
|
||||
if (scriptId == 0) return null;
|
||||
var parts = AcDream.Core.Meshing.SetupPartTransforms.Compute(setup);
|
||||
return new AcDream.App.Rendering.Vfx.ScriptActivationInfo(scriptId, parts);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0u;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
var entityScriptActivator = new AcDream.App.Rendering.Vfx.EntityScriptActivator(
|
||||
_scriptRunner!, _particleSink!, ResolveDefaultScript);
|
||||
_scriptRunner!, _particleSink!, ResolveActivation);
|
||||
_entityScriptActivator = entityScriptActivator;
|
||||
|
||||
// Phase Post-A.5 #53 (Task 12): wire EntityClassificationCache.InvalidateLandblock
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue