refactor(runtime): own combat and magic intent
Move attack build/repeat state, combat-mode policy, authoritative auto-target transitions, and spell-cast intent beneath RuntimeActionState. Keep App as the input, world-query, DAT-policy, transport, and presentation adapter while preserving retail request and busy ordering. Add direct/graphical parity, reset, failure, and instance-isolation coverage. Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
parent
81b31857c6
commit
20df9d155d
49 changed files with 1949 additions and 634 deletions
|
|
@ -45,7 +45,9 @@ internal sealed record InteractionRetainedUiDependencies(
|
|||
InputDispatcher? InputDispatcher,
|
||||
RuntimeSettingsController Settings,
|
||||
RuntimeActionState Actions,
|
||||
ICombatAttackOperations CombatAttackOperations,
|
||||
IRuntimeCombatAttackOperations CombatAttackOperations,
|
||||
RuntimeCombatTargetOperationsSlot CombatTargetOperations,
|
||||
RuntimeSpellCastOperationsSlot SpellCastOperations,
|
||||
RuntimeInventoryState Inventory,
|
||||
MagicCatalog MagicCatalog,
|
||||
RuntimeCharacterState Character,
|
||||
|
|
@ -70,14 +72,13 @@ internal sealed record RetainedUiComposition(
|
|||
VitalsVM Vitals,
|
||||
ChatVM Chat,
|
||||
CharacterSheetProvider CharacterSheet,
|
||||
MagicRuntime Magic,
|
||||
FrameScreenshotController? Screenshots);
|
||||
|
||||
internal sealed record InteractionRetainedUiResult(
|
||||
CombatAttackController CombatAttack,
|
||||
CombatTargetController CombatTarget,
|
||||
RuntimeCombatAttackState CombatAttack,
|
||||
ExternalContainerLifecycleController ExternalContainerLifecycle,
|
||||
ItemInteractionController ItemInteraction,
|
||||
MagicRuntime Magic,
|
||||
RetainedUiComposition? RetainedUi,
|
||||
InteractionUiLateBindings LateBindings);
|
||||
|
||||
|
|
@ -89,16 +90,15 @@ internal interface IGameWindowInteractionRetainedUiPublication
|
|||
internal enum InteractionRetainedUiCompositionPoint
|
||||
{
|
||||
LateBindingsCreated,
|
||||
CombatAttackCreated,
|
||||
CombatTargetCreated,
|
||||
ExternalContainerLifecycleCreated,
|
||||
ItemInteractionCreated,
|
||||
MagicRuntimeCreated,
|
||||
RetainedUiDisabled,
|
||||
UiHostAcquired,
|
||||
InputCaptureBound,
|
||||
CursorAssetsCreated,
|
||||
CharacterSheetCreated,
|
||||
MagicRuntimeCreated,
|
||||
MouseInputWired,
|
||||
KeyboardInputWired,
|
||||
UiAssetsCreated,
|
||||
|
|
@ -225,10 +225,7 @@ internal sealed class InteractionUiLateBindings : IDisposable
|
|||
|
||||
internal interface IInteractionRetainedUiCompositionFactory
|
||||
{
|
||||
CombatAttackController CreateCombatAttack(
|
||||
InteractionRetainedUiDependencies dependencies);
|
||||
|
||||
CombatTargetController CreateCombatTarget(
|
||||
IDisposable BindCombatTarget(
|
||||
InteractionRetainedUiDependencies dependencies,
|
||||
DeferredSelectionUiAuthority selection);
|
||||
|
||||
|
|
@ -240,12 +237,18 @@ internal interface IInteractionRetainedUiCompositionFactory
|
|||
InteractionRetainedUiDependencies dependencies,
|
||||
InteractionUiLateBindings lateBindings);
|
||||
|
||||
MagicRuntime CreateMagicRuntime(
|
||||
InteractionRetainedUiDependencies dependencies,
|
||||
InteractionUiLateBindings lateBindings,
|
||||
ItemInteractionController itemInteraction);
|
||||
|
||||
RetainedUiComposition CreateRetainedUi(
|
||||
InteractionRetainedUiDependencies dependencies,
|
||||
InteractionUiLateBindings lateBindings,
|
||||
RetailUiRuntimeLease lease,
|
||||
CombatAttackController combatAttack,
|
||||
RuntimeCombatAttackState combatAttack,
|
||||
ItemInteractionController itemInteraction,
|
||||
MagicRuntime magic,
|
||||
Action<InteractionRetainedUiCompositionPoint> checkpoint);
|
||||
|
||||
void Release(IDisposable resource);
|
||||
|
|
@ -254,19 +257,13 @@ internal interface IInteractionRetainedUiCompositionFactory
|
|||
internal sealed class RetailInteractionRetainedUiCompositionFactory
|
||||
: IInteractionRetainedUiCompositionFactory
|
||||
{
|
||||
public CombatAttackController CreateCombatAttack(
|
||||
InteractionRetainedUiDependencies d) =>
|
||||
new(d.Actions.Combat, d.CombatAttackOperations);
|
||||
|
||||
public CombatTargetController CreateCombatTarget(
|
||||
public IDisposable BindCombatTarget(
|
||||
InteractionRetainedUiDependencies d,
|
||||
DeferredSelectionUiAuthority selection) =>
|
||||
new(
|
||||
d.Actions.Combat,
|
||||
d.Actions.Selection,
|
||||
d.CombatTargetOperations.BindOwned(new LiveCombatTargetOperations(
|
||||
autoTarget: () => d.Settings.Gameplay.AutoTarget,
|
||||
selectClosestTarget: () =>
|
||||
selection.SelectClosestCombatTarget(showToast: false));
|
||||
selection.SelectClosestCombatTarget(showToast: false)));
|
||||
|
||||
public ExternalContainerLifecycleController CreateExternalContainerLifecycle(
|
||||
InteractionRetainedUiDependencies d,
|
||||
|
|
@ -339,12 +336,38 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
requestUse: selection.RequestUse);
|
||||
}
|
||||
|
||||
public MagicRuntime CreateMagicRuntime(
|
||||
InteractionRetainedUiDependencies d,
|
||||
InteractionUiLateBindings late,
|
||||
ItemInteractionController itemInteraction) =>
|
||||
MagicRuntime.Create(
|
||||
d.MagicCatalog,
|
||||
d.Actions.SpellCast,
|
||||
d.SpellCastOperations,
|
||||
d.Inventory.Objects,
|
||||
localPlayerId: () => d.PlayerIdentity.ServerGuid,
|
||||
accountName: () => late.Session.AccountName
|
||||
?? d.Options.LiveUser
|
||||
?? string.Empty,
|
||||
stopCompletely: d.CombatAttackOperations.PrepareAttackRequest,
|
||||
sendUntargeted: spellId =>
|
||||
late.Session.CurrentSession?.SendCastUntargetedSpell(spellId),
|
||||
sendTargeted: (target, spellId) =>
|
||||
late.Session.CurrentSession?.SendCastTargetedSpell(
|
||||
target,
|
||||
spellId),
|
||||
displayMessage:
|
||||
text => d.Communication.Chat.OnSystemMessage(text, 0x1Au),
|
||||
incrementBusy: itemInteraction.IncrementBusyCount,
|
||||
canSend: () => late.Session.IsInWorld);
|
||||
|
||||
public RetainedUiComposition CreateRetainedUi(
|
||||
InteractionRetainedUiDependencies d,
|
||||
InteractionUiLateBindings late,
|
||||
RetailUiRuntimeLease lease,
|
||||
CombatAttackController combatAttack,
|
||||
RuntimeCombatAttackState combatAttack,
|
||||
ItemInteractionController itemInteraction,
|
||||
MagicRuntime magic,
|
||||
Action<InteractionRetainedUiCompositionPoint> checkpoint)
|
||||
{
|
||||
IDisposable? inputCapture = null;
|
||||
|
|
@ -404,27 +427,6 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
credits));
|
||||
checkpoint(InteractionRetainedUiCompositionPoint.CharacterSheetCreated);
|
||||
|
||||
MagicRuntime magic = MagicRuntime.Create(
|
||||
d.MagicCatalog,
|
||||
d.Character.Spellbook,
|
||||
d.Inventory.Objects,
|
||||
selectedObject: () =>
|
||||
d.Actions.Selection.SelectedObjectId,
|
||||
localPlayerId: () => d.PlayerIdentity.ServerGuid,
|
||||
accountName: () => late.Session.AccountName
|
||||
?? d.Options.LiveUser
|
||||
?? string.Empty,
|
||||
stopCompletely: d.CombatAttackOperations.PrepareAttackRequest,
|
||||
sendUntargeted: spellId =>
|
||||
late.Session.CurrentSession?.SendCastUntargetedSpell(spellId),
|
||||
sendTargeted: (target, spellId) =>
|
||||
late.Session.CurrentSession?.SendCastTargetedSpell(target, spellId),
|
||||
displayMessage:
|
||||
text => d.Communication.Chat.OnSystemMessage(text, 0x1Au),
|
||||
incrementBusy: itemInteraction.IncrementBusyCount,
|
||||
canSend: () => late.Session.IsInWorld);
|
||||
checkpoint(InteractionRetainedUiCompositionPoint.MagicRuntimeCreated);
|
||||
|
||||
uint MagicSkillLevel(MagicSchool school)
|
||||
{
|
||||
static uint SkillId(MagicSchool value) => value switch
|
||||
|
|
@ -717,7 +719,6 @@ internal sealed class RetailInteractionRetainedUiCompositionFactory
|
|||
vitals,
|
||||
chat,
|
||||
characterSheet,
|
||||
magic,
|
||||
screenshots);
|
||||
}
|
||||
catch (Exception failure)
|
||||
|
|
@ -805,15 +806,12 @@ internal sealed class InteractionRetainedUiCompositionPhase
|
|||
_dependencies.SelectionCameraFactory(late.SelectionViewPlane));
|
||||
Fault(InteractionRetainedUiCompositionPoint.LateBindingsCreated);
|
||||
|
||||
var attackLease = scope.Acquire(
|
||||
"combat attack controller",
|
||||
() => _factory.CreateCombatAttack(_dependencies),
|
||||
_factory.Release);
|
||||
Fault(InteractionRetainedUiCompositionPoint.CombatAttackCreated);
|
||||
var targetLease = scope.Acquire(
|
||||
"combat target controller",
|
||||
() => _factory.CreateCombatTarget(_dependencies, late.Selection),
|
||||
_factory.Release);
|
||||
IDisposable combatTargetBinding = _factory.BindCombatTarget(
|
||||
_dependencies,
|
||||
late.Selection);
|
||||
late.AdoptLateOwnerBinding(
|
||||
"combat-target operations",
|
||||
combatTargetBinding);
|
||||
Fault(InteractionRetainedUiCompositionPoint.CombatTargetCreated);
|
||||
var externalLease = scope.Acquire(
|
||||
"external container lifecycle",
|
||||
|
|
@ -827,6 +825,14 @@ internal sealed class InteractionRetainedUiCompositionPhase
|
|||
() => _factory.CreateItemInteraction(_dependencies, late),
|
||||
_factory.Release);
|
||||
Fault(InteractionRetainedUiCompositionPoint.ItemInteractionCreated);
|
||||
var magicLease = scope.Acquire(
|
||||
"magic runtime",
|
||||
() => _factory.CreateMagicRuntime(
|
||||
_dependencies,
|
||||
late,
|
||||
itemLease.Resource),
|
||||
_factory.Release);
|
||||
Fault(InteractionRetainedUiCompositionPoint.MagicRuntimeCreated);
|
||||
|
||||
var uiLease = scope.Own(
|
||||
"retained UI runtime lease",
|
||||
|
|
@ -839,8 +845,9 @@ internal sealed class InteractionRetainedUiCompositionPhase
|
|||
_dependencies,
|
||||
late,
|
||||
_retainedUiLease,
|
||||
attackLease.Resource,
|
||||
_dependencies.Actions.CombatAttack,
|
||||
itemLease.Resource,
|
||||
magicLease.Resource,
|
||||
Fault);
|
||||
}
|
||||
else
|
||||
|
|
@ -849,18 +856,17 @@ internal sealed class InteractionRetainedUiCompositionPhase
|
|||
}
|
||||
|
||||
var result = new InteractionRetainedUiResult(
|
||||
attackLease.Resource,
|
||||
targetLease.Resource,
|
||||
_dependencies.Actions.CombatAttack,
|
||||
externalLease.Resource,
|
||||
itemLease.Resource,
|
||||
magicLease.Resource,
|
||||
retainedUi,
|
||||
late);
|
||||
_publication.PublishInteractionRetainedUi(result);
|
||||
lateLease.Transfer();
|
||||
attackLease.Transfer();
|
||||
targetLease.Transfer();
|
||||
externalLease.Transfer();
|
||||
itemLease.Transfer();
|
||||
magicLease.Transfer();
|
||||
uiLease.Transfer();
|
||||
Fault(InteractionRetainedUiCompositionPoint.ResultPublished);
|
||||
scope.Complete();
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ internal sealed record SessionPlayerDependencies(
|
|||
WorldSceneDebugState WorldSceneDebugState,
|
||||
RuntimeDiagnosticCommandSlot RuntimeDiagnosticCommands,
|
||||
LiveCombatModeCommandSlot CombatModeCommands,
|
||||
RuntimeCombatModeOperationsSlot CombatModeOperations,
|
||||
HostQuiescenceGate HostQuiescence,
|
||||
PhysicsEngine PhysicsEngine,
|
||||
PhysicsDataCache PhysicsDataCache,
|
||||
|
|
@ -514,7 +515,7 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
d.PhysicsEngine,
|
||||
content.Dats,
|
||||
content.AnimationLoader,
|
||||
interaction.CombatTarget,
|
||||
d.Actions.CombatTarget,
|
||||
d.WorldOrigin,
|
||||
d.TeleportSink,
|
||||
d.PlayerController,
|
||||
|
|
@ -804,7 +805,7 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
interaction.RetainedUi?.Runtime,
|
||||
vitals,
|
||||
interaction.RetainedUi?.CharacterSheet,
|
||||
interaction.RetainedUi?.Magic,
|
||||
interaction.Magic,
|
||||
live.PaperdollPresenter),
|
||||
new LiveSessionInteractionRuntime(
|
||||
d.Settings,
|
||||
|
|
@ -850,14 +851,18 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
Action<string>? debugToast = d.SettingsDevTools.DevTools is { } devOwner
|
||||
? message => devOwner.Debug.AddToast(message)
|
||||
: null;
|
||||
var combatCommand = new LiveCombatModeCommandController(
|
||||
var combatModeOperations = new LiveCombatModeOperations(
|
||||
new LiveSessionCombatModeAuthority(sessionHost),
|
||||
new LocalPlayerCombatEquipmentSource(
|
||||
d.EntityObjects.Objects,
|
||||
d.PlayerIdentity),
|
||||
d.Actions.Combat,
|
||||
new ItemInteractionCombatModeIntentSink(
|
||||
interaction.ItemInteraction),
|
||||
interaction.ItemInteraction));
|
||||
bindings.Adopt(
|
||||
"runtime combat-mode operations",
|
||||
d.CombatModeOperations.BindOwned(combatModeOperations));
|
||||
var combatCommand = new RuntimeCombatModeCommandAdapter(
|
||||
d.Actions.CombatMode,
|
||||
d.Log,
|
||||
debugToast,
|
||||
text => d.Communication.Chat.OnSystemMessage(text, 0x1Au));
|
||||
|
|
@ -879,8 +884,7 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
worldReveal,
|
||||
d.UpdateClock,
|
||||
live.SelectionInteractions,
|
||||
gameplayInput,
|
||||
combatCommand);
|
||||
gameplayInput);
|
||||
bindings.Adopt("current game runtime adapter", gameRuntime);
|
||||
bindings.Adopt(
|
||||
"retained-UI game runtime commands",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue