refactor(runtime): own inventory transaction state
Move the retail one-request-at-a-time gate, shared use busy references, external-container state, item mana, shortcuts, and desired-component snapshots into one Runtime-owned graph over J3's exact ClientObjectTable. Retained UI and session routing now borrow that owner; reset and shutdown preserve the existing order while failure/reentrancy tests protect the transaction boundary. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
595d5e6b01
commit
011efbeaa7
18 changed files with 1337 additions and 406 deletions
|
|
@ -46,13 +46,11 @@ internal sealed record InteractionRetainedUiDependencies(
|
|||
CombatState Combat,
|
||||
ICombatAttackOperations CombatAttackOperations,
|
||||
SelectionState Selection,
|
||||
ExternalContainerState ExternalContainers,
|
||||
ClientObjectTable Objects,
|
||||
RuntimeInventoryState Inventory,
|
||||
MagicCatalog MagicCatalog,
|
||||
Spellbook Spellbook,
|
||||
RuntimeCommunicationState Communication,
|
||||
LocalPlayerState LocalPlayer,
|
||||
ItemManaState ItemMana,
|
||||
StackSplitQuantityState StackSplitQuantity,
|
||||
BufferedUiRegistry? UiRegistry,
|
||||
LiveCombatModeCommandSlot CombatModeCommands,
|
||||
|
|
@ -60,7 +58,6 @@ internal sealed record InteractionRetainedUiDependencies(
|
|||
ILocalPlayerControllerSource PlayerController,
|
||||
ILocalPlayerModeSource PlayerMode,
|
||||
PlayerCharacterOptionsState CharacterOptions,
|
||||
ShortcutSnapshotState Shortcuts,
|
||||
Func<DeferredSelectionViewPlaneSource, SelectionCameraSource>
|
||||
SelectionCameraFactory,
|
||||
DeferredRenderFrameDiagnosticsSource FrameDiagnostics,
|
||||
|
|
@ -275,8 +272,8 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
InteractionRetainedUiDependencies d,
|
||||
DeferredLiveSessionUiAuthority session) =>
|
||||
new(
|
||||
d.ExternalContainers,
|
||||
d.Objects,
|
||||
d.Inventory.ExternalContainers,
|
||||
d.Inventory.Objects,
|
||||
guid => session.CurrentSession?.SendNoLongerViewingContents(guid));
|
||||
|
||||
public ItemInteractionController CreateItemInteraction(
|
||||
|
|
@ -286,7 +283,7 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
DeferredLiveSessionUiAuthority session = late.Session;
|
||||
DeferredSelectionUiAuthority selection = late.Selection;
|
||||
return new ItemInteractionController(
|
||||
d.Objects,
|
||||
d.Inventory.Objects,
|
||||
playerGuid: () => d.PlayerIdentity.ServerGuid,
|
||||
sendUse: null,
|
||||
sendExamine: guid => session.CurrentSession?.SendAppraise(guid),
|
||||
|
|
@ -313,7 +310,8 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
placeInBackpack: selection.SendPickup,
|
||||
backpackContainerId: () => late.InventoryContainer.Current(
|
||||
d.PlayerIdentity.ServerGuid),
|
||||
groundObjectId: () => d.ExternalContainers.CurrentContainerId,
|
||||
groundObjectId: () =>
|
||||
d.Inventory.ExternalContainers.CurrentContainerId,
|
||||
sendSplitToWorld: (item, amount) =>
|
||||
session.CurrentSession?.SendStackableSplitTo3D(item, amount),
|
||||
selectedObjectId: () => d.Selection.SelectedObjectId ?? 0u,
|
||||
|
|
@ -333,9 +331,10 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
amount),
|
||||
requestExternalContainer: guid =>
|
||||
{
|
||||
d.ExternalContainers.RequestOpen(guid);
|
||||
d.Inventory.ExternalContainers.RequestOpen(guid);
|
||||
},
|
||||
requestUse: selection.RequestUse);
|
||||
requestUse: selection.RequestUse,
|
||||
transactions: d.Inventory.Transactions);
|
||||
}
|
||||
|
||||
public RetainedUiComposition CreateRetainedUi(
|
||||
|
|
@ -372,7 +371,7 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
checkpoint(InteractionRetainedUiCompositionPoint.CursorAssetsCreated);
|
||||
|
||||
var characterSheet = new CharacterSheetProvider(
|
||||
d.Objects,
|
||||
d.Inventory.Objects,
|
||||
d.LocalPlayer,
|
||||
playerGuid: () => d.PlayerIdentity.ServerGuid,
|
||||
activeToonName: () => d.Settings.ActiveToonKey,
|
||||
|
|
@ -391,7 +390,7 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
MagicRuntime magic = MagicRuntime.Create(
|
||||
d.MagicCatalog,
|
||||
d.Spellbook,
|
||||
d.Objects,
|
||||
d.Inventory.Objects,
|
||||
selectedObject: () => d.Selection.SelectedObjectId,
|
||||
localPlayerId: () => d.PlayerIdentity.ServerGuid,
|
||||
accountName: () => late.Session.AccountName
|
||||
|
|
@ -530,7 +529,7 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
Magic: new MagicRuntimeBindings(
|
||||
d.Spellbook,
|
||||
magic.Casting,
|
||||
d.Objects,
|
||||
d.Inventory.Objects,
|
||||
() => d.PlayerIdentity.ServerGuid,
|
||||
d.MagicCatalog.Components,
|
||||
iconComposer.GetIcon,
|
||||
|
|
@ -571,7 +570,7 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
late.SelectionCamera.UiSnapshot),
|
||||
Indicators: new IndicatorRuntimeBindings(
|
||||
d.Spellbook,
|
||||
d.Objects,
|
||||
d.Inventory.Objects,
|
||||
() => d.PlayerIdentity.ServerGuid,
|
||||
() => d.LocalPlayer.GetAttribute(
|
||||
LocalPlayerState.AttributeKind.Strength)
|
||||
|
|
@ -581,13 +580,13 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
() => late.Session.CurrentSession?.RequestLinkStatusPing(),
|
||||
d.Window.Close),
|
||||
Toolbar: new ToolbarRuntimeBindings(
|
||||
d.Objects,
|
||||
() => d.Shortcuts.Items,
|
||||
d.Inventory.Objects,
|
||||
() => d.Inventory.Shortcuts.Items,
|
||||
iconComposer.GetIcon,
|
||||
iconComposer.GetDragIcon,
|
||||
guid => late.Session.TryUseItem(guid, d.Log),
|
||||
d.Combat,
|
||||
d.ItemMana,
|
||||
d.Inventory.ItemMana,
|
||||
d.CombatModeCommands.Toggle,
|
||||
itemInteraction,
|
||||
entry => late.Session.CurrentSession?.SendAddShortcut(entry),
|
||||
|
|
@ -596,10 +595,11 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
handler => d.Combat.HealthChanged += handler,
|
||||
handler => d.Combat.HealthChanged -= handler,
|
||||
late.Selection.ShouldShowHealth,
|
||||
guid => d.Objects.Get(guid)?.GetAppropriateName(),
|
||||
guid => d.Inventory.Objects.Get(guid)?.GetAppropriateName(),
|
||||
d.Combat.GetHealthPercent,
|
||||
d.Combat.HasHealth,
|
||||
guid => (uint)(d.Objects.Get(guid)?.StackSize ?? 0),
|
||||
guid =>
|
||||
(uint)(d.Inventory.Objects.Get(guid)?.StackSize ?? 0),
|
||||
guid => late.Session.CurrentSession?.SendQueryHealth(guid),
|
||||
guid => late.Session.CurrentSession?.SendQueryItemMana(guid),
|
||||
() => d.PlayerIdentity.ServerGuid,
|
||||
|
|
@ -610,7 +610,7 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
placement)),
|
||||
Character: new CharacterRuntimeBindings(characterSheet),
|
||||
Inventory: new InventoryRuntimeBindings(
|
||||
d.Objects,
|
||||
d.Inventory.Objects,
|
||||
() => d.PlayerIdentity.ServerGuid,
|
||||
iconComposer.GetIcon,
|
||||
iconComposer.GetDragIcon,
|
||||
|
|
@ -637,8 +637,8 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
itemInteraction,
|
||||
d.Selection),
|
||||
ExternalContainer: new ExternalContainerRuntimeBindings(
|
||||
d.ExternalContainers,
|
||||
d.Objects,
|
||||
d.Inventory.ExternalContainers,
|
||||
d.Inventory.Objects,
|
||||
iconComposer.GetIcon,
|
||||
iconComposer.GetDragIcon,
|
||||
itemInteraction,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using AcDream.App.Rendering;
|
|||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
using AcDream.App.UI.Testing;
|
||||
using AcDream.Core.Items;
|
||||
using AcDream.Core.Net;
|
||||
using AcDream.Core.Net.Messages;
|
||||
using AcDream.UI.Abstractions;
|
||||
|
|
@ -406,32 +407,6 @@ internal sealed class PlayerCharacterOptionsState
|
|||
public void Reset() => Options = PlayerDescriptionParser.CharacterOptions1.Default;
|
||||
}
|
||||
|
||||
internal sealed class ShortcutSnapshotState
|
||||
{
|
||||
private IReadOnlyList<AcDream.Core.Items.ShortcutEntry> _items =
|
||||
Array.Empty<AcDream.Core.Items.ShortcutEntry>();
|
||||
|
||||
public IReadOnlyList<AcDream.Core.Items.ShortcutEntry> Items
|
||||
{
|
||||
get => _items;
|
||||
set => _items = value ?? Array.Empty<AcDream.Core.Items.ShortcutEntry>();
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class DesiredComponentSnapshotState
|
||||
{
|
||||
private IReadOnlyList<(uint Id, uint Amount)> _items =
|
||||
Array.Empty<(uint Id, uint Amount)>();
|
||||
|
||||
public IReadOnlyList<(uint Id, uint Amount)> Items
|
||||
{
|
||||
get => _items;
|
||||
set => _items = value ?? Array.Empty<(uint Id, uint Amount)>();
|
||||
}
|
||||
|
||||
public void Clear() => _items = Array.Empty<(uint Id, uint Amount)>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Probe scripts are mounted in Phase 5; reveal/resource facts become valid in
|
||||
/// Phase 7. Calls remain inert and diagnostic until that exact owner binds.
|
||||
|
|
|
|||
|
|
@ -72,8 +72,7 @@ internal sealed record SessionPlayerDependencies(
|
|||
ViewportAspectState ViewportAspect,
|
||||
PlayerApproachCompletionState PlayerApproachCompletions,
|
||||
PlayerCharacterOptionsState CharacterOptions,
|
||||
ShortcutSnapshotState Shortcuts,
|
||||
DesiredComponentSnapshotState DesiredComponents,
|
||||
RuntimeInventoryState Inventory,
|
||||
PointerPositionState PointerPosition,
|
||||
DispatcherMovementInputSource MovementInput,
|
||||
IInputCaptureSource InputCapture,
|
||||
|
|
@ -88,8 +87,6 @@ internal sealed record SessionPlayerDependencies(
|
|||
RuntimeCommunicationState Communication,
|
||||
LocalPlayerState LocalPlayer,
|
||||
Spellbook Spellbook,
|
||||
ItemManaState ItemMana,
|
||||
ExternalContainerState ExternalContainers,
|
||||
TransferableResourceSlot<PortalTunnelPresentation> PortalTunnelFallback,
|
||||
Action<string> Log);
|
||||
|
||||
|
|
@ -802,16 +799,13 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
d.PlayerController,
|
||||
d.PlayerSkills,
|
||||
d.WorldOrigin,
|
||||
d.CharacterOptions,
|
||||
d.Shortcuts,
|
||||
d.DesiredComponents),
|
||||
d.CharacterOptions),
|
||||
new LiveSessionDomainRuntime(
|
||||
d.EntityObjects,
|
||||
d.LocalPlayer,
|
||||
d.Spellbook,
|
||||
d.Combat,
|
||||
d.ItemMana,
|
||||
d.ExternalContainers,
|
||||
d.Inventory,
|
||||
d.Communication),
|
||||
new LiveSessionUiRuntime(
|
||||
interaction.RetainedUi?.Runtime,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue