feat(vfx #C.1.5b): GpuWorldState fires activator for dat-hydrated entities
Four new foreach blocks in GpuWorldState wire EntityScriptActivator into the dat-hydration spawn/despawn paths: - AddLandblock: fires OnCreate for each entity with ServerGuid==0 (live entities filtered out — they got OnCreate at AppendLiveEntity and would double-fire on pending-bucket merges). - AddEntitiesToExistingLandblock: fires OnCreate for each entity in the promoted batch (all dat-hydrated by construction). - RemoveLandblock: fires OnRemove(entity.Id) for each ServerGuid==0 entity before the loaded record is dropped. - RemoveEntitiesFromLandblock: fires OnRemove for the demote-tier entities about to be cleared (Near→Far demotion). 5 new integration tests cover the four fire-sites + the no-double-fire invariant on pending-bucket merges. Pattern matches existing GpuWorldStateTests (stub LandBlock heightmap + WorldEntity factory). Closes #56 end-to-end. Slice A (per-part transforms in Tasks 1-3) + Slice B (dat-hydrated entity DefaultScript firing, this task) both ready for visual verification at Holtburg portal + Inn fireplace + cottage chimney + spell cast. Note: 8 pre-existing failures in Physics/Input/MotionInterpreter test families are unrelated to this work (verified by re-running with this task's changes stashed). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5ca5827abe
commit
8735c39a40
2 changed files with 220 additions and 0 deletions
|
|
@ -180,6 +180,21 @@ public sealed class GpuWorldState
|
|||
_loaded[landblock.LandblockId] = landblock;
|
||||
if (_wbSpawnAdapter is not null)
|
||||
_wbSpawnAdapter.OnLandblockLoaded(_loaded[landblock.LandblockId]);
|
||||
|
||||
// C.1.5b: fire DefaultScript for dat-hydrated entities (ServerGuid==0).
|
||||
// Live entities (ServerGuid!=0) already had OnCreate fired at
|
||||
// AppendLiveEntity; the filter avoids double-firing pending-bucket merges.
|
||||
if (_entityScriptActivator is not null)
|
||||
{
|
||||
var loadedEntities = _loaded[landblock.LandblockId].Entities;
|
||||
for (int i = 0; i < loadedEntities.Count; i++)
|
||||
{
|
||||
var e = loadedEntities[i];
|
||||
if (e.ServerGuid == 0)
|
||||
_entityScriptActivator.OnCreate(e);
|
||||
}
|
||||
}
|
||||
|
||||
RebuildFlatView();
|
||||
}
|
||||
|
||||
|
|
@ -245,6 +260,19 @@ public sealed class GpuWorldState
|
|||
_persistentRescued.Add(entity);
|
||||
}
|
||||
}
|
||||
|
||||
// C.1.5b: stop DefaultScript for each dat-hydrated entity in
|
||||
// the landblock. Server-spawned entities are either being
|
||||
// rescued (script continues at the new LB) or were OnRemove'd
|
||||
// via RemoveEntityByServerGuid earlier; leave them alone here.
|
||||
if (_entityScriptActivator is not null)
|
||||
{
|
||||
foreach (var entity in lb.Entities)
|
||||
{
|
||||
if (entity.ServerGuid == 0)
|
||||
_entityScriptActivator.OnRemove(entity.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_pendingByLandblock.Remove(landblockId);
|
||||
|
|
@ -408,6 +436,18 @@ public sealed class GpuWorldState
|
|||
// canonicalized). Null when the cache isn't wired (tests). Per spec §5.3 W3b.
|
||||
_onLandblockUnloaded?.Invoke(canonical);
|
||||
|
||||
// C.1.5b: stop DefaultScript for each dat-hydrated entity about to
|
||||
// be dropped. Demote-tier entities are always atlas-tier (ServerGuid==0
|
||||
// per this method's class doc-comment); the filter is belt-and-suspenders.
|
||||
if (_entityScriptActivator is not null)
|
||||
{
|
||||
foreach (var entity in lb.Entities)
|
||||
{
|
||||
if (entity.ServerGuid == 0)
|
||||
_entityScriptActivator.OnRemove(entity.Id);
|
||||
}
|
||||
}
|
||||
|
||||
_loaded[canonical] = new LoadedLandblock(lb.LandblockId, lb.Heightmap, System.Array.Empty<WorldEntity>());
|
||||
_pendingByLandblock.Remove(canonical);
|
||||
RebuildFlatView();
|
||||
|
|
@ -447,6 +487,17 @@ public sealed class GpuWorldState
|
|||
_loaded[canonical] = new LoadedLandblock(lb.LandblockId, lb.Heightmap, merged);
|
||||
if (_wbSpawnAdapter is not null)
|
||||
_wbSpawnAdapter.OnLandblockLoaded(_loaded[canonical]);
|
||||
|
||||
// C.1.5b: fire DefaultScript for each promoted dat-hydrated entity.
|
||||
// All entities arriving via this path are atlas-tier by construction
|
||||
// (the promotion path streams in dat-static scenery + EnvCell statics
|
||||
// + stabs per the method's class doc-comment).
|
||||
if (_entityScriptActivator is not null)
|
||||
{
|
||||
for (int i = 0; i < entities.Count; i++)
|
||||
_entityScriptActivator.OnCreate(entities[i]);
|
||||
}
|
||||
|
||||
RebuildFlatView();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue