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

@ -2,6 +2,7 @@ using System.Runtime.CompilerServices;
using AcDream.App.Net;
using AcDream.App.UI;
using AcDream.Core.Chat;
using AcDream.Core.Items;
using AcDream.Core.Social;
using AcDream.UI.Abstractions;
@ -220,6 +221,35 @@ public sealed class LiveSessionCommandRouterTests
GC.KeepAlive(router);
}
[Fact]
public void RuntimeStateCommandsUseActiveGenerationRouteAndBecomeInert()
{
var shortcuts = new List<ShortcutEntry>();
var options = new List<uint>();
LiveSessionCommandRouter router = NewRouter(
addShortcut: shortcuts.Add,
setCharacterOptions: options.Add);
router.Publish(new AddShortcutRuntimeCmd(
new ShortcutEntry(1, 0x80000001u, 0u)));
router.Activate();
router.Publish(new AddShortcutRuntimeCmd(
new ShortcutEntry(2, 0x80000002u, 0u)));
router.Publish(new SetCharacterOptionsRuntimeCmd(0x50C4A54Au));
router.Dispose();
router.Publish(new AddShortcutRuntimeCmd(
new ShortcutEntry(3, 0x80000003u, 0u)));
Assert.Collection(
shortcuts,
entry =>
{
Assert.Equal(2, entry.Index);
Assert.Equal(0x80000002u, entry.ObjectId);
});
Assert.Equal([0x50C4A54Au], options);
}
private static LiveSessionCommandRouter NewRouter(
ChatLog? chat = null,
TurbineChatState? turbine = null,
@ -228,6 +258,8 @@ public sealed class LiveSessionCommandRouterTests
Action<string, string>? sendTell = null,
Action<uint, string>? sendChannel = null,
Action<uint, uint, uint, uint, string, uint>? sendTurbine = null,
Action<ShortcutEntry>? addShortcut = null,
Action<uint>? setCharacterOptions = null,
Action<string>? log = null,
ClientCommandController.Bindings? clientBindings = null) => new(
new LiveSessionCommandBindings(
@ -239,7 +271,27 @@ public sealed class LiveSessionCommandRouterTests
sendTell ?? ((_, _) => { }),
sendChannel ?? ((_, _) => { }),
sendTurbine ?? ((_, _, _, _, _, _) => { }),
log));
AddShortcut: addShortcut ?? (_ => { }),
RemoveShortcut: _ => { },
AddFavorite: (_, _, _) => { },
RemoveFavorite: (_, _) => { },
SetSpellbookFilter: _ => { },
ForgetSpell: _ => { },
SetDesiredComponent: (_, _) => { },
ClearDesiredComponents: () => { },
RaiseAttribute: (_, _) => { },
RaiseVital: (_, _) => { },
RaiseSkill: (_, _) => { },
TrainSkill: (_, _) => { },
SetCharacterOptions: setCharacterOptions ?? (_ => { }),
AddFriend: _ => { },
RemoveFriend: _ => { },
ClearFriends: () => { },
RequestLegacyFriends: () => { },
ModifyCharacterSquelch: (_, _, _, _) => { },
ModifyAccountSquelch: (_, _) => { },
ModifyGlobalSquelch: (_, _) => { },
Log: log));
[MethodImpl(MethodImplOptions.NoInlining)]
private static (LiveSessionCommandRouter, WeakReference<object>)