Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
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
    }
}