using AcDream.Core.Physics; using Xunit; namespace AcDream.Core.Tests.Physics; /// /// A6.P7 (2026-05-25) — retail-binary dispatch rule. Retail's /// CPhysicsObj::FindObjCollisions at /// docs/research/named-retail/acclient_2013_pseudo_c.txt:276861 /// dispatches BINARILY between "BSP-only" and "cyl + sphere" based on /// the HAS_PHYSICS_BSP_PS flag (bit 16, hex 0x10000) in /// PhysicsState. The flag is defined in /// docs/research/named-retail/acclient.h:2833 and mirrored in /// ACE at references/ACE/Source/ACE.Entity/Enum/PhysicsState.cs:24 /// as HasPhysicsBSP = 0x00010000. /// /// /// For non-PvP, non-missile movers (M1.5 scope — walking-vs-static), an /// entity with HAS_PHYSICS_BSP_PS in its state tests its BSP exclusively /// — the foot cyl is NEVER tested. The closed cottage door (state /// 0x10008 = STATIC | REPORT_COLLISIONS | HAS_PHYSICS_BSP) /// hits this branch. /// /// /// /// Pre-A6.P7: our dispatcher iterates every ShadowEntry /// independently and tests both the cyl AND the BSP for a door. The /// cyl's radial normal contaminates the slide direction at NE/SE /// approach headings (see /// docs/research/2026-05-25-a6-door-cyl-retail-dispatch-investigation.md). /// /// /// /// Post-A6.P7: the dispatcher consults /// on each cyl/sphere /// entry and skips it when the entity has BSP, matching retail. /// /// public class A6P7DispatchRulesTests { /// /// Retail bit constant HAS_PHYSICS_BSP_PS = 0x10000 /// (acclient.h:2833) and ACE's HasPhysicsBSP = 0x00010000 /// (PhysicsState.cs:24) must match the value we expose on /// . /// [Fact] public void PhysicsStateFlags_HasPhysicsBsp_Is_Bit_16() { Assert.Equal(0x00010000u, (uint)PhysicsStateFlags.HasPhysicsBsp); } /// /// The dispatch predicate maps directly from retail's branch at /// acclient_2013_pseudo_c.txt:276861: /// /// ((state & 0x10000) == 0 || ebp_1 != 0 || eax_12 != 0) /// → cyl + sphere path /// else /// → BSP-only path /// /// For M1.5 scope ebp_1 (PvP-target-player) and eax_12 /// (missile_ignore) are treated as false. The predicate reduces to: /// "BSP-only iff HAS_PHYSICS_BSP_PS is set". /// [Theory] [InlineData(0x00010008u, true)] // closed cottage door — STATIC | REPORT | HAS_BSP [InlineData(0x00010000u, true)] // bare HAS_BSP [InlineData(0x00110000u, true)] // HAS_BSP | CLOAKED [InlineData(0x00000008u, false)] // creature — REPORT_COLLISIONS only [InlineData(0x00000000u, false)] // empty state [InlineData(0x0000FFFFu, false)] // every bit BELOW 0x10000 set public void BspOnlyDispatch_RespectsHasPhysicsBspFlag( uint entityState, bool expected) { Assert.Equal(expected, Transition.BspOnlyDispatch(entityState)); } }