Stabilize mapped SoA layout across row changes
This commit is contained in:
parent
7abfaba31a
commit
8c51676722
3 changed files with 32 additions and 2 deletions
|
|
@ -4380,13 +4380,19 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
|
||||
using var soaCache = new CultCache();
|
||||
using var soaPublisher = new AetheriaRuntimeDaemonSoaFramePublisher(soaCache, producerEpoch: 1);
|
||||
var soaFrame = soaPublisher.BuildCurrentZoneEntities(
|
||||
using var soaFrame = soaPublisher.BuildCurrentZoneEntities(
|
||||
new AetheriaRuntimeDaemonFrameDocument { FrameId = 2, Run = run });
|
||||
var mineIdentity = soaFrame.View.Identities.Single(identity =>
|
||||
identity.EntityId == $"{run.RunId}:zone:0:physical-payload:{mine.PayloadId}");
|
||||
Require(mineIdentity.Kind == "physical-payload" && mineIdentity.AssetRef == "prefab.entity.mine" &&
|
||||
!mineIdentity.Selectable && mineIdentity.EntityIndex < -1,
|
||||
"the playable SoA must carry the retained Ymir mine through its provider-owned asset identity");
|
||||
var activeBodyExtent = soaFrame.View.Buffers[0].ByteLength;
|
||||
var activeColumns = soaFrame.View.Columns.ToDictionary(
|
||||
column => column.ColumnId,
|
||||
column => (column.ByteOffset, column.ElementStride),
|
||||
StringComparer.Ordinal);
|
||||
soaFrame.Dispose();
|
||||
|
||||
var objects = AetheriaRuntimeGameDocuments.ObjectsViewport(
|
||||
new AetheriaRuntimeDaemonFrameDocument { FrameId = 2, Run = run },
|
||||
|
|
@ -4411,6 +4417,18 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
"Aetheria must apply authored blast damage after the delay");
|
||||
Require(run.GameEvents.Count(value => value.Kind == "deployable.detonated") == 1,
|
||||
"daemon must publish one authoritative detonation event");
|
||||
|
||||
using var settledSoaFrame = soaPublisher.BuildCurrentZoneEntities(
|
||||
new AetheriaRuntimeDaemonFrameDocument { FrameId = 3, Run = run });
|
||||
Require(activeBodyExtent == settledSoaFrame.View.Buffers[0].ByteLength,
|
||||
"one SoA layout version must retain a fixed body extent when active entity count changes");
|
||||
foreach (var column in settledSoaFrame.View.Columns)
|
||||
{
|
||||
var activeColumn = activeColumns[column.ColumnId];
|
||||
Require(activeColumn.ByteOffset == column.ByteOffset &&
|
||||
activeColumn.ElementStride == column.ElementStride,
|
||||
$"SoA column '{column.ColumnId}' must retain its byte interpretation across active row changes");
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeployableRangeExpiryDetonatesAfterYmirMovement()
|
||||
|
|
|
|||
|
|
@ -179,7 +179,10 @@ namespace GameCult.Aetheria.State.Verse
|
|||
if (count > Capacity)
|
||||
throw new InvalidOperationException($"Aetheria entity SoA capacity {Capacity} was exceeded by {count} rows.");
|
||||
var generation = Math.Max(frame.FrameId, 0);
|
||||
var layout = EntityHotSlabLayout.Create(count);
|
||||
// LayoutVersion owns byte interpretation. Keep offsets and body extent fixed for the
|
||||
// publisher capacity so a mapped frame may advance before reactive row metadata
|
||||
// without causing the same layout version to reinterpret its bytes.
|
||||
var layout = EntityHotSlabLayout.Create(Capacity);
|
||||
if (!_localPublisher.TryAcquireWrite(out var write))
|
||||
throw new InvalidOperationException("CultMesh has no unleased frame slot for the Aetheria SoA generation.");
|
||||
try
|
||||
|
|
|
|||
|
|
@ -174,6 +174,15 @@ radius/mass/inverse mass, render scale, visibility, LOD, and render group. This
|
|||
is the right direction for a thin Unity client: daemon state appears as a native
|
||||
view instead of a serialized object graph.
|
||||
|
||||
The publisher's `LayoutVersion` owns byte interpretation. Column offsets,
|
||||
strides, and the mapped body extent are therefore derived from the fixed SoA
|
||||
capacity, not the current active row count. Active element counts, identities,
|
||||
and render groups remain reactive metadata. A mapped generation may advance
|
||||
before that metadata notification without changing what any existing offset
|
||||
means: removed rows are cleared, and newly added rows remain outside the old
|
||||
element count until the matching metadata arrives. Neither EveUnity nor the
|
||||
transport may repair or reinterpret a mismatched generation.
|
||||
|
||||
Current limitation: physics body radius, mass, inverse mass, render scale, LOD,
|
||||
and render group are still generic defaults in the publisher. Entity identity
|
||||
and position are real; body semantics are not yet rich enough to replace all
|
||||
|
|
|
|||
Loading…
Reference in a new issue