using System.Collections.Generic;
using Core;
using Godot;
using Models;
///
/// 游戏主控制节点(MVC 的桥接层)
/// 设计说明:
/// 1) 负责初始化 GameSession,并把输入/信号转交给 Controller/System。
/// 2) 仅做“流程调度”,不直接计算复杂数值,避免逻辑堆积。
/// 注意事项:
/// - View 与 Model 的绑定应逐步迁移到独立 View 脚本,避免在此类膨胀。
/// 未来扩展:
/// - 可拆分为 SceneRoot + UIController + DebugController,分层管理。
///
public partial class GameManager : Node {
// --- Signals ---
///
/// 阶段变更信号
///
/// 阶段枚举的整数值
[Signal]
public delegate void PhaseChangedEventHandler(int phase); // int cast of GamePhase
///
/// 回合变更信号
///
/// 当前回合数
[Signal]
public delegate void TurnChangedEventHandler(int turn);
///
/// 双倍大小的箭头光标资源
///
public static readonly Resource Arrow2X =
ResourceLoader.Load("res://temp_res/kenney_ui-pack-space-expansion/PNG/Extra/Double/cursor_f.png");
///
/// 最大回合数
///
[Export] public int MaxTurns = 30;
///
/// 指示当前是否处于教程模式
///
public static bool IsTutorial { get; private set; }
///
/// 下一个场景的路径
///
public static string NextScene { get; set; } = null;
// --- Global State ---
///
/// 游戏会话实例
///
public GameSession Session { get; private set; }
///
/// 当前游戏状态
///
public GameState State => Session?.State;
///
/// 游戏控制器
///
public GameController Controller { get; private set; }
///
/// 当前游戏阶段
///
public GamePhase CurrentPhase => State?.Turn.Phase ?? GamePhase.Planning;
///
/// 当前回合数
///
public int CurrentTurn => State?.Turn.CurrentTurn ?? 1;
// --- Domain Model ---
///
/// 导师模型
///
public MentorModel Mentor => State?.Roster.Mentor;
///
/// 学生列表
///
public List Students => State?.Roster.Students;
///
/// 当前活动任务列表
///
public List ActiveTasks => State?.Tasks.ActiveTasks;
///
/// 经济状态
///
public EconomyState Economy => State?.Economy;
// Singleton instance access (if needed, though Godot uses node paths)
///
/// 单例实例
///
public static GameManager Instance { get; private set; }
///
/// 进入场景树时调用
///
public override void _EnterTree() {
Instance = this;
}
///
/// 准备就绪时调用
///
public override void _Ready() {
Input.SetCustomMouseCursor(Arrow2X);
// MVP Initialization
InitializeGame();
}
///
/// 初始化游戏数据
///
private void InitializeGame() {
Session = GameSession.CreateDefault();
Controller = new GameController();
Controller.Initialize(Session);
State.Turn.MaxTurns = MaxTurns;
State.Turn.CurrentTurn = 1;
State.Turn.Phase = GamePhase.Planning;
// MVP: Add a test student
var s1 = new StudentModel("张三");
Students.Add(s1);
// MVP: Add a test task
var t1 = new TaskModel("深度学习导论", TaskKind.AcademicExploration, 1000f, 3);
t1.Reward.Money = 1000;
t1.Reward.Reputation = 5;
ActiveTasks.Add(t1);
GD.Print("Game Initialized. Phase: Planning, Turn: 1");
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
///
/// 每帧调用
///
/// 距离上一帧的时间间隔
public override void _Process(double delta) {
if (CurrentPhase == GamePhase.Execution) {
// Update game logic (timers, etc.)
// In a real implementation, this might manage the global timer for the day/week
}
Session?.Tick((float)delta);
}
///
/// 结束筹备阶段,开始执行
///
public void StartExecution() {
if (CurrentPhase != GamePhase.Planning) return;
Controller.StartExecution();
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
GD.Print("Phase Changed: Execution");
// Notify all agents to start working (this would be handled by a system listening to the signal)
}
///
/// 结束执行阶段(通常由时间耗尽或玩家手动触发),进入结算
///
public void EndExecution() {
if (CurrentPhase != GamePhase.Execution) return;
Controller.EndExecution();
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
GD.Print("Phase Changed: Review");
PerformReview();
}
///
/// 执行结算逻辑,并准备下一回合
///
private void PerformReview() {
Session.Systems.Task.ResolveEndOfTurn();
Session.Events.Publish(new TurnEndedEvent(CurrentTurn));
GD.Print("Review Complete. Waiting for Next Turn confirmation.");
}
///
/// 开始新的回合
///
public void StartNextTurn() {
if (CurrentPhase != GamePhase.Review) return;
Controller.StartNextTurn();
if (CurrentTurn > State.Turn.MaxTurns) {
GD.Print("Game Over!");
// Handle Game Over
return;
}
State.Turn.Phase = GamePhase.Planning;
EmitSignal(SignalName.TurnChanged, CurrentTurn);
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
// Refresh resources/AP
Mentor.Resources.Energy.Current.Value = Mentor.Resources.Energy.UpperThreshold;
GD.Print($"Turn {CurrentTurn} Started. Phase: Planning");
}
}