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:
parent
3456dff038
commit
aa3f4a60f8
36 changed files with 878 additions and 276 deletions
|
|
@ -782,7 +782,8 @@ public sealed class CurrentGameRuntimeAdapterTests
|
|||
CombatMode = new RecordingCombatModeOperations();
|
||||
_combatModeBinding =
|
||||
CombatModeOperations.BindOwned(CombatMode);
|
||||
MovementInput = new DispatcherMovementInputSource();
|
||||
MovementState = new RuntimeLocalPlayerMovementState();
|
||||
MovementInput = new DispatcherMovementInputSource(MovementState);
|
||||
GameplayInput = new GameplayInputFrameController(
|
||||
dispatcher: null,
|
||||
MovementInput,
|
||||
|
|
@ -832,11 +833,10 @@ public sealed class CurrentGameRuntimeAdapterTests
|
|||
Character,
|
||||
Communication,
|
||||
Actions,
|
||||
new LocalPlayerControllerSlot(),
|
||||
MovementState,
|
||||
WorldReveal,
|
||||
Clock,
|
||||
selectionController,
|
||||
GameplayInput);
|
||||
selectionController);
|
||||
}
|
||||
|
||||
public RuntimeOptions Options { get; }
|
||||
|
|
@ -853,6 +853,7 @@ public sealed class CurrentGameRuntimeAdapterTests
|
|||
public RuntimeSpellCastOperationsSlot SpellCastOperations { get; }
|
||||
public RuntimeActionState Actions { get; }
|
||||
public SelectionState Selection => Actions.Selection;
|
||||
public RuntimeLocalPlayerMovementState MovementState { get; }
|
||||
public DispatcherMovementInputSource MovementInput { get; }
|
||||
public GameplayInputFrameController GameplayInput { get; }
|
||||
public RecordingCombatModeOperations CombatMode { get; }
|
||||
|
|
@ -874,6 +875,7 @@ public sealed class CurrentGameRuntimeAdapterTests
|
|||
Actions.Dispose();
|
||||
InventoryState.Dispose();
|
||||
Entities.Clear();
|
||||
MovementState.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
123
tests/AcDream.App.Tests/Runtime/RuntimeMovementOwnershipTests.cs
Normal file
123
tests/AcDream.App.Tests/Runtime/RuntimeMovementOwnershipTests.cs
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AcDream.App.Tests.Runtime;
|
||||
|
||||
public sealed class RuntimeMovementOwnershipTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProductionConstructsOneCanonicalRuntimeMovementOwner()
|
||||
{
|
||||
string root = FindRepositoryRoot();
|
||||
string appRoot = Path.Combine(root, "src", "AcDream.App");
|
||||
string runtimeRoot = Path.Combine(root, "src", "AcDream.Runtime");
|
||||
string app = string.Join(
|
||||
"\n",
|
||||
Directory.EnumerateFiles(appRoot, "*.cs", SearchOption.AllDirectories)
|
||||
.Select(File.ReadAllText));
|
||||
string runtime = string.Join(
|
||||
"\n",
|
||||
Directory.EnumerateFiles(runtimeRoot, "*.cs", SearchOption.AllDirectories)
|
||||
.Select(File.ReadAllText));
|
||||
|
||||
Assert.False(File.Exists(Path.Combine(
|
||||
appRoot,
|
||||
"Input",
|
||||
"PlayerMovementController.cs")));
|
||||
Assert.False(File.Exists(Path.Combine(
|
||||
appRoot,
|
||||
"Input",
|
||||
"LocalPlayerOutboundController.cs")));
|
||||
Assert.DoesNotContain(
|
||||
"class PlayerMovementController",
|
||||
app,
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain(
|
||||
"class LocalPlayerOutboundController",
|
||||
app,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Empty(Regex.Matches(app, @"\bbool\s+_autoRunActive\b"));
|
||||
Assert.Single(Regex.Matches(
|
||||
app,
|
||||
@"RuntimeLocalPlayerMovementState\s+\w+\s*=\s*new\s*\(")
|
||||
.Cast<Match>());
|
||||
Assert.DoesNotContain(
|
||||
"ACDREAM_RUN_SKILL",
|
||||
runtime,
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain(
|
||||
"ACDREAM_JUMP_SKILL",
|
||||
runtime,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GraphicalInputRuntimeViewsAndShutdownBorrowTheExactOwner()
|
||||
{
|
||||
string root = FindRepositoryRoot();
|
||||
string gameWindow = ReadAppSource(root, "Rendering", "GameWindow.cs");
|
||||
string input = ReadAppSource(
|
||||
root,
|
||||
"Input",
|
||||
"DispatcherMovementInputSource.cs");
|
||||
string view = ReadAppSource(
|
||||
root,
|
||||
"Runtime",
|
||||
"CurrentGameRuntimeViewAdapter.cs");
|
||||
string commands = ReadAppSource(
|
||||
root,
|
||||
"Runtime",
|
||||
"CurrentGameRuntimeCommandAdapter.cs");
|
||||
string lifetime = ReadAppSource(
|
||||
root,
|
||||
"Rendering",
|
||||
"GameWindowLifetime.cs");
|
||||
|
||||
Assert.Contains(
|
||||
"RuntimeLocalPlayerMovementState _playerControllerSlot = new();",
|
||||
gameWindow,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"new AcDream.App.Input.DispatcherMovementInputSource(",
|
||||
gameWindow,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"_playerControllerSlot,",
|
||||
gameWindow,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"RuntimeLocalPlayerMovementState movement,",
|
||||
input,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("_movement.AutoRunActive", input, StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"movement ?? throw new ArgumentNullException(nameof(movement))).View",
|
||||
view,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("_movement.Execute(command)", commands, StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"RuntimeLocalPlayerMovementState Movement",
|
||||
lifetime,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"\"runtime local movement state\"",
|
||||
lifetime,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static string ReadAppSource(string root, params string[] relative) =>
|
||||
File.ReadAllText(Path.Combine(
|
||||
[root, "src", "AcDream.App", .. relative]));
|
||||
|
||||
private static string FindRepositoryRoot()
|
||||
{
|
||||
var current = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
while (current is not null)
|
||||
{
|
||||
if (File.Exists(Path.Combine(current.FullName, "AcDream.slnx")))
|
||||
return current.FullName;
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
throw new DirectoryNotFoundException("AcDream.slnx was not found.");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue