feat(runtime): define borrowed views commands and ordered events

Establish the J1 presentation-independent contract with instance-scoped clocks and generations, immutable borrowed views, typed generation-gated commands, normalized ordered diagnostics, and teardown acknowledgements. Route graphical startup plus press-time selection, movement, and combat through focused App adapters over the exact existing owners without adding a queue or mirrored world.

Validated by the Release solution build, 13 Runtime tests, 3,838 App tests with three existing skips, and the complete 8,424-test Release suite with five existing skips.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-25 19:08:42 +02:00
parent afebbe3eca
commit 854d9e9cd1
21 changed files with 2594 additions and 44 deletions

View file

@ -2,6 +2,7 @@ using AcDream.App.Interaction;
using AcDream.App.Rendering;
using AcDream.App.UI;
using AcDream.Core.Combat;
using AcDream.Runtime;
using AcDream.UI.Abstractions.Input;
namespace AcDream.App.Input;
@ -83,6 +84,9 @@ internal sealed class RuntimeGameplayInputPriorityTargets
private readonly CameraPointerInputController _pointer;
private readonly RetailUiRuntime? _retainedUi;
private readonly SelectionInteractionController? _selection;
private readonly IGameRuntimeView _runtimeView;
private readonly IRuntimeSelectionCommands _runtimeSelection;
private readonly IRuntimeMovementCommands _runtimeMovement;
private readonly IGameplayInputCommandTarget _commands;
public RuntimeGameplayInputPriorityTargets(
@ -90,12 +94,21 @@ internal sealed class RuntimeGameplayInputPriorityTargets
CameraPointerInputController pointer,
RetailUiRuntime? retainedUi,
SelectionInteractionController? selection,
IGameRuntimeView runtimeView,
IRuntimeSelectionCommands runtimeSelection,
IRuntimeMovementCommands runtimeMovement,
IGameplayInputCommandTarget commands)
{
_frame = frame ?? throw new ArgumentNullException(nameof(frame));
_pointer = pointer ?? throw new ArgumentNullException(nameof(pointer));
_retainedUi = retainedUi;
_selection = selection;
_runtimeView = runtimeView
?? throw new ArgumentNullException(nameof(runtimeView));
_runtimeSelection = runtimeSelection
?? throw new ArgumentNullException(nameof(runtimeSelection));
_runtimeMovement = runtimeMovement
?? throw new ArgumentNullException(nameof(runtimeMovement));
_commands = commands ?? throw new ArgumentNullException(nameof(commands));
}
@ -111,11 +124,48 @@ internal sealed class RuntimeGameplayInputPriorityTargets
public bool HandleRetainedUiAction(InputAction action) =>
_retainedUi?.HandleInputAction(action) == true;
public bool HandleSelectionAction(InputAction action) =>
_selection?.HandleInputAction(action) == true;
public bool HandleSelectionAction(InputAction action)
{
RuntimeSelectionCommand? command = action switch
{
InputAction.SelectionClosestMonster =>
RuntimeSelectionCommand.SelectClosestHostile,
InputAction.SelectionPreviousSelection =>
RuntimeSelectionCommand.SelectPrevious,
InputAction.SelectionExamine =>
RuntimeSelectionCommand.ExamineSelected,
InputAction.UseSelected =>
RuntimeSelectionCommand.UseSelected,
InputAction.SelectionPickUp =>
RuntimeSelectionCommand.PickUpSelected,
_ => null,
};
if (command is { } typed)
{
_runtimeSelection.Execute(_runtimeView.Generation, typed);
return true;
}
public bool HandlePressedMovementAction(InputAction action) =>
_frame.HandlePressedMovementAction(action);
return _selection?.HandleInputAction(action) == true;
}
public bool HandlePressedMovementAction(InputAction action)
{
RuntimeMovementCommand? command = action switch
{
InputAction.MovementRunLock =>
RuntimeMovementCommand.ToggleRunLock,
InputAction.MovementStop => RuntimeMovementCommand.Stop,
_ => null,
};
if (command is { } typed)
{
_runtimeMovement.Execute(_runtimeView.Generation, typed);
return true;
}
return _frame.HandlePressedMovementAction(action);
}
public void HandleCommand(InputAction action) =>
_commands.Handle(action);

View file

@ -2,6 +2,7 @@ using AcDream.App.Combat;
using AcDream.App.Diagnostics;
using AcDream.App.Rendering;
using AcDream.App.UI;
using AcDream.Runtime;
using AcDream.UI.Abstractions.Input;
namespace AcDream.App.Input;
@ -137,7 +138,8 @@ internal sealed class GameplayInputCommandController : IGameplayInputCommandTarg
private readonly IPlayerModeGameplayCommands _playerMode;
private readonly IItemTargetModeCommands _targetMode;
private readonly IGameplayCameraModeCommands _camera;
private readonly ILiveCombatModeCommand _combat;
private readonly IGameRuntimeView _runtimeView;
private readonly IRuntimeCombatCommands _combat;
private readonly IGameplayWindowCommands _window;
public GameplayInputCommandController(
@ -147,7 +149,8 @@ internal sealed class GameplayInputCommandController : IGameplayInputCommandTarg
IPlayerModeGameplayCommands playerMode,
IItemTargetModeCommands targetMode,
IGameplayCameraModeCommands camera,
ILiveCombatModeCommand combat,
IGameRuntimeView runtimeView,
IRuntimeCombatCommands combat,
IGameplayWindowCommands window)
{
_retained = retained ?? throw new ArgumentNullException(nameof(retained));
@ -156,6 +159,8 @@ internal sealed class GameplayInputCommandController : IGameplayInputCommandTarg
_playerMode = playerMode ?? throw new ArgumentNullException(nameof(playerMode));
_targetMode = targetMode ?? throw new ArgumentNullException(nameof(targetMode));
_camera = camera ?? throw new ArgumentNullException(nameof(camera));
_runtimeView = runtimeView
?? throw new ArgumentNullException(nameof(runtimeView));
_combat = combat ?? throw new ArgumentNullException(nameof(combat));
_window = window ?? throw new ArgumentNullException(nameof(window));
}
@ -186,7 +191,9 @@ internal sealed class GameplayInputCommandController : IGameplayInputCommandTarg
_devTools.ToggleSettingsPanel();
return true;
case InputAction.CombatToggleCombat:
_combat.Toggle();
_combat.Execute(
_runtimeView.Generation,
RuntimeCombatCommand.ToggleMode);
return true;
case InputAction.EscapeKey:
HandleEscape();