acdream/tests/AcDream.App.Tests/World/LiveEntityTestFixture.cs
Erik 420e5eea70 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.
2026-07-25 21:50:58 +02:00

87 lines
3.1 KiB
C#

using System.Numerics;
using AcDream.Core.Net;
using AcDream.Core.World;
using AcDream.Runtime.Entities;
namespace AcDream.App.World;
/// <summary>
/// Test-only construction seam for exact Runtime identities and App
/// projections. Component fixtures must not manufacture detached
/// <see cref="LiveEntityRecord"/> instances because that bypasses the same
/// local-ID/incarnation key used by production.
/// </summary>
internal static class LiveEntityTestFixture
{
public static LiveEntityRecord CreateExactProjectionRecord(
WorldSession.EntitySpawn spawn)
{
var directory = new RuntimeEntityDirectory();
RuntimeEntityRecord canonical = directory.AddActive(spawn);
directory.ClaimLocalId(canonical);
var projections = new LiveEntityProjectionStore(directory);
return projections.AddMaterializing(canonical);
}
public static LiveEntityRecord RegisterAndMaterializeProjection(
this LiveEntityRuntime runtime,
WorldSession.EntitySpawn spawn,
Func<uint, WorldEntity>? factory = null,
LiveEntityProjectionKind projectionKind = LiveEntityProjectionKind.World,
Action<LiveEntityRecord>? initializeProjection = null)
{
ArgumentNullException.ThrowIfNull(runtime);
LiveEntityRegistrationResult registration =
runtime.RegisterLiveEntity(spawn);
RuntimeEntityRecord canonical = registration.Canonical
?? throw new InvalidOperationException(
"The fixture cannot materialize a stale CreateObject.");
if (registration.Projection is { } existing)
return existing;
WorldEntity? entity = runtime.MaterializeLiveEntity(
canonical,
spawn.Position?.LandblockId ?? canonical.FullCellId,
factory ?? (id => CreateWorldEntity(id, spawn)),
projectionKind,
initializeProjection,
out LiveEntityRecord? record);
if (entity is null || record is null)
{
throw new InvalidOperationException(
"The fixture failed to materialize the exact Runtime incarnation.");
}
return record;
}
private static WorldEntity CreateWorldEntity(
uint localEntityId,
WorldSession.EntitySpawn spawn)
{
var position = spawn.Position;
return new WorldEntity
{
Id = localEntityId,
ServerGuid = spawn.Guid,
SourceGfxObjOrSetupId = spawn.SetupTableId ?? 0u,
Position = position is { } placed
? new Vector3(
placed.PositionX,
placed.PositionY,
placed.PositionZ)
: Vector3.Zero,
Rotation = position is { } oriented
? new Quaternion(
oriented.RotationX,
oriented.RotationY,
oriented.RotationZ,
oriented.RotationW)
: Quaternion.Identity,
MeshRefs = Array.Empty<MeshRef>(),
ParentCellId = position?.LandblockId,
EffectCellId = position?.LandblockId,
};
}
}