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:
parent
c557038353
commit
eeb0f6b45c
29 changed files with 3311 additions and 1073 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue