using System.Reflection; using AcDream.App.Net; using AcDream.App.Physics; using AcDream.App.Tests.Architecture; using AcDream.Core.Physics; using AcDream.Runtime.Gameplay; namespace AcDream.App.Tests.Physics; public sealed class Issue270ProductionWiringTests { [Fact] public void MovementStats_UseOneEdgeTrackerAndResetItWithTheSession() { // C3c-F1 (2026-08-02): the #270 invariant is unchanged — exactly one // stamina-exhaustion edge tracker, exhaustion dispatched once on the // edge, tracker reset with the session — but the wiring moved from // the factory's deleted ApplyMovementStats body into // LiveMovementStatsApplier, which routes through the Runtime // movement owner's typed seam instead of touching the controller. _ = Assert.Single( typeof(LiveMovementStatsApplier).GetFields( BindingFlags.Instance | BindingFlags.NonPublic), field => field.FieldType == typeof(StaminaExhaustionEdgeTracker)); IReadOnlyList applierCalls = CompiledCallGraph.ReadDeclared(typeof(LiveMovementStatsApplier)); Assert.Single( applierCalls, call => call.Target.DeclaringType == typeof(StaminaExhaustionEdgeTracker) && call.Target.Name == nameof(StaminaExhaustionEdgeTracker.Observe)); Assert.Single( applierCalls, call => call.Target.DeclaringType == typeof(RuntimeLocalPlayerMovementState) && call.Target.Name == nameof( RuntimeLocalPlayerMovementState.ReportExhaustion)); Assert.Single( applierCalls, call => call.Target.DeclaringType == typeof(StaminaExhaustionEdgeTracker) && call.Target.Name == nameof(StaminaExhaustionEdgeTracker.Reset)); IReadOnlyList factoryCalls = CompiledCallGraph.ReadDeclared(typeof(LiveSessionRuntimeFactory)); Assert.Single( factoryCalls, call => call.Target.DeclaringType == typeof(LiveMovementStatsApplier) && call.Target.Name == nameof(LiveMovementStatsApplier.Reset)); // The factory keeps zero direct controller mutations: both stat // callbacks route through the applier's seam. Assert.Equal( 2, factoryCalls.Count(call => call.Target.DeclaringType == typeof(LiveMovementStatsApplier) && call.Target.Name == nameof(LiveMovementStatsApplier.Apply))); Assert.DoesNotContain( factoryCalls, call => call.Target.DeclaringType == typeof(MotionInterpreter) && call.Target.Name == nameof(MotionInterpreter.ReportExhaustion)); } [Fact] public void RemoteSpawnSettle_IsRetriedAndCoversBothCreationRoutes() { const BindingFlags flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly; MethodInfo[] callers = typeof(LiveEntityNetworkUpdateController) .GetMethods(flags) .Where(method => method.GetMethodBody() is not null) .Where(method => CompiledCallGraph.Read(method).Any(call => call.Target.DeclaringType == typeof(LiveEntityNetworkUpdateController) && call.Target.Name == "SeedRemoteSpawnPlacement")) .ToArray(); Assert.Equal(2, callers.Length); Assert.Equal( ["DispatchRemoteInboundMotion", "OnPosition"], callers.Select(method => method.Name).Order().ToArray()); MethodInfo retryingInboundRoute = Assert.Single( callers, method => method.Name == "DispatchRemoteInboundMotion"); IReadOnlyList retryCalls = CompiledCallGraph.Read(retryingInboundRoute); int contact = CompiledCallGraph.IndexOf( retryCalls, typeof(PhysicsBody), "get_InContact"); int settle = CompiledCallGraph.IndexOf( retryCalls, typeof(LiveEntityNetworkUpdateController), "SeedRemoteSpawnPlacement"); Assert.True(contact >= 0 && settle > contact); // C3c-F5: the settle helper moved to Core (SpawnPlacementSettler) so // the local player's Runtime first-entry activation shares the same // tested compressed-first-gravity-frame sweep. MethodInfo seed = typeof(LiveEntityNetworkUpdateController).GetMethod( "SeedRemoteSpawnPlacement", flags) ?? throw new MissingMethodException( typeof(LiveEntityNetworkUpdateController).FullName, "SeedRemoteSpawnPlacement"); Assert.Contains( CompiledCallGraph.Read(seed), call => call.Target.DeclaringType == typeof(SpawnPlacementSettler) && call.Target.Name == nameof(SpawnPlacementSettler.TrySettle)); } }