refactor(app): key live projections by runtime identity
Move materialized live-object sidecars and presentation worksets to exact RuntimeEntityKey ownership. Runtime remains the only GUID/incarnation/local-ID authority while hydration, animation, effects, lights, equipped children, renderer resources, visibility, liveness, and teardown resolve exact projection identities. Preserve synchronous callbacks, local-ID allocation order, and current rendering behavior.
This commit is contained in:
parent
e18df84437
commit
420e5eea70
73 changed files with 2939 additions and 1715 deletions
|
|
@ -7,6 +7,7 @@ using AcDream.Core.Net;
|
|||
using AcDream.Core.Net.Messages;
|
||||
using AcDream.Core.Physics;
|
||||
using AcDream.Core.World;
|
||||
using AcDream.Runtime.Entities;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using DatReaderWriter.Types;
|
||||
|
||||
|
|
@ -64,9 +65,9 @@ public sealed class LiveEntityAnimationPresenterTests
|
|||
old.Live.SetAnimationRuntime(Guid, replacement);
|
||||
var presenter = Presenter(old.Live, new EntityEffectPoseRegistry(), new Context());
|
||||
|
||||
presenter.Present(new Dictionary<uint, LiveEntityAnimationSchedule>
|
||||
presenter.Present(new Dictionary<RuntimeEntityKey, LiveEntityAnimationSchedule>
|
||||
{
|
||||
[old.Entity.Id] = stale,
|
||||
[old.Record.ProjectionKey!.Value] = stale,
|
||||
});
|
||||
|
||||
Assert.Empty(replacement.MeshRefsScratch);
|
||||
|
|
@ -178,9 +179,9 @@ public sealed class LiveEntityAnimationPresenterTests
|
|||
[true]);
|
||||
var presenter = Presenter(fixture.Live, new EntityEffectPoseRegistry(), new Context());
|
||||
|
||||
presenter.Present(new Dictionary<uint, LiveEntityAnimationSchedule>
|
||||
presenter.Present(new Dictionary<RuntimeEntityKey, LiveEntityAnimationSchedule>
|
||||
{
|
||||
[fixture.Entity.Id] = stale,
|
||||
[fixture.Record.ProjectionKey!.Value] = stale,
|
||||
});
|
||||
|
||||
Assert.Empty(fixture.State.MeshRefsScratch);
|
||||
|
|
@ -252,11 +253,11 @@ public sealed class LiveEntityAnimationPresenterTests
|
|||
Assert.Equal(2, nested.Count);
|
||||
};
|
||||
var presenter = Presenter(first.Live, poses, new Context());
|
||||
var schedules = new Dictionary<uint, LiveEntityAnimationSchedule>
|
||||
var schedules = new Dictionary<RuntimeEntityKey, LiveEntityAnimationSchedule>
|
||||
{
|
||||
[first.Entity.Id] = Schedule(first,
|
||||
[first.Record.ProjectionKey!.Value] = Schedule(first,
|
||||
[new PartTransform(Vector3.UnitX, Quaternion.Identity)]),
|
||||
[second.Entity.Id] = Schedule(second,
|
||||
[second.Record.ProjectionKey!.Value] = Schedule(second,
|
||||
[new PartTransform(Vector3.UnitY, Quaternion.Identity)]),
|
||||
};
|
||||
|
||||
|
|
@ -283,11 +284,11 @@ public sealed class LiveEntityAnimationPresenterTests
|
|||
first.Live.SetAnimationRuntime(Guid + 1, replacement);
|
||||
};
|
||||
var presenter = Presenter(first.Live, poses, new Context());
|
||||
var schedules = new Dictionary<uint, LiveEntityAnimationSchedule>
|
||||
var schedules = new Dictionary<RuntimeEntityKey, LiveEntityAnimationSchedule>
|
||||
{
|
||||
[first.Entity.Id] = Schedule(first,
|
||||
[first.Record.ProjectionKey!.Value] = Schedule(first,
|
||||
[new PartTransform(Vector3.UnitX, Quaternion.Identity)]),
|
||||
[second.Entity.Id] = Schedule(second,
|
||||
[second.Record.ProjectionKey!.Value] = Schedule(second,
|
||||
[new PartTransform(new Vector3(99f, 0f, 0f), Quaternion.Identity)]),
|
||||
};
|
||||
|
||||
|
|
@ -305,11 +306,11 @@ public sealed class LiveEntityAnimationPresenterTests
|
|||
var second = Add(first.Live, Guid + 1, partCount: 1);
|
||||
var poses = new EntityEffectPoseRegistry();
|
||||
var presenter = Presenter(first.Live, poses, new Context());
|
||||
var schedules = new Dictionary<uint, LiveEntityAnimationSchedule>
|
||||
var schedules = new Dictionary<RuntimeEntityKey, LiveEntityAnimationSchedule>
|
||||
{
|
||||
[first.Entity.Id] = Schedule(first,
|
||||
[first.Record.ProjectionKey!.Value] = Schedule(first,
|
||||
[new PartTransform(Vector3.UnitX, Quaternion.Identity)]),
|
||||
[second.Entity.Id] = Schedule(second,
|
||||
[second.Record.ProjectionKey!.Value] = Schedule(second,
|
||||
[new PartTransform(Vector3.UnitY, Quaternion.Identity)]),
|
||||
};
|
||||
bool recursed = false;
|
||||
|
|
@ -359,9 +360,9 @@ public sealed class LiveEntityAnimationPresenterTests
|
|||
fixture.Record.ObjectClockEpoch,
|
||||
fixture.Record.ProjectionMutationVersion,
|
||||
fixture.State.PresentationRevision);
|
||||
var schedules = new Dictionary<uint, LiveEntityAnimationSchedule>
|
||||
var schedules = new Dictionary<RuntimeEntityKey, LiveEntityAnimationSchedule>
|
||||
{
|
||||
[fixture.Entity.Id] = schedule,
|
||||
[fixture.Record.ProjectionKey!.Value] = schedule,
|
||||
};
|
||||
var poses = new EntityEffectPoseRegistry();
|
||||
var presenter = Presenter(fixture.Live, poses, new Context());
|
||||
|
|
@ -407,12 +408,12 @@ public sealed class LiveEntityAnimationPresenterTests
|
|||
}
|
||||
}
|
||||
|
||||
private static IReadOnlyDictionary<uint, LiveEntityAnimationSchedule> Schedules(
|
||||
private static IReadOnlyDictionary<RuntimeEntityKey, LiveEntityAnimationSchedule> Schedules(
|
||||
Fixture fixture,
|
||||
IReadOnlyList<PartTransform> frames) =>
|
||||
new Dictionary<uint, LiveEntityAnimationSchedule>
|
||||
new Dictionary<RuntimeEntityKey, LiveEntityAnimationSchedule>
|
||||
{
|
||||
[fixture.Entity.Id] = Schedule(fixture, frames),
|
||||
[fixture.Record.ProjectionKey!.Value] = Schedule(fixture, frames),
|
||||
};
|
||||
|
||||
private static LiveEntityAnimationSchedule Schedule(
|
||||
|
|
@ -452,10 +453,8 @@ public sealed class LiveEntityAnimationPresenterTests
|
|||
float scale = 1f,
|
||||
bool withSequencer = true)
|
||||
{
|
||||
LiveEntityRecord record = live.RegisterLiveEntity(Spawn(guid)).Record!;
|
||||
WorldEntity entity = live.MaterializeLiveEntity(
|
||||
guid,
|
||||
Cell,
|
||||
LiveEntityRecord record = live.RegisterAndMaterializeProjection(
|
||||
Spawn(guid),
|
||||
id => new WorldEntity
|
||||
{
|
||||
Id = id,
|
||||
|
|
@ -465,7 +464,8 @@ public sealed class LiveEntityAnimationPresenterTests
|
|||
Rotation = Quaternion.Identity,
|
||||
MeshRefs = Array.Empty<MeshRef>(),
|
||||
ParentCellId = Cell,
|
||||
})!;
|
||||
});
|
||||
WorldEntity entity = Assert.IsType<WorldEntity>(record.WorldEntity);
|
||||
LiveEntityAnimationState state = State(entity, partCount, scale, withSequencer);
|
||||
entity.SetIndexedPartPoses(
|
||||
Enumerable.Repeat(Matrix4x4.Identity, partCount).ToArray(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue