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:
Erik 2026-07-26 09:12:30 +02:00
parent 9d0d9b07e0
commit dcb61efb5a
34 changed files with 2076 additions and 103 deletions

View file

@ -1,3 +1,6 @@
using System.Reflection;
using AcDream.Runtime.Gameplay;
namespace AcDream.Runtime.Tests;
public sealed class GameRuntimeContractTests
@ -137,4 +140,68 @@ public sealed class GameRuntimeContractTests
Assert.Equal("General|Grey|hello", entry.Text);
});
}
[Fact]
public void TraceRecorderIncludesJ4GameplayStateInCheckpoint()
{
var recorder = new RuntimeTraceRecorder();
var stamp = new RuntimeEventStamp(new(3), 1, 8);
var checkpoint = new RuntimeStateCheckpoint(
new RuntimeGenerationToken(3),
RuntimeLifecycleState.InWorld,
FrameNumber: 8,
EntityCount: 2,
MaterializedEntityCount: 2,
InventoryObjectCount: 1,
InventoryContainerCount: 1,
new RuntimeInventoryStateSnapshot(
0u, 0u, 0, true, null, 2, 4, 1, 3),
new RuntimeCharacterSnapshot(
CharacterRevision: 5,
SpellbookRevision: 6,
default,
default,
LearnedSpellCount: 7,
ActiveEnchantmentCount: 0,
DesiredComponentCount: 0,
SkillCount: 8,
SpellbookFilters: 0x3FFFu),
new RuntimeSocialSnapshot(9, 10, 11, 0, 0, 0, 0),
ChatRevision: 12,
ChatCount: 13,
default,
default);
recorder.AddCheckpoint(stamp, checkpoint);
RuntimeTraceEntry entry = Assert.Single(recorder.Entries);
Assert.Contains("inventory-state=2:4:1:3", entry.Text);
Assert.Contains("character=5:6:7:8:0:0", entry.Text);
Assert.Contains("social=9:10:11", entry.Text);
}
[Fact]
public void J4GameplayOwnersHaveNoStaticMutableSessionState()
{
Type[] owners =
[
typeof(RuntimeCommunicationState),
typeof(RuntimeInventoryState),
typeof(RuntimeCharacterState),
typeof(RuntimeCharacterOptionsState),
typeof(RuntimeMovementSkillState),
];
foreach (Type owner in owners)
{
FieldInfo[] mutable = owner
.GetFields(
BindingFlags.Static
| BindingFlags.Public
| BindingFlags.NonPublic)
.Where(static field => !field.IsLiteral)
.ToArray();
Assert.Empty(mutable);
}
}
}