refactor(runtime): own local movement and outbound cadence

Move the canonical local movement controller, body/motion managers, object clock, movement wire data, and MTS/jump/AP sender into AcDream.Runtime. Replace process skill defaults with typed Runtime character options, make graphical and direct commands borrow one autorun owner, retain the construction-time PartArray seam, and include movement in terminal ownership convergence.

Preserve the accepted pre-inbound movement/jump and post-inbound autonomous-position order while moving the exact packet/cadence fixtures into Runtime tests. Add graphical/direct parity, two-instance isolation, teardown, allocation, architecture, and divergence-path coverage.

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Erik 2026-07-26 12:33:53 +02:00
parent 3456dff038
commit aa3f4a60f8
36 changed files with 878 additions and 276 deletions

View file

@ -9,7 +9,7 @@ public sealed class DispatcherMovementInputSourceTests
[Fact]
public void UnboundSourceCapturesNeutralInput()
{
var source = new DispatcherMovementInputSource();
var source = CreateSource();
Assert.Equal(default, source.Capture());
}
@ -18,7 +18,7 @@ public sealed class DispatcherMovementInputSourceTests
public void CapturesDispatcherHeldStateAndRetailWalkModifier()
{
var (dispatcher, _, _) = CreateDispatcher();
var source = new DispatcherMovementInputSource();
var source = CreateSource();
source.Bind(dispatcher);
Assert.True(dispatcher.TrySetAutomationActionHeld(
@ -38,7 +38,7 @@ public sealed class DispatcherMovementInputSourceTests
public void RetainedKeyboardCaptureSilencesHeldKeysButDoesNotCancelAutorun()
{
var (dispatcher, _, mouse) = CreateDispatcher();
var source = new DispatcherMovementInputSource();
var source = CreateSource();
source.Bind(dispatcher);
dispatcher.TrySetAutomationActionHeld(InputAction.MovementForward, held: true);
Assert.True(source.HandlePressedAction(InputAction.MovementRunLock));
@ -59,7 +59,7 @@ public sealed class DispatcherMovementInputSourceTests
{
var capture = new FakeCapture();
var (dispatcher, _, _) = CreateDispatcher();
var source = new DispatcherMovementInputSource(capture);
var source = CreateSource(capture);
source.Bind(dispatcher);
source.HandlePressedAction(InputAction.MovementRunLock);
@ -78,7 +78,7 @@ public sealed class DispatcherMovementInputSourceTests
[InlineData(InputAction.MovementStrafeRight)]
public void RetailCancelActionsClearAutorun(InputAction action)
{
var source = new DispatcherMovementInputSource();
var source = CreateSource();
source.HandlePressedAction(InputAction.MovementRunLock);
Assert.False(source.HandlePressedAction(action));
@ -89,7 +89,7 @@ public sealed class DispatcherMovementInputSourceTests
[Fact]
public void ForwardDoesNotCancelAutorunAndResetDoes()
{
var source = new DispatcherMovementInputSource();
var source = CreateSource();
source.HandlePressedAction(InputAction.MovementRunLock);
Assert.False(source.HandlePressedAction(InputAction.MovementForward));
@ -102,7 +102,7 @@ public sealed class DispatcherMovementInputSourceTests
[Fact]
public void BindingIsIdempotentOnlyForTheSameDispatcher()
{
var source = new DispatcherMovementInputSource();
var source = CreateSource();
var (first, _, _) = CreateDispatcher();
var (second, _, _) = CreateDispatcher();
@ -115,7 +115,7 @@ public sealed class DispatcherMovementInputSourceTests
[Fact]
public void UnbindRequiresExactDispatcherAndRestoresNeutralCapture()
{
var source = new DispatcherMovementInputSource();
var source = CreateSource();
var (first, _, _) = CreateDispatcher();
var (other, _, _) = CreateDispatcher();
source.Bind(first);
@ -142,6 +142,10 @@ public sealed class DispatcherMovementInputSourceTests
return (dispatcher, keyboard, mouse);
}
private static DispatcherMovementInputSource CreateSource(
IInputCaptureSource? capture = null) =>
new(new RuntimeLocalPlayerMovementState(), capture);
private sealed class FakeKeyboard : IKeyboardSource
{
#pragma warning disable CS0067