refactor(runtime): expose canonical gameplay state
Move character options and movement skills into the Runtime-owned character graph, expose borrowed inventory, character, and social views, and route retained UI state commands through generation-gated typed Runtime contracts. Preserve the existing synchronous wire path while deleting the App-owned option and skill mirrors and extending normalized parity checkpoints. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
9d0d9b07e0
commit
dcb61efb5a
34 changed files with 2076 additions and 103 deletions
|
|
@ -1,4 +1,5 @@
|
|||
using AcDream.Core.Spells;
|
||||
using AcDream.Core.Player;
|
||||
using AcDream.Runtime.Gameplay;
|
||||
|
||||
namespace AcDream.Runtime.Tests.Gameplay;
|
||||
|
|
@ -152,4 +153,105 @@ public sealed class RuntimeCharacterStateTests
|
|||
|
||||
Assert.True(state.IsDisposed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OwnsRetailCharacterOptionsAndMovementSkillProjection()
|
||||
{
|
||||
using var state = new RuntimeCharacterState();
|
||||
|
||||
Assert.Equal(
|
||||
RuntimeCharacterOptionsState.DefaultOptions1,
|
||||
state.Options.Options1);
|
||||
Assert.Equal(
|
||||
RuntimeCharacterOptionsState.DefaultOptions2,
|
||||
state.Options.Options2);
|
||||
Assert.False(state.MovementSkills.IsComplete);
|
||||
|
||||
state.Options.Replace(0x04000000u, 0x12345678u);
|
||||
state.MovementSkills.Update(runSkill: 210, jumpSkill: -1);
|
||||
state.MovementSkills.Update(runSkill: -1, jumpSkill: 165);
|
||||
|
||||
Assert.True(state.Options.DragItemOnPlayerOpensSecureTrade);
|
||||
Assert.Equal(0x12345678u, state.Options.Options2);
|
||||
Assert.Equal(
|
||||
new RuntimeMovementSkillSnapshot(
|
||||
210,
|
||||
165,
|
||||
state.MovementSkills.Revision),
|
||||
state.MovementSkills.Snapshot);
|
||||
Assert.True(state.MovementSkills.IsComplete);
|
||||
|
||||
state.ResetSession();
|
||||
|
||||
Assert.Equal(
|
||||
RuntimeCharacterOptionsState.DefaultOptions1,
|
||||
state.Options.Options1);
|
||||
Assert.Equal(
|
||||
RuntimeCharacterOptionsState.DefaultOptions2,
|
||||
state.Options.Options2);
|
||||
Assert.Equal(-1, state.MovementSkills.RunSkill);
|
||||
Assert.Equal(-1, state.MovementSkills.JumpSkill);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CharacterViewBorrowsExactOwnersWithoutReconstructedState()
|
||||
{
|
||||
using var state = new RuntimeCharacterState();
|
||||
state.LocalPlayer.OnAttributeUpdate(1u, 40u, 10u, 500u);
|
||||
state.LocalPlayer.OnVitalUpdate(7u, 60u, 20u, 700u, 75u);
|
||||
state.LocalPlayer.OnSkillUpdate(
|
||||
6u,
|
||||
30u,
|
||||
2u,
|
||||
800u,
|
||||
10u,
|
||||
0u,
|
||||
5d,
|
||||
12u);
|
||||
state.Spellbook.OnSpellLearned(42u);
|
||||
state.Spellbook.SetFavorite(0, 0, 42u);
|
||||
state.Spellbook.SetDesiredComponent(0x68000001u, 11u);
|
||||
|
||||
RuntimeCharacterSnapshot summary = state.View.Snapshot;
|
||||
|
||||
Assert.Equal(1, summary.LearnedSpellCount);
|
||||
Assert.Equal(1, summary.DesiredComponentCount);
|
||||
Assert.Equal(1, summary.SkillCount);
|
||||
Assert.True(state.View.KnowsSpell(42u));
|
||||
Assert.True(state.View.TryGetFavorite(0, 0, out uint favorite));
|
||||
Assert.Equal(42u, favorite);
|
||||
Assert.True(state.View.TryGetDesiredComponent(
|
||||
0x68000001u,
|
||||
out uint desired));
|
||||
Assert.Equal(11u, desired);
|
||||
Assert.True(state.View.TryGetAttribute(
|
||||
(int)LocalPlayerState.AttributeKind.Strength,
|
||||
out RuntimeAttributeSnapshot attribute));
|
||||
Assert.Equal(50u, attribute.Current);
|
||||
Assert.True(state.View.TryGetVital(
|
||||
(int)LocalPlayerState.VitalKind.Health,
|
||||
out RuntimeVitalSnapshot vital));
|
||||
Assert.Equal(75u, vital.Current);
|
||||
Assert.True(state.View.TryGetSkill(6u, out RuntimeSkillSnapshot skill));
|
||||
Assert.Equal(52u, skill.CurrentLevel);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TwoRuntimeInstancesIsolateOptionsSkillsAndViewRevisions()
|
||||
{
|
||||
using var first = new RuntimeCharacterState();
|
||||
using var second = new RuntimeCharacterState();
|
||||
|
||||
first.Options.Replace(1u, 2u);
|
||||
first.MovementSkills.Update(100, 200);
|
||||
first.Spellbook.OnSpellLearned(9u);
|
||||
|
||||
Assert.NotEqual(
|
||||
first.View.Snapshot.Options,
|
||||
second.View.Snapshot.Options);
|
||||
Assert.True(first.View.Snapshot.MovementSkills.IsComplete);
|
||||
Assert.False(second.View.Snapshot.MovementSkills.IsComplete);
|
||||
Assert.True(first.View.Snapshot.SpellbookRevision > 0);
|
||||
Assert.Equal(0, second.View.Snapshot.SpellbookRevision);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue