using System.Threading; using Cysharp.Threading.Tasks; using R3; using RebootKit.Engine.Foundation; namespace RebootKit.Engine.Services.Game { public class GameService : IService { static readonly Logger s_logger = new(nameof(GameService)); [Inject] DIContext m_DIContext; GameModeAsset m_GameModeAsset; CancellationTokenSource m_DestroyCancellationTokenSource = new(); DisposableBag m_ActiveGameModeDisposableBag; IGameMode m_ActiveGameMode; public void Dispose() { m_DestroyCancellationTokenSource.Cancel(); m_DestroyCancellationTokenSource.Dispose(); m_ActiveGameModeDisposableBag.Dispose(); } public void Start(GameModeAsset asset) { if (m_ActiveGameMode != null) { s_logger.Warning("Game is already running"); return; } Stop(); m_ActiveGameModeDisposableBag = new DisposableBag(); m_ActiveGameMode = asset.Create(m_DIContext); m_ActiveGameModeDisposableBag.Add(m_ActiveGameMode); InitializeGameModeAsync().Forget(); } async UniTask InitializeGameModeAsync() { await m_ActiveGameMode.OnInit(m_DestroyCancellationTokenSource.Token); m_ActiveGameMode.OnStart(); Observable.EveryUpdate().Subscribe(_ => { m_ActiveGameMode?.OnTick(); }).AddTo(ref m_ActiveGameModeDisposableBag); } public void Stop() { if (m_ActiveGameMode == null) { return; } m_ActiveGameMode.OnStop(); m_ActiveGameMode = null; m_ActiveGameModeDisposableBag.Dispose(); } } }