using System.Numerics;
using AcDream.Core.Net;
using AcDream.Core.World;
using AcDream.Runtime.Entities;
namespace AcDream.App.World;
///
/// Test-only construction seam for exact Runtime identities and App
/// projections. Component fixtures must not manufacture detached
/// instances because that bypasses the same
/// local-ID/incarnation key used by production.
///
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? factory = null,
LiveEntityProjectionKind projectionKind = LiveEntityProjectionKind.World,
Action? 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(),
ParentCellId = position?.LandblockId,
EffectCellId = position?.LandblockId,
};
}
}