refactor(runtime): own canonical action state
Move selection, combat, and interaction target mode under one Runtime owner; make plugins, retained UI, session routing, and typed runtime views borrow its exact children; and add failure-safe reset, instance isolation, source ownership, and normalized checkpoint coverage without changing retail ordering. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
bb45afef33
commit
b298f99f91
38 changed files with 711 additions and 93 deletions
|
|
@ -44,9 +44,8 @@ internal sealed record InteractionRetainedUiDependencies(
|
|||
RetainedUiInputCaptureSlot RetainedInputCapture,
|
||||
InputDispatcher? InputDispatcher,
|
||||
RuntimeSettingsController Settings,
|
||||
CombatState Combat,
|
||||
RuntimeActionState Actions,
|
||||
ICombatAttackOperations CombatAttackOperations,
|
||||
SelectionState Selection,
|
||||
RuntimeInventoryState Inventory,
|
||||
MagicCatalog MagicCatalog,
|
||||
RuntimeCharacterState Character,
|
||||
|
|
@ -257,14 +256,14 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
{
|
||||
public CombatAttackController CreateCombatAttack(
|
||||
InteractionRetainedUiDependencies d) =>
|
||||
new(d.Combat, d.CombatAttackOperations);
|
||||
new(d.Actions.Combat, d.CombatAttackOperations);
|
||||
|
||||
public CombatTargetController CreateCombatTarget(
|
||||
InteractionRetainedUiDependencies d,
|
||||
DeferredSelectionUiAuthority selection) =>
|
||||
new(
|
||||
d.Combat,
|
||||
d.Selection,
|
||||
d.Actions.Combat,
|
||||
d.Actions.Selection,
|
||||
autoTarget: () => d.Settings.Gameplay.AutoTarget,
|
||||
selectClosestTarget: () =>
|
||||
selection.SelectClosestCombatTarget(showToast: false));
|
||||
|
|
@ -286,6 +285,7 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
return new ItemInteractionController(
|
||||
d.Inventory.Objects,
|
||||
d.Inventory.Transactions,
|
||||
d.Actions.Interaction,
|
||||
playerGuid: () => d.PlayerIdentity.ServerGuid,
|
||||
sendUse: null,
|
||||
sendExamine: guid => session.CurrentSession?.SendAppraise(guid),
|
||||
|
|
@ -304,8 +304,8 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
d.PlayerMode.IsPlayerMode
|
||||
&& d.PlayerController.Controller is { IsAirborne: false },
|
||||
inNonCombatMode: () =>
|
||||
d.Combat.CurrentMode == CombatMode.NonCombat,
|
||||
combatState: d.Combat,
|
||||
d.Actions.Combat.CurrentMode == CombatMode.NonCombat,
|
||||
combatState: d.Actions.Combat,
|
||||
sendChangeCombatMode: mode =>
|
||||
session.CurrentSession?.SendChangeCombatMode(mode),
|
||||
isComponentPack: d.MagicCatalog.IsComponentPack,
|
||||
|
|
@ -316,7 +316,8 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
d.Inventory.ExternalContainers.CurrentContainerId,
|
||||
sendSplitToWorld: (item, amount) =>
|
||||
session.CurrentSession?.SendStackableSplitTo3D(item, amount),
|
||||
selectedObjectId: () => d.Selection.SelectedObjectId ?? 0u,
|
||||
selectedObjectId: () =>
|
||||
d.Actions.Selection.SelectedObjectId ?? 0u,
|
||||
stackSplitQuantity: d.StackSplitQuantity,
|
||||
systemMessage:
|
||||
text => d.Communication.Chat.OnSystemMessage(text, 0x1Au),
|
||||
|
|
@ -351,7 +352,9 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
try
|
||||
{
|
||||
VitalsVM vitals = d.ExistingVitals
|
||||
?? new VitalsVM(d.Combat, d.Character.LocalPlayer);
|
||||
?? new VitalsVM(
|
||||
d.Actions.Combat,
|
||||
d.Character.LocalPlayer);
|
||||
UiHost host = lease.AcquireHost(
|
||||
() => new UiHost(
|
||||
d.Gl,
|
||||
|
|
@ -367,7 +370,8 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
itemInteraction,
|
||||
worldTargetProvider: () =>
|
||||
late.Selection.PickAtCursor(includeSelf: true) ?? 0u,
|
||||
combatModeProvider: () => d.Combat.CurrentMode);
|
||||
combatModeProvider: () =>
|
||||
d.Actions.Combat.CurrentMode);
|
||||
var cursorManager = new RetailCursorManager(d.Dats, d.DatLock);
|
||||
checkpoint(InteractionRetainedUiCompositionPoint.CursorAssetsCreated);
|
||||
|
||||
|
|
@ -404,7 +408,8 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
d.MagicCatalog,
|
||||
d.Character.Spellbook,
|
||||
d.Inventory.Objects,
|
||||
selectedObject: () => d.Selection.SelectedObjectId,
|
||||
selectedObject: () =>
|
||||
d.Actions.Selection.SelectedObjectId,
|
||||
localPlayerId: () => d.PlayerIdentity.ServerGuid,
|
||||
accountName: () => late.Session.AccountName
|
||||
?? d.Options.LiveUser
|
||||
|
|
@ -533,10 +538,10 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
Chat: new ChatRuntimeBindings(chat, () => late.Session.Commands),
|
||||
Radar: new RadarRuntimeBindings(
|
||||
late.Radar.Snapshot,
|
||||
d.Selection,
|
||||
d.Actions.Selection,
|
||||
d.Settings.SetUiLocked),
|
||||
Combat: new CombatRuntimeBindings(
|
||||
d.Combat,
|
||||
d.Actions.Combat,
|
||||
combatAttack,
|
||||
() => d.Settings.Gameplay,
|
||||
d.Settings.SetCombatGameplay),
|
||||
|
|
@ -550,11 +555,13 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
iconComposer.GetDragIcon,
|
||||
iconComposer.GetSpellIcon,
|
||||
iconComposer.GetSpellComponentIcon,
|
||||
d.Selection,
|
||||
d.Actions.Selection,
|
||||
d.MagicCatalog.GetSpellLevel,
|
||||
magic.GetExamineComponents,
|
||||
MagicSkillLevel,
|
||||
guid => d.Selection.Select(guid, SelectionChangeSource.Inventory),
|
||||
guid => d.Actions.Selection.Select(
|
||||
guid,
|
||||
SelectionChangeSource.Inventory),
|
||||
guid => late.Session.TryUseItem(guid, d.Log),
|
||||
(tab, position, spellId) =>
|
||||
late.GameRuntime.AddFavorite(tab, position, spellId),
|
||||
|
|
@ -574,7 +581,7 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
() => 1.0,
|
||||
() => d.Settings.DisplayPreview.ShowFps),
|
||||
VividTarget: new VividTargetRuntimeBindings(
|
||||
d.Selection,
|
||||
d.Actions.Selection,
|
||||
() => d.PlayerIdentity.ServerGuid,
|
||||
() => d.Settings.Gameplay.VividTargetingIndicator,
|
||||
late.Selection.ResolveVividTargetInfo,
|
||||
|
|
@ -596,19 +603,19 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
iconComposer.GetIcon,
|
||||
iconComposer.GetDragIcon,
|
||||
guid => late.Session.TryUseItem(guid, d.Log),
|
||||
d.Combat,
|
||||
d.Actions.Combat,
|
||||
d.Inventory.ItemMana,
|
||||
d.CombatModeCommands.Toggle,
|
||||
itemInteraction,
|
||||
entry => late.GameRuntime.AddShortcut(entry),
|
||||
index => late.GameRuntime.RemoveShortcut(index),
|
||||
d.Selection,
|
||||
handler => d.Combat.HealthChanged += handler,
|
||||
handler => d.Combat.HealthChanged -= handler,
|
||||
d.Actions.Selection,
|
||||
handler => d.Actions.Combat.HealthChanged += handler,
|
||||
handler => d.Actions.Combat.HealthChanged -= handler,
|
||||
late.Selection.ShouldShowHealth,
|
||||
guid => d.Inventory.Objects.Get(guid)?.GetAppropriateName(),
|
||||
d.Combat.GetHealthPercent,
|
||||
d.Combat.HasHealth,
|
||||
d.Actions.Combat.GetHealthPercent,
|
||||
d.Actions.Combat.HasHealth,
|
||||
guid =>
|
||||
(uint)(d.Inventory.Objects.Get(guid)?.StackSize ?? 0),
|
||||
guid => late.Session.CurrentSession?.SendQueryHealth(guid),
|
||||
|
|
@ -646,14 +653,14 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
target,
|
||||
amount),
|
||||
itemInteraction,
|
||||
d.Selection),
|
||||
d.Actions.Selection),
|
||||
ExternalContainer: new ExternalContainerRuntimeBindings(
|
||||
d.Inventory.ExternalContainers,
|
||||
d.Inventory.Objects,
|
||||
iconComposer.GetIcon,
|
||||
iconComposer.GetDragIcon,
|
||||
itemInteraction,
|
||||
d.Selection,
|
||||
d.Actions.Selection,
|
||||
guid => late.Session.CurrentSession?.SendUse(guid),
|
||||
(item, container, placement) =>
|
||||
late.Session.CurrentSession?.SendPutItemInContainer(
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ internal sealed record SessionPlayerDependencies(
|
|||
PhysicsDataCache PhysicsDataCache,
|
||||
WorldGameState WorldGameState,
|
||||
WorldEvents WorldEvents,
|
||||
SelectionState Selection,
|
||||
RuntimeActionState Actions,
|
||||
RuntimeEntityObjectLifetime EntityObjects,
|
||||
EntityClassificationCache ClassificationCache,
|
||||
LiveEntityRuntimeSlot RuntimeSlot,
|
||||
|
|
@ -80,7 +80,6 @@ internal sealed record SessionPlayerDependencies(
|
|||
UpdateFrameClock UpdateClock,
|
||||
MovementTruthDiagnosticController MovementDiagnostics,
|
||||
CombatAttackOperationsSlot CombatAttackOperations,
|
||||
CombatState Combat,
|
||||
CombatFeedbackSlot CombatFeedback,
|
||||
RuntimeCommunicationState Communication,
|
||||
RuntimeCharacterState Character,
|
||||
|
|
@ -326,7 +325,7 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
d.DatLock);
|
||||
var worldQuiescence = new WorldGenerationQuiescence(
|
||||
live.WorldAvailability,
|
||||
d.Selection,
|
||||
d.Actions.Selection,
|
||||
live.WorldState,
|
||||
guid => live.LiveEntities.TryGetProjectionKey(
|
||||
guid,
|
||||
|
|
@ -455,7 +454,7 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
live.EntityEffects,
|
||||
live.RemoteTeleport,
|
||||
live.SelectionInteractions,
|
||||
d.Selection,
|
||||
d.Actions.Selection,
|
||||
d.AnimatedEntities,
|
||||
d.RemoteMovementObservations,
|
||||
d.TranslucencyFades,
|
||||
|
|
@ -563,9 +562,9 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
"combat attack operations",
|
||||
d.CombatAttackOperations.BindOwned(
|
||||
new LiveCombatAttackOperations(
|
||||
d.Combat,
|
||||
d.Actions.Combat,
|
||||
new CombatAttackTargetSource(
|
||||
d.Selection,
|
||||
d.Actions.Selection,
|
||||
live.LiveEntities,
|
||||
d.EntityObjects.Objects,
|
||||
d.PlayerIdentity),
|
||||
|
|
@ -798,7 +797,7 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
new LiveSessionDomainRuntime(
|
||||
d.EntityObjects,
|
||||
d.Character,
|
||||
d.Combat,
|
||||
d.Actions,
|
||||
d.Inventory,
|
||||
d.Communication),
|
||||
new LiveSessionUiRuntime(
|
||||
|
|
@ -856,7 +855,7 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
new LocalPlayerCombatEquipmentSource(
|
||||
d.EntityObjects.Objects,
|
||||
d.PlayerIdentity),
|
||||
d.Combat,
|
||||
d.Actions.Combat,
|
||||
new ItemInteractionCombatModeIntentSink(
|
||||
interaction.ItemInteraction),
|
||||
d.Log,
|
||||
|
|
@ -875,10 +874,10 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
d.Inventory,
|
||||
d.Character,
|
||||
d.Communication,
|
||||
d.Actions,
|
||||
d.PlayerController,
|
||||
worldReveal,
|
||||
d.UpdateClock,
|
||||
d.Selection,
|
||||
live.SelectionInteractions,
|
||||
gameplayInput,
|
||||
combatCommand);
|
||||
|
|
@ -940,7 +939,7 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
GameplayInputActionRouter gameplayActions =
|
||||
GameplayInputActionRouter.Create(
|
||||
dispatcher,
|
||||
d.Combat,
|
||||
d.Actions.Combat,
|
||||
targets,
|
||||
d.HostQuiescence,
|
||||
d.Log);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue