fix(streaming): preserve exact live projection identity
Carry RuntimeEntityKey through spatial residency, visibility transitions, rebucketing, quiescence, landblock retirement, and origin recentering. This prevents stale incarnation edges from mutating a replacement projection while retaining the static DAT-entity path. Validated by 104 focused ownership/streaming tests, the Release solution build, and 8,444 complete Release tests with five existing skips. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
420e5eea70
commit
e937cc36df
8 changed files with 338 additions and 120 deletions
|
|
@ -3,6 +3,7 @@ using AcDream.App.Audio;
|
|||
using AcDream.App.Streaming;
|
||||
using AcDream.Core.Selection;
|
||||
using AcDream.Core.World;
|
||||
using AcDream.Runtime.Entities;
|
||||
using DatReaderWriter.DBObjs;
|
||||
|
||||
namespace AcDream.App.Tests.Streaming;
|
||||
|
|
@ -23,10 +24,11 @@ public sealed class WorldGenerationQuiescenceTests
|
|||
new LandBlock(),
|
||||
Array.Empty<WorldEntity>()));
|
||||
world.PlaceLiveEntityProjection(LandblockId, entity);
|
||||
RuntimeEntityKey key = Key(entity);
|
||||
world.SetLandblockAabb(LandblockId, Vector3.Zero, Vector3.One);
|
||||
var nearby = new List<KeyValuePair<uint, WorldEntity>>();
|
||||
|
||||
Assert.True(world.IsLiveEntityVisible(entity.Id));
|
||||
Assert.True(world.IsLiveEntityVisible(key));
|
||||
Assert.Single(world.LandblockEntries);
|
||||
Assert.Single(world.LandblockBounds);
|
||||
|
||||
|
|
@ -34,7 +36,7 @@ public sealed class WorldGenerationQuiescenceTests
|
|||
world.CopyLiveEntitiesNearLandblock(LandblockId, 0, nearby);
|
||||
|
||||
Assert.False(availability.IsWorldAvailable);
|
||||
Assert.False(world.IsLiveEntityVisible(entity.Id));
|
||||
Assert.False(world.IsLiveEntityVisible(key));
|
||||
Assert.Empty(world.LandblockEntries);
|
||||
Assert.Empty(world.LandblockBounds);
|
||||
Assert.Empty(nearby);
|
||||
|
|
@ -44,7 +46,7 @@ public sealed class WorldGenerationQuiescenceTests
|
|||
Assert.False(availability.End(16));
|
||||
Assert.False(availability.IsWorldAvailable);
|
||||
Assert.True(availability.End(17));
|
||||
Assert.True(world.IsLiveEntityVisible(entity.Id));
|
||||
Assert.True(world.IsLiveEntityVisible(key));
|
||||
Assert.Same(entity, Assert.Single(world.LandblockEntries).Entities.Single());
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +68,7 @@ public sealed class WorldGenerationQuiescenceTests
|
|||
availability,
|
||||
selection,
|
||||
world,
|
||||
guid => guid == ServerGuid ? entity.Id : null,
|
||||
guid => guid == ServerGuid ? Key(entity) : null,
|
||||
audio);
|
||||
|
||||
quiescence.Begin(1);
|
||||
|
|
@ -115,6 +117,9 @@ public sealed class WorldGenerationQuiescenceTests
|
|||
MeshRefs = Array.Empty<MeshRef>(),
|
||||
};
|
||||
|
||||
private static RuntimeEntityKey Key(WorldEntity entity) =>
|
||||
new(entity.Id, 0);
|
||||
|
||||
private sealed class RecordingAudioQuiescence : IWorldAudioQuiescence
|
||||
{
|
||||
public int SuspendCalls { get; private set; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue