Files

96 lines
3.2 KiB
C#

using System;
namespace AibisDream
{
public enum GameSessionPhase
{
MainMenu,
Starting,
Transitioning,
Restoring,
Playing,
ReturningToMenu
}
/// <summary>
/// 单次游戏会话的纯状态模型。它不执行流程,也不发送全局事件。
/// </summary>
public sealed class GameSession
{
public GameSessionPhase Phase { get; private set; } = GameSessionPhase.MainMenu;
public TalkSceneSO CurrentTalkScene { get; private set; }
public bool IsPaused { get; private set; }
public bool IsDialogueActive { get; private set; }
public bool IsActive => Phase != GameSessionPhase.MainMenu;
public bool IsBusy => Phase is GameSessionPhase.Starting
or GameSessionPhase.Transitioning
or GameSessionPhase.Restoring
or GameSessionPhase.ReturningToMenu;
public bool CanPause => Phase == GameSessionPhase.Playing && !IsPaused;
public bool CanResume => Phase == GameSessionPhase.Playing && IsPaused;
public bool CanAdvanceDialogue => Phase == GameSessionPhase.Playing && IsDialogueActive && !IsPaused;
internal bool TryTransitionTo(GameSessionPhase next, out string error)
{
if (Phase == next)
{
error = null;
return true;
}
if (!IsTransitionAllowed(Phase, next))
{
error = $"Illegal game session transition: {Phase} -> {next}";
return false;
}
Phase = next;
error = null;
return true;
}
internal void SetCurrentTalkScene(TalkSceneSO scene)
{
CurrentTalkScene = scene;
}
internal void SetPaused(bool paused)
{
IsPaused = paused;
}
internal void SetDialogueActive(bool active)
{
IsDialogueActive = active;
}
internal void ResetRuntimeState()
{
CurrentTalkScene = null;
IsPaused = false;
IsDialogueActive = false;
}
private static bool IsTransitionAllowed(GameSessionPhase current, GameSessionPhase next)
{
return current switch
{
GameSessionPhase.MainMenu => next is GameSessionPhase.Starting or GameSessionPhase.Restoring,
GameSessionPhase.Starting => next is GameSessionPhase.Playing or GameSessionPhase.ReturningToMenu,
GameSessionPhase.Transitioning => next is GameSessionPhase.Playing or GameSessionPhase.ReturningToMenu,
GameSessionPhase.Restoring => next is GameSessionPhase.Playing
or GameSessionPhase.MainMenu
or GameSessionPhase.ReturningToMenu,
GameSessionPhase.Playing => next is GameSessionPhase.Transitioning
or GameSessionPhase.Restoring
or GameSessionPhase.ReturningToMenu,
GameSessionPhase.ReturningToMenu => next == GameSessionPhase.MainMenu,
_ => throw new ArgumentOutOfRangeException(nameof(current), current, null)
};
}
}
}