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

@ -38,11 +38,10 @@ internal sealed class CurrentGameRuntimeAdapter
RuntimeCharacterState character,
RuntimeCommunicationState communication,
RuntimeActionState actions,
ILocalPlayerControllerSource playerController,
RuntimeLocalPlayerMovementState movement,
WorldRevealCoordinator worldReveal,
IGameRuntimeClock clock,
SelectionInteractionController selection,
GameplayInputFrameController gameplayInput)
SelectionInteractionController selection)
{
_view = new CurrentGameRuntimeViewAdapter(
session,
@ -53,7 +52,7 @@ internal sealed class CurrentGameRuntimeAdapter
character,
communication,
actions,
playerController,
movement,
worldReveal,
clock);
entityObjects.BindEventContext(
@ -71,8 +70,8 @@ internal sealed class CurrentGameRuntimeAdapter
inventory,
character,
actions,
movement,
selection,
gameplayInput,
_events);
}

View file

@ -34,8 +34,8 @@ internal sealed class CurrentGameRuntimeCommandAdapter
private readonly RuntimeInventoryState _inventory;
private readonly RuntimeCharacterState _character;
private readonly RuntimeActionState _actions;
private readonly RuntimeLocalPlayerMovementState _movement;
private readonly SelectionInteractionController _selection;
private readonly GameplayInputFrameController _gameplayInput;
private readonly ICurrentGameRuntimeEventSink _events;
public CurrentGameRuntimeCommandAdapter(
@ -46,8 +46,8 @@ internal sealed class CurrentGameRuntimeCommandAdapter
RuntimeInventoryState inventory,
RuntimeCharacterState character,
RuntimeActionState actions,
RuntimeLocalPlayerMovementState movement,
SelectionInteractionController selection,
GameplayInputFrameController gameplayInput,
ICurrentGameRuntimeEventSink events)
{
_session = session ?? throw new ArgumentNullException(nameof(session));
@ -58,9 +58,9 @@ internal sealed class CurrentGameRuntimeCommandAdapter
_character = character ?? throw new ArgumentNullException(nameof(character));
_actions = actions
?? throw new ArgumentNullException(nameof(actions));
_movement = movement
?? throw new ArgumentNullException(nameof(movement));
_selection = selection ?? throw new ArgumentNullException(nameof(selection));
_gameplayInput = gameplayInput
?? throw new ArgumentNullException(nameof(gameplayInput));
_events = events ?? throw new ArgumentNullException(nameof(events));
}
@ -246,22 +246,9 @@ internal sealed class CurrentGameRuntimeCommandAdapter
if (gate != RuntimeCommandStatus.Accepted)
return Result(gate);
InputAction action = command switch
{
RuntimeMovementCommand.ToggleRunLock => InputAction.MovementRunLock,
RuntimeMovementCommand.Stop => InputAction.MovementStop,
_ => InputAction.None,
};
RuntimeCommandStatus status;
if (action == InputAction.None)
{
status = RuntimeCommandStatus.Unsupported;
}
else
{
_gameplayInput.HandlePressedMovementAction(action);
status = RuntimeCommandStatus.Accepted;
}
RuntimeCommandStatus status = _movement.Execute(command)
? RuntimeCommandStatus.Accepted
: RuntimeCommandStatus.Unsupported;
_events.EmitCommand(RuntimeCommandDomain.Movement, (int)command, status);
return Result(status);

View file

@ -29,7 +29,7 @@ internal sealed class CurrentGameRuntimeViewAdapter : IGameRuntimeView
private readonly IRuntimeSocialView _socialView;
private readonly IRuntimeChatView _chatView;
private readonly IRuntimeActionView _actionView;
private readonly MovementView _movementView;
private readonly IRuntimeMovementView _movementView;
private readonly PortalView _portalView;
private bool _active = true;
@ -42,7 +42,7 @@ internal sealed class CurrentGameRuntimeViewAdapter : IGameRuntimeView
RuntimeCharacterState character,
RuntimeCommunicationState communication,
RuntimeActionState actions,
ILocalPlayerControllerSource playerController,
RuntimeLocalPlayerMovementState movement,
WorldRevealCoordinator worldReveal,
IGameRuntimeClock clock)
{
@ -65,10 +65,8 @@ internal sealed class CurrentGameRuntimeViewAdapter : IGameRuntimeView
_socialView = communication.SocialView;
_actionView = (
actions ?? throw new ArgumentNullException(nameof(actions))).View;
_movementView = new MovementView(
playerController
?? throw new ArgumentNullException(nameof(playerController)),
_clock);
_movementView = (
movement ?? throw new ArgumentNullException(nameof(movement))).View;
_portalView = new PortalView(
worldReveal ?? throw new ArgumentNullException(nameof(worldReveal)));
}
@ -132,35 +130,6 @@ internal sealed class CurrentGameRuntimeViewAdapter : IGameRuntimeView
internal void Deactivate() => _active = false;
private sealed class MovementView(
ILocalPlayerControllerSource owner,
IGameRuntimeClock clock)
: IRuntimeMovementView
{
public RuntimeMovementSnapshot Snapshot
{
get
{
PlayerMovementController? controller = owner.Controller;
return controller is null
? new RuntimeMovementSnapshot(
false,
0u,
default,
default,
false,
clock.SimulationTimeSeconds)
: new RuntimeMovementSnapshot(
true,
controller.LocalEntityId,
controller.CellPosition,
controller.BodyVelocity,
controller.IsAirborne,
clock.SimulationTimeSeconds);
}
}
}
private sealed class PortalView(WorldRevealCoordinator owner)
: IRuntimePortalView
{