Repository URL to install this package:
|
Version:
2023.12.1 ▾
|
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Gs2.Core.Domain;
using Gs2.Gs2StateMachine.Exception;
using Gs2.Unity.Core;
using Gs2.Unity.Util;
using UnityEngine.Events;
#if UNITY_2017_1_OR_NEWER
using UnityEngine;
#if GS2_ENABLE_UNITASK
using Cysharp.Threading.Tasks;
#endif
#else
using System.Threading.Tasks;
#endif
namespace Gs2.Unity.Gs2StateMachine.Local
{
public class EventStream
{
private string _stateMachineNamespaceName;
private string _statusName;
private readonly Queue<IEvent> _events = new Queue<IEvent>();
private DateTime _lastFlushAt;
private bool _detectStateMismatch;
public delegate void DetectStateMismatchHandler(string namespaceName, string statusName);
public event DetectStateMismatchHandler OnDetectStateMismatch;
public void Attach(
ActiveStateMachine stateMachine,
string stateMachineNamespaceName,
string statusName
) {
this._stateMachineNamespaceName = stateMachineNamespaceName;
this._statusName = statusName;
this._lastFlushAt = DateTime.Now;
stateMachine.OnEmit += (name, parameters) =>
{
this._events.Enqueue(new EmitEvent(name, parameters));
};
stateMachine.OnChangeState += (taskName, hash) =>
{
this._events.Enqueue(new ChangeStateEvent(taskName, hash));
};
}
public Gs2Future DispatchFuture(
Gs2Domain gs2,
GameSession gameSession
) {
IEnumerator Impl(Gs2Future result) {
if (
this._lastFlushAt - DateTime.Now > TimeSpan.FromSeconds(3) ||
this._events.Count >= 100
) {
var future = FlushFuture(
gs2,
gameSession
);
if (future.Error != null) {
result.OnError(future.Error);
yield break;
}
result.OnComplete(null);
}
}
return new Gs2InlineFuture(Impl);
}
#if !UNITY_2017_1_OR_NEWER || GS2_ENABLE_UNITASK
#if UNITY_2017_1_OR_NEWER
public async UniTask DispatchAsync(
#else
public async Task DispatchAsync(
#endif
Gs2Domain gs2,
GameSession gameSession
) {
if (
DateTime.Now - this._lastFlushAt > TimeSpan.FromSeconds(3) ||
this._events.Count >= 100
) {
await FlushAsync(
gs2,
gameSession
);
}
}
#endif
public Gs2Future FlushFuture(
Gs2Domain gs2,
GameSession gameSession
) {
IEnumerator Impl(Gs2Future result) {
if (this._detectStateMismatch) {
Debug.LogWarning("Skipped sending a report because a state mismatch was detected.");
yield break;
}
var events = new List<IEvent>();
while (this._events.Count > 0) {
events.Add(this._events.Dequeue());
}
if (events.Count > 0) {
var future = gs2.StateMachine.Namespace(
this._stateMachineNamespaceName
).Me(
gameSession
).Status(
this._statusName
).ReportFuture(
events.Select(v => v.ToGs2Model()).ToArray()
);
if (future.Error != null) {
if (future.Error is StateMismatchException) {
OnDetectStateMismatch?.Invoke(this._stateMachineNamespaceName, this._statusName);
this._detectStateMismatch = true;
result.OnComplete(null);
yield break;
}
result.OnError(future.Error);
yield break;
}
}
this._lastFlushAt = DateTime.Now;
result.OnComplete(null);
}
return new Gs2InlineFuture(Impl);
}
#if !UNITY_2017_1_OR_NEWER || GS2_ENABLE_UNITASK
#if UNITY_2017_1_OR_NEWER
public async UniTask FlushAsync(
#else
public async Task FlushAsync(
#endif
Gs2Domain gs2,
GameSession gameSession
) {
if (this._detectStateMismatch) {
Debug.LogWarning("Skipped sending a report because a state mismatch was detected.");
return;
}
try {
var events = new List<IEvent>();
while (this._events.Count > 0) {
events.Add(this._events.Dequeue());
}
if (events.Count > 0) {
await gs2.StateMachine.Namespace(
this._stateMachineNamespaceName
).Me(
gameSession
).Status(
this._statusName
).ReportAsync(
events.Select(v => v.ToGs2Model()).ToArray()
);
}
this._lastFlushAt = DateTime.Now;
}
catch (StateMismatchException) {
OnDetectStateMismatch?.Invoke(this._stateMachineNamespaceName, this._statusName);
this._detectStateMismatch = true;
}
}
#endif
}
}