From aba882cec694236a11ff8e9fd9148519839ac942 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 22 Jun 2026 13:05:38 +0200 Subject: [PATCH] feat(teleport B): PhysicsEngine.IsLandblockTerrainResident worldReady query MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a high-16-bit-prefix landblock residency check used as the teleport worldReady gate — true once the destination landblock's terrain+cells have been registered via AddLandblock, regardless of whether the caller passes a canonical (0xFFFF), cell-resolved, or bare landblock id. Two TDD tests confirm: false before registration, true after, and that a cell-resolved id on the same landblock returns true. Co-Authored-By: Claude Sonnet 4.6 --- src/AcDream.Core/Physics/PhysicsEngine.cs | 14 ++++++++ .../Physics/PhysicsEngineResidencyTests.cs | 34 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/AcDream.Core.Tests/Physics/PhysicsEngineResidencyTests.cs diff --git a/src/AcDream.Core/Physics/PhysicsEngine.cs b/src/AcDream.Core/Physics/PhysicsEngine.cs index 108b9234..292eeec4 100644 --- a/src/AcDream.Core/Physics/PhysicsEngine.cs +++ b/src/AcDream.Core/Physics/PhysicsEngine.cs @@ -31,6 +31,20 @@ public sealed class PhysicsEngine /// Number of registered landblocks (diagnostic). public int LandblockCount => _landblocks.Count; + /// + /// True once the landblock covering has had its + /// terrain + cells registered via . Accepts a canonical + /// (0xFFFF) id, a cell-resolved id, or a bare landblock id — compares on the high 16 + /// bits. This is the teleport "worldReady" gate (the destination is grounded). + /// + public bool IsLandblockTerrainResident(uint cellOrLandblockId) + { + uint prefix = cellOrLandblockId & 0xFFFF0000u; + foreach (var key in _landblocks.Keys) + if ((key & 0xFFFF0000u) == prefix) return true; + return false; + } + /// /// Cell-based spatial index for static object collision. /// Populated during landblock streaming; queried by the Transition system. diff --git a/tests/AcDream.Core.Tests/Physics/PhysicsEngineResidencyTests.cs b/tests/AcDream.Core.Tests/Physics/PhysicsEngineResidencyTests.cs new file mode 100644 index 00000000..3cb17aad --- /dev/null +++ b/tests/AcDream.Core.Tests/Physics/PhysicsEngineResidencyTests.cs @@ -0,0 +1,34 @@ +using System; +using System.Numerics; +using AcDream.Core.Physics; +using Xunit; + +namespace AcDream.Core.Tests.Physics; + +public class PhysicsEngineResidencyTests +{ + [Fact] + public void IsLandblockTerrainResident_trueOnlyAfterAddLandblock() + { + var eng = new PhysicsEngine(); + uint canonical = 0xA9B4FFFFu; // canonical (streaming) form + uint lbId = canonical & 0xFFFF0000u; // AddLandblock id + + Assert.False(eng.IsLandblockTerrainResident(canonical)); + + eng.AddLandblock(lbId, terrain: null!, cells: Array.Empty(), + portals: Array.Empty(), worldOffsetX: 0f, worldOffsetY: 0f); + + Assert.True(eng.IsLandblockTerrainResident(canonical)); + } + + [Fact] + public void IsLandblockTerrainResident_matchesOnHigh16_acceptsCellResolvedId() + { + var eng = new PhysicsEngine(); + eng.AddLandblock(0xA9B40000u, null!, Array.Empty(), + Array.Empty(), 0f, 0f); + Assert.True(eng.IsLandblockTerrainResident(0xA9B40019u)); // cell-resolved id, same LB + Assert.False(eng.IsLandblockTerrainResident(0xC6A90019u)); // different LB + } +}