refactor(runtime): close canonical gameplay ownership
Unify the toolbar shortcut manager with Runtime inventory state, route retail-ordered shortcut and spellbook command effects through the canonical owners, and make retained controllers borrow those exact instances. Remove the item-interaction transaction fallback and add graphical/no-window parity plus failure-safe terminal ownership-ledger coverage. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
ce6fae7b38
commit
89e6b207f8
36 changed files with 1433 additions and 251 deletions
|
|
@ -371,7 +371,7 @@ public sealed class CurrentGameRuntimeAdapterTests
|
|||
harness.Character.Options.Replace(0x04000000u, 0x00948700u);
|
||||
harness.Character.MovementSkills.Update(200, 175);
|
||||
harness.Character.Spellbook.OnSpellLearned(42u);
|
||||
harness.InventoryState.Shortcuts.Replace(
|
||||
harness.InventoryState.Shortcuts.Load(
|
||||
[
|
||||
new ShortcutEntry(1, 0x80000001u, 0u),
|
||||
]);
|
||||
|
|
@ -506,6 +506,20 @@ public sealed class CurrentGameRuntimeAdapterTests
|
|||
static entry => entry.Kind == RuntimeTraceKind.Command
|
||||
&& (entry.Code >> 16)
|
||||
== (int)RuntimeCommandDomain.Social);
|
||||
Assert.True(harness.InventoryState.View.TryGetShortcut(
|
||||
2,
|
||||
out RuntimeShortcutSnapshot storedShortcut));
|
||||
Assert.Equal(0x80000001u, storedShortcut.ObjectId);
|
||||
Assert.True(harness.Character.View.TryGetFavorite(
|
||||
0,
|
||||
0,
|
||||
out uint storedFavorite));
|
||||
Assert.Equal(42u, storedFavorite);
|
||||
Assert.Equal(0x3FFEu, harness.Character.Spellbook.SpellbookFilters);
|
||||
Assert.True(harness.Character.View.TryGetDesiredComponent(
|
||||
0x68000001u,
|
||||
out uint storedDesired));
|
||||
Assert.Equal(10u, storedDesired);
|
||||
|
||||
int published = harness.Commands.Published.Count;
|
||||
RuntimeCommandResult stale = commands.Character.SetOptions1(
|
||||
|
|
@ -515,6 +529,101 @@ public sealed class CurrentGameRuntimeAdapterTests
|
|||
Assert.Equal(published, harness.Commands.Published.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GraphicalAndNoWindowJ4CommandsProduceIdenticalCanonicalState()
|
||||
{
|
||||
using var directEntities = new RuntimeEntityObjectLifetime();
|
||||
using var directInventory =
|
||||
new RuntimeInventoryState(directEntities);
|
||||
using var directCharacter = new RuntimeCharacterState();
|
||||
using var harness = new Harness();
|
||||
_ = harness.Runtime.Session.Start(harness.Runtime.Generation);
|
||||
RuntimeGenerationToken generation = harness.Runtime.Generation;
|
||||
IGameRuntimeCommands graphical = harness.Runtime;
|
||||
var directOutbound = new List<string>();
|
||||
var shortcut = new ShortcutEntry(2, 0x80000001u, 0u);
|
||||
|
||||
Assert.True(directInventory.TryAddShortcut(
|
||||
shortcut,
|
||||
() => directOutbound.Add("add-shortcut")));
|
||||
Assert.True(directCharacter.TryAddFavorite(
|
||||
0,
|
||||
0,
|
||||
42u,
|
||||
() => directOutbound.Add("add-favorite")));
|
||||
directCharacter.SetSpellbookFilter(
|
||||
0x3FFEu,
|
||||
() => directOutbound.Add("filter"));
|
||||
Assert.True(directCharacter.TrySetDesiredComponent(
|
||||
0x68000001u,
|
||||
10u,
|
||||
() => directOutbound.Add("desired")));
|
||||
|
||||
Assert.True(graphical.InventoryState.AddShortcut(
|
||||
generation,
|
||||
new RuntimeShortcutCommand(
|
||||
shortcut.Index,
|
||||
shortcut.ObjectId,
|
||||
shortcut.SpellId)).Accepted);
|
||||
Assert.True(graphical.Spellbook.AddFavorite(
|
||||
generation,
|
||||
0,
|
||||
0,
|
||||
42u).Accepted);
|
||||
Assert.True(graphical.Spellbook.SetFilter(
|
||||
generation,
|
||||
0x3FFEu).Accepted);
|
||||
Assert.True(graphical.Spellbook.SetDesiredComponent(
|
||||
generation,
|
||||
0x68000001u,
|
||||
10u).Accepted);
|
||||
|
||||
Assert.Equal(
|
||||
directInventory.View.Snapshot,
|
||||
harness.InventoryState.View.Snapshot);
|
||||
Assert.Equal(
|
||||
directCharacter.View.Snapshot,
|
||||
harness.Character.View.Snapshot);
|
||||
Assert.Equal(
|
||||
directInventory.Shortcuts.Items,
|
||||
harness.InventoryState.Shortcuts.Items);
|
||||
Assert.Equal(
|
||||
directCharacter.Spellbook.GetFavorites(0),
|
||||
harness.Character.Spellbook.GetFavorites(0));
|
||||
Assert.Equal(
|
||||
["add-shortcut", "add-favorite", "filter", "desired"],
|
||||
directOutbound);
|
||||
|
||||
Assert.True(directInventory.TryRemoveShortcut(
|
||||
2,
|
||||
() => directOutbound.Add("remove-shortcut")));
|
||||
Assert.True(directCharacter.TryRemoveFavorite(
|
||||
0,
|
||||
42u,
|
||||
() => directOutbound.Add("remove-favorite")));
|
||||
directCharacter.ClearDesiredComponents(
|
||||
() => directOutbound.Add("clear-desired"));
|
||||
Assert.True(graphical.InventoryState.RemoveShortcut(
|
||||
generation,
|
||||
2).Accepted);
|
||||
Assert.True(graphical.Spellbook.RemoveFavorite(
|
||||
generation,
|
||||
0,
|
||||
42u).Accepted);
|
||||
Assert.True(graphical.Spellbook.ClearDesiredComponents(
|
||||
generation).Accepted);
|
||||
|
||||
Assert.Equal(
|
||||
directInventory.View.Snapshot,
|
||||
harness.InventoryState.View.Snapshot);
|
||||
Assert.Equal(
|
||||
directCharacter.View.Snapshot,
|
||||
harness.Character.View.Snapshot);
|
||||
Assert.Empty(harness.InventoryState.Shortcuts.Items);
|
||||
Assert.Empty(harness.Character.Spellbook.GetFavorites(0));
|
||||
Assert.Empty(harness.Character.Spellbook.DesiredComponents);
|
||||
}
|
||||
|
||||
private static ClientObject Object(WorldSession.EntitySpawn spawn) => new()
|
||||
{
|
||||
ObjectId = spawn.Guid,
|
||||
|
|
@ -587,6 +696,7 @@ public sealed class CurrentGameRuntimeAdapterTests
|
|||
|
||||
_items = new ItemInteractionController(
|
||||
Objects,
|
||||
InventoryState.Transactions,
|
||||
() => PlayerGuid,
|
||||
sendUse: null,
|
||||
sendUseWithTarget: null,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue