refactor(world): extract live projection mechanics
Move appearance rebinding, collision construction, default-pose resolution, local shadow ownership, and exact leave-world presentation into focused owners. Preserve retail parent ordering with staged validation, committed recovery, recursive attached-subtree withdrawal, and retryable exact teardown across parent, pickup, position, unwield, and pose-loss edges. Co-Authored-By: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
c87bac31a0
commit
69a2ca0c6d
26 changed files with 4172 additions and 430 deletions
|
|
@ -160,6 +160,110 @@ public class ShadowObjectRegistryTests
|
|||
Assert.Equal(0x44u, restored.State);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceMultiPartPayload_VisibleOwnerKeepsExistingCellMembership()
|
||||
{
|
||||
const uint entityId = 25u;
|
||||
var reg = new ShadowObjectRegistry();
|
||||
Vector3 position = new(12f, 12f, 50f);
|
||||
reg.RegisterMultiPart(
|
||||
entityId,
|
||||
position,
|
||||
Quaternion.Identity,
|
||||
[BspShape(0x01000011u, radius: 0.5f)],
|
||||
state: 0u,
|
||||
flags: EntityCollisionFlags.None,
|
||||
OffX,
|
||||
OffY,
|
||||
LbId,
|
||||
seedCellId: LbId | 1u,
|
||||
isStatic: false);
|
||||
|
||||
reg.ReplaceMultiPartPayload(
|
||||
entityId,
|
||||
position,
|
||||
Quaternion.Identity,
|
||||
[BspShape(0x01000012u, radius: 40f)],
|
||||
state: 0u,
|
||||
flags: EntityCollisionFlags.None,
|
||||
OffX,
|
||||
OffY,
|
||||
landblockId: 0u,
|
||||
seedCellId: 0u,
|
||||
isStatic: false);
|
||||
|
||||
ShadowEntry replaced = Assert.Single(reg.GetObjectsInCell(LbId | 1u));
|
||||
Assert.Equal(0x01000012u, replaced.GfxObjId);
|
||||
Assert.Empty(reg.GetObjectsInCell(LbId | 9u));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceMultiPartPayload_SuspendedShapedEmptyShaped_RemainsSuspended()
|
||||
{
|
||||
const uint entityId = 26u;
|
||||
var reg = new ShadowObjectRegistry();
|
||||
Vector3 position = new(12f, 12f, 50f);
|
||||
reg.RegisterMultiPart(
|
||||
entityId,
|
||||
position,
|
||||
Quaternion.Identity,
|
||||
[BspShape(0x01000021u, radius: 0.5f)],
|
||||
state: 0u,
|
||||
flags: EntityCollisionFlags.None,
|
||||
OffX,
|
||||
OffY,
|
||||
LbId,
|
||||
seedCellId: LbId | 1u,
|
||||
isStatic: false);
|
||||
Assert.True(reg.Suspend(entityId));
|
||||
|
||||
reg.ReplaceMultiPartPayload(
|
||||
entityId, position, Quaternion.Identity, [], 0u,
|
||||
EntityCollisionFlags.None, OffX, OffY, LbId, LbId | 1u);
|
||||
reg.ReplaceMultiPartPayload(
|
||||
entityId,
|
||||
position,
|
||||
Quaternion.Identity,
|
||||
[BspShape(0x01000022u, radius: 0.5f)],
|
||||
0u,
|
||||
EntityCollisionFlags.None,
|
||||
OffX,
|
||||
OffY,
|
||||
LbId,
|
||||
LbId | 1u);
|
||||
|
||||
Assert.Equal(1, reg.RetainedRegistrationCount);
|
||||
Assert.Equal(1, reg.SuspendedRegistrationCount);
|
||||
Assert.Empty(reg.GetObjectsInCell(LbId | 1u));
|
||||
reg.UpdatePosition(
|
||||
entityId, position, Quaternion.Identity, OffX, OffY, LbId, LbId | 1u);
|
||||
Assert.Equal(0x01000022u, Assert.Single(reg.GetObjectsInCell(LbId | 1u)).GfxObjId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReplaceMultiPartPayload_NewCelllessOwnerRegistersRetainedButSuspended()
|
||||
{
|
||||
const uint entityId = 27u;
|
||||
var reg = new ShadowObjectRegistry();
|
||||
reg.ReplaceMultiPartPayload(
|
||||
entityId,
|
||||
new Vector3(12f, 12f, 50f),
|
||||
Quaternion.Identity,
|
||||
[BspShape(0x01000031u, radius: 0.5f)],
|
||||
0u,
|
||||
EntityCollisionFlags.None,
|
||||
OffX,
|
||||
OffY,
|
||||
LbId,
|
||||
seedCellId: LbId | 1u,
|
||||
isStatic: false,
|
||||
suspendIfNew: true);
|
||||
|
||||
Assert.Equal(1, reg.RetainedRegistrationCount);
|
||||
Assert.Equal(1, reg.SuspendedRegistrationCount);
|
||||
Assert.Empty(reg.GetObjectsInCell(LbId | 1u));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// RemoveLandblock
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
@ -652,6 +756,15 @@ public class ShadowObjectRegistryTests
|
|||
};
|
||||
}
|
||||
|
||||
private static ShadowShape BspShape(uint gfxObjId, float radius) => new(
|
||||
gfxObjId,
|
||||
Vector3.Zero,
|
||||
Quaternion.Identity,
|
||||
Scale: 1f,
|
||||
CollisionType: ShadowCollisionType.BSP,
|
||||
Radius: radius,
|
||||
CylHeight: 0f);
|
||||
|
||||
private static CellPhysics BuildShadowCellSetTests_MakeLeafCell(Matrix4x4 worldTransform)
|
||||
{
|
||||
Matrix4x4.Invert(worldTransform, out var inv);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue