refactor(runtime): cut graphical host over to canonical root

Make every App composition phase borrow one GameRuntime, retire the duplicate view/event adapters, and dispose the root only after its graphical borrowers release. This preserves synchronous UI commands while giving shutdown one exact ownership ledger.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-26 19:06:09 +02:00
parent ecb9f79444
commit ce41efb9e5
29 changed files with 613 additions and 778 deletions

View file

@ -26,6 +26,7 @@ using AcDream.Core.Player;
using AcDream.Core.Social;
using AcDream.Core.Spells;
using AcDream.Core.World;
using AcDream.Runtime;
using AcDream.Runtime.Entities;
using AcDream.Runtime.Gameplay;
using AcDream.Runtime.Session;
@ -35,6 +36,7 @@ namespace AcDream.App.Composition;
internal sealed record SessionPlayerDependencies(
RuntimeOptions Options,
GameRuntime Runtime,
IWindow Window,
object DatLock,
RuntimeSettingsController Settings,
@ -49,8 +51,6 @@ internal sealed record SessionPlayerDependencies(
PhysicsDataCache PhysicsDataCache,
WorldGameState WorldGameState,
WorldEvents WorldEvents,
RuntimeActionState Actions,
RuntimeEntityObjectLifetime EntityObjects,
EntityClassificationCache ClassificationCache,
LiveEntityRuntimeSlot RuntimeSlot,
LiveEntityAnimationRuntimeView<LiveEntityAnimationState> AnimatedEntities,
@ -60,7 +60,6 @@ internal sealed record SessionPlayerDependencies(
RetailInboundEventDispatcher InboundEntityEvents,
DeferredLiveEntityMotionRuntimeBindings MotionBindings,
LocalPlayerIdentityState PlayerIdentity,
RuntimeLocalPlayerMovementState PlayerController,
LocalPlayerPhysicsHostSlot PlayerHost,
LocalPlayerModeState PlayerMode,
ChaseCameraInputState ChaseCameraInput,
@ -71,7 +70,6 @@ internal sealed record SessionPlayerDependencies(
LocalPlayerShadowState PlayerShadow,
ViewportAspectState ViewportAspect,
PlayerApproachCompletionState PlayerApproachCompletions,
RuntimeInventoryState Inventory,
PointerPositionState PointerPosition,
DispatcherMovementInputSource MovementInput,
IInputCaptureSource InputCapture,
@ -82,10 +80,24 @@ internal sealed record SessionPlayerDependencies(
MovementTruthDiagnosticController MovementDiagnostics,
CombatAttackOperationsSlot CombatAttackOperations,
CombatFeedbackSlot CombatFeedback,
RuntimeCommunicationState Communication,
RuntimeCharacterState Character,
TransferableResourceSlot<PortalTunnelPresentation> PortalTunnelFallback,
Action<string> Log);
Action<string> Log)
{
public RuntimeActionState Actions => Runtime.ActionOwner;
public RuntimeEntityObjectLifetime EntityObjects =>
Runtime.EntityObjects;
public RuntimeLocalPlayerMovementState PlayerController =>
Runtime.MovementOwner;
public RuntimeInventoryState Inventory => Runtime.InventoryOwner;
public RuntimeCommunicationState Communication =>
Runtime.CommunicationOwner;
public RuntimeCharacterState Character => Runtime.CharacterOwner;
}
internal sealed record SessionPlayerResult(
LandblockStreamer Streamer,
@ -430,11 +442,7 @@ internal sealed class SessionPlayerCompositionPhase
sealedDungeonCells,
d.Log);
var liveSessionLease = scope.Acquire(
"live-session controller",
static () => new LiveSessionController(),
static value => value.Dispose());
LiveSessionController liveSession = liveSessionLease.Resource;
LiveSessionController liveSession = d.Runtime.Session;
var liveSessionCommands = new LiveSessionCommandSurface();
var liveSessionSource = new LiveSessionAppSource(
liveSession,
@ -869,19 +877,9 @@ internal sealed class SessionPlayerCompositionPhase
"live combat-mode commands",
d.CombatModeCommands.BindOwned(combatCommand));
var gameRuntime = new CurrentGameRuntimeAdapter(
liveSession,
d.Runtime,
sessionHost,
liveSessionCommands,
d.PlayerIdentity,
d.EntityObjects,
d.Inventory,
d.Character,
d.Communication,
d.Actions,
d.PlayerController,
d.WorldEnvironment.Runtime,
live.WorldTransit,
d.UpdateClock,
live.SelectionInteractions);
bindings.Adopt("current game runtime adapter", gameRuntime);
bindings.Adopt(
@ -987,7 +985,6 @@ internal sealed class SessionPlayerCompositionPhase
_publication.PublishSessionPlayer(result);
streamerLease.Transfer();
liveSessionLease.Transfer();
teleportLease.Transfer();
gameplayActionsLease?.Transfer();
componentLifecycleLease.Transfer();