Move selection, combat, and interaction target mode under one Runtime owner; make plugins, retained UI, session routing, and typed runtime views borrow its exact children; and add failure-safe reset, instance isolation, source ownership, and normalized checkpoint coverage without changing retail ordering. Co-authored-by: Codex <codex@openai.com>
120 lines
4.3 KiB
C#
120 lines
4.3 KiB
C#
using AcDream.Core.Combat;
|
|
using AcDream.Core.Selection;
|
|
using AcDream.Runtime.Gameplay;
|
|
|
|
namespace AcDream.Runtime.Tests.Gameplay;
|
|
|
|
public sealed class RuntimeActionStateTests
|
|
{
|
|
[Fact]
|
|
public void ViewProjectsTheExactCanonicalChildrenAndRevisions()
|
|
{
|
|
using var actions = new RuntimeActionState();
|
|
|
|
actions.Selection.Select(
|
|
0x50000001u,
|
|
SelectionChangeSource.World);
|
|
actions.Combat.SetCombatMode(CombatMode.Missile);
|
|
actions.Combat.OnUpdateHealth(0x50000001u, 0.625f);
|
|
actions.Interaction.EnterUseItemOnTarget(0x70000001u);
|
|
|
|
RuntimeActionSnapshot snapshot = actions.View.Snapshot;
|
|
|
|
Assert.Equal(1, snapshot.SelectionRevision);
|
|
Assert.Equal(0x50000001u, snapshot.SelectedObjectId);
|
|
Assert.Equal(2, snapshot.CombatRevision);
|
|
Assert.Equal(CombatMode.Missile, snapshot.CombatMode);
|
|
Assert.Equal(1, snapshot.TrackedTargetHealthCount);
|
|
Assert.Equal(1, snapshot.InteractionRevision);
|
|
Assert.Equal(
|
|
InteractionModeKind.UseItemOnTarget,
|
|
snapshot.InteractionMode);
|
|
Assert.Equal(0x70000001u, snapshot.InteractionSourceObjectId);
|
|
Assert.True(
|
|
actions.View.TryGetHealth(0x50000001u, out float health));
|
|
Assert.Equal(0.625f, health);
|
|
}
|
|
|
|
[Fact]
|
|
public void ResetSessionConvergesEveryChildAfterObserverFailures()
|
|
{
|
|
var actions = new RuntimeActionState();
|
|
actions.Selection.Select(
|
|
0x50000001u,
|
|
SelectionChangeSource.World);
|
|
actions.Combat.SetCombatMode(CombatMode.Melee);
|
|
actions.Combat.OnUpdateHealth(0x50000001u, 0.25f);
|
|
actions.Interaction.EnterExamine();
|
|
|
|
actions.Selection.Changed += static _ =>
|
|
throw new InvalidOperationException("selection observer");
|
|
actions.Combat.CombatModeChanged += static _ =>
|
|
throw new InvalidOperationException("combat observer");
|
|
actions.Interaction.Changed += static _ =>
|
|
throw new InvalidOperationException("interaction observer");
|
|
|
|
Assert.Throws<AggregateException>(actions.ResetSession);
|
|
|
|
RuntimeActionOwnershipSnapshot snapshot =
|
|
actions.CaptureOwnership();
|
|
Assert.Equal(0u, snapshot.SelectedObjectId);
|
|
Assert.Equal(0u, snapshot.PreviousObjectId);
|
|
Assert.Equal(0u, snapshot.PreviousValidObjectId);
|
|
Assert.Equal(CombatMode.NonCombat, snapshot.CombatMode);
|
|
Assert.Equal(0, snapshot.TrackedTargetHealthCount);
|
|
Assert.Equal(InteractionMode.None, snapshot.InteractionMode);
|
|
Assert.Throws<AggregateException>(actions.Dispose);
|
|
}
|
|
|
|
[Fact]
|
|
public void DisposeIsTerminalAndConvergedAfterObserverFailures()
|
|
{
|
|
var actions = new RuntimeActionState();
|
|
actions.Selection.Select(
|
|
0x50000001u,
|
|
SelectionChangeSource.World);
|
|
actions.Combat.SetCombatMode(CombatMode.Magic);
|
|
actions.Combat.OnUpdateHealth(0x50000001u, 0.5f);
|
|
actions.Interaction.EnterUse();
|
|
actions.Selection.Changed += static _ =>
|
|
throw new InvalidOperationException("selection observer");
|
|
actions.Combat.CombatModeChanged += static _ =>
|
|
throw new InvalidOperationException("combat observer");
|
|
actions.Interaction.Changed += static _ =>
|
|
throw new InvalidOperationException("interaction observer");
|
|
|
|
Assert.Throws<AggregateException>(actions.Dispose);
|
|
|
|
RuntimeActionOwnershipSnapshot snapshot =
|
|
actions.CaptureOwnership();
|
|
Assert.True(snapshot.IsConverged);
|
|
actions.Dispose();
|
|
}
|
|
|
|
[Fact]
|
|
public void InstancesAreFullyIsolated()
|
|
{
|
|
using var first = new RuntimeActionState();
|
|
using var second = new RuntimeActionState();
|
|
|
|
first.Selection.Select(
|
|
0x50000001u,
|
|
SelectionChangeSource.World);
|
|
first.Combat.SetCombatMode(CombatMode.Missile);
|
|
first.Interaction.EnterUse();
|
|
|
|
Assert.Equal(
|
|
new RuntimeActionSnapshot(
|
|
0,
|
|
0u,
|
|
0u,
|
|
0u,
|
|
0,
|
|
CombatMode.NonCombat,
|
|
0,
|
|
0,
|
|
InteractionModeKind.None,
|
|
0u),
|
|
second.View.Snapshot);
|
|
}
|
|
}
|