refactor(runtime): extract local teleport and player mode

Move local teleport, player-mode, animation, shadow, and sealed-dungeon lifetimes out of GameWindow. Make player-mode entry transactional and isolate approach completions by controller lifetime and approach generation so stale callbacks cannot affect replacements.

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Erik 2026-07-22 02:50:15 +02:00
parent c557038353
commit eeb0f6b45c
29 changed files with 3311 additions and 1073 deletions

View file

@ -1,4 +1,5 @@
using AcDream.Core.Physics;
using AcDream.App.Physics;
namespace AcDream.App.Input;
@ -29,6 +30,20 @@ internal sealed class LocalPlayerControllerSlot : ILocalPlayerControllerSource
public PlayerMovementController? Controller { get; set; }
}
internal interface ILocalPlayerPhysicsHostSource
{
EntityPhysicsHost? Host { get; }
}
/// <summary>
/// The one mutable local physics-host slot. Player-mode lifecycle owns
/// assignment; teleport and update owners receive the read-only seam.
/// </summary>
internal sealed class LocalPlayerPhysicsHostSlot : ILocalPlayerPhysicsHostSource
{
public EntityPhysicsHost? Host { get; set; }
}
internal interface ILocalPlayerModeSource
{
bool IsPlayerMode { get; }
@ -50,3 +65,59 @@ internal sealed class LocalPlayerModeState : ILocalPlayerModeSource
ChaseModeEverEntered = false;
}
}
/// <summary>
/// Session-scoped server-authoritative movement skills. Player-description
/// delivery and player-mode construction share this owner so rebuilding the
/// local physics controller cannot fall back to stale defaults.
/// </summary>
internal sealed class LocalPlayerSkillState
{
public int RunSkill { get; private set; } = -1;
public int JumpSkill { get; private set; } = -1;
public bool IsComplete => RunSkill >= 0 && JumpSkill >= 0;
public void Update(
int runSkill,
int jumpSkill,
PlayerMovementController? controller)
{
if (runSkill >= 0)
RunSkill = runSkill;
if (jumpSkill >= 0)
JumpSkill = jumpSkill;
ApplyTo(controller);
}
public bool ApplyTo(PlayerMovementController? controller)
{
if (controller is null || !IsComplete)
return false;
controller.SetCharacterSkills(RunSkill, JumpSkill);
return true;
}
public void ResetSession()
{
RunSkill = -1;
JumpSkill = -1;
}
}
internal interface IViewportAspectSource
{
float Aspect { get; }
}
/// <summary>Framebuffer aspect published by the window host.</summary>
internal sealed class ViewportAspectState : IViewportAspectSource
{
public float Aspect { get; private set; } = 16f / 9f;
public void Update(int width, int height)
{
if (width > 0 && height > 0)
Aspect = width / (float)height;
}
}