feat(physics #145): Slice 2a — PhysicsBody carries CellPosition; setter delta-syncs into the cell frame
Add CellPosition (retail Position type) alongside the world Vector3 Position. The Position setter mirrors each world delta into the cell-local origin and calls AdjustToOutside only when the local coord crosses a landblock boundary ([0,192) on X or Y), so the within-block cell id is preserved from the wire seed. SnapToCell seeds both positions from the wire's (cell, local) pair verbatim — no streaming center involved. Unseeded bodies (ObjCellId==0) and indoor cells are no-ops in the delta path. UpdatePhysicsInternal's existing `Position +=` desugars through the new setter automatically; no call sites changed. 4 new unit tests; full Core suite 1526 passed / 0 failed / 2 skipped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c980763322
commit
afe495b9e6
2 changed files with 118 additions and 2 deletions
51
tests/AcDream.Core.Tests/Physics/PhysicsBodyCellSyncTests.cs
Normal file
51
tests/AcDream.Core.Tests/Physics/PhysicsBodyCellSyncTests.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
using System.Numerics;
|
||||
using AcDream.Core.Physics;
|
||||
using Xunit;
|
||||
|
||||
namespace AcDream.Core.Tests.Physics;
|
||||
|
||||
public class PhysicsBodyCellSyncTests
|
||||
{
|
||||
[Fact]
|
||||
public void SnapToCell_SeedsCellPosition_AndWorldPosition()
|
||||
{
|
||||
var body = new PhysicsBody();
|
||||
body.SnapToCell(0xC95B0001u, worldPos: new Vector3(1000f, 2000f, 12f), cellLocal: new Vector3(14.8f, 0.3f, 12f));
|
||||
Assert.Equal(0xC95B0001u, body.CellPosition.ObjCellId);
|
||||
Assert.Equal(new Vector3(14.8f, 0.3f, 12f), body.CellPosition.Frame.Origin);
|
||||
Assert.Equal(new Vector3(1000f, 2000f, 12f), body.Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PositionDelta_MirrorsIntoCellPosition_WithinLandblock()
|
||||
{
|
||||
var body = new PhysicsBody();
|
||||
body.SnapToCell(0xC95B0001u, new Vector3(1000f, 2000f, 12f), new Vector3(100f, 50f, 12f));
|
||||
body.Position += new Vector3(5f, 3f, 0f); // move within the landblock
|
||||
Assert.Equal(new Vector3(105f, 53f, 12f), body.CellPosition.Frame.Origin);
|
||||
Assert.Equal(0xC95B0001u, body.CellPosition.ObjCellId); // no [0,192) crossing → same cell
|
||||
Assert.Equal(new Vector3(1005f, 2003f, 12f), body.Position); // world still authoritative + moved
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PositionDelta_AcrossSouthLandblockEdge_BumpsCellAndRewraps()
|
||||
{
|
||||
var body = new PhysicsBody();
|
||||
// local Y just above 0 in 0xC95B (lbY=0x5B); move south past 0 → south neighbour 0xC95A, local Y near 192.
|
||||
body.SnapToCell(0xC95B0001u, new Vector3(1000f, 2000f, 12f), new Vector3(100f, 0.3f, 12f));
|
||||
body.Position += new Vector3(0f, -1f, 0f);
|
||||
int lbY = (int)((body.CellPosition.ObjCellId >> 16) & 0xFFu);
|
||||
Assert.Equal(0x5A, lbY); // bumped to south neighbour
|
||||
Assert.InRange(body.CellPosition.Frame.Origin.Y, 190f, 192f); // re-wrapped near top of southern block
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PositionDelta_WithoutSeed_LeavesCellPositionDefault()
|
||||
{
|
||||
// A body that was never SnapToCell'd (e.g. a remote entity) must NOT get
|
||||
// a synthesized cell — CellPosition stays default, no AdjustToOutside.
|
||||
var body = new PhysicsBody();
|
||||
body.Position += new Vector3(10f, 10f, 0f);
|
||||
Assert.Equal(0u, body.CellPosition.ObjCellId);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue