using System.Collections;
using GFramework.Game.Abstractions.coroutine;
namespace GFramework.Game.coroutine;
///
/// 协程句柄类,用于管理和控制协程的执行状态
/// 实现了IYieldInstruction和ICoroutineHandle接口
///
public class CoroutineHandle : IYieldInstruction, ICoroutineHandle
{
///
/// 存储协程执行栈的堆栈结构
///
private readonly Stack _stack = new();
///
/// 当前等待执行的指令
///
private IYieldInstruction? _waitingInstruction;
///
/// 初始化一个新的协程句柄实例
///
/// 要执行的枚举器协程
/// 协程上下文环境
/// 初始等待的指令
internal CoroutineHandle(IEnumerator routine, CoroutineContext context, IYieldInstruction? waitingInstruction)
{
_stack.Push(routine);
Context = context;
_waitingInstruction = waitingInstruction;
}
///
/// 获取协程的上下文环境
///
public CoroutineContext Context { get; }
///
/// 获取协程句柄的上下文环境(接口实现)
///
ICoroutineContext ICoroutineHandle.Context => Context;
///
/// 获取协程是否已被取消的标志
///
public bool IsCancelled { get; private set; }
///
/// 协程完成时触发的事件
///
public event Action? OnComplete;
///
/// 协程发生错误时触发的事件
///
public event Action? OnError;
///
/// 取消协程的执行
///
public void Cancel()
{
if (IsDone) return;
IsDone = true;
IsCancelled = true;
_stack.Clear();
_waitingInstruction = null;
OnComplete?.Invoke();
}
///
/// 获取协程是否已完成的标志
///
public bool IsDone { get; private set; }
///
/// 更新协程执行状态(接口实现)
///
/// 时间增量
void IYieldInstruction.Update(float deltaTime)
{
InternalUpdate(deltaTime);
}
///
/// 内部更新协程执行逻辑
///
/// 时间增量
/// 如果协程仍在运行返回true,否则返回false
private bool InternalUpdate(float deltaTime)
{
if (IsDone) return false;
// 检查并更新当前等待的指令
if (_waitingInstruction != null)
{
_waitingInstruction.Update(deltaTime);
if (!_waitingInstruction.IsDone) return true;
_waitingInstruction = null;
}
if (_stack.Count == 0)
{
Complete();
return false;
}
try
{
var current = _stack.Peek();
if (current.MoveNext())
{
ProcessYieldValue(current.Current);
return true;
}
_stack.Pop();
return _stack.Count > 0 || !CompleteCheck();
}
catch (Exception ex)
{
HandleError(ex);
return false;
}
}
///
/// 处理协程中yield返回的值,根据类型决定如何处理
///
/// 协程yield返回的对象
private void ProcessYieldValue(object yielded)
{
switch (yielded)
{
case CoroutineHandle otherHandle:
_waitingInstruction = otherHandle;
break;
case IEnumerator nested:
_stack.Push(nested);
break;
case IYieldInstruction instruction:
_waitingInstruction = instruction;
break;
case null:
break;
default:
throw new InvalidOperationException($"Unsupported yield type: {yielded.GetType()}");
}
}
///
/// 检查协程是否完成并进行相应处理
///
/// 如果协程已完成返回true,否则返回false
private bool CompleteCheck()
{
if (_stack.Count == 0) Complete();
return IsDone;
}
///
/// 标记协程完成并清理相关资源
///
private void Complete()
{
if (IsDone) return;
IsDone = true;
_stack.Clear();
_waitingInstruction = null;
OnComplete?.Invoke();
}
///
/// 处理协程执行过程中发生的异常
///
/// 发生的异常
private void HandleError(Exception ex)
{
IsDone = true;
_stack.Clear();
_waitingInstruction = null;
OnError?.Invoke(ex);
}
}