sea-battle-vr/Assets/Scripts/Gameplay/Core/EndGameConditionChecker.cs

95 lines
2.6 KiB
C#

using System;
using UnityEngine;
using Cysharp.Threading.Tasks;
using System.Threading;
using Lights;
public class EndGameConditionChecker : IDisposable
{
public event Action<EndgameReason> OnEndGameCondition;
private bool _isDisposed = false;
private float startTime;
private float endTime;
public float TimeRest => limitedByTime ? endTime - Time.time : -1;
private bool limitedByTime;
private CancellationTokenSource _cts;
private WeaponModel weaponModel;
private Health playerHealth;
public EndGameConditionChecker(WeaponModel weaponModel, Health playerHealth, int sessionTimeMinutes = 0)
{
if (weaponModel == null)
throw new ArgumentNullException("WeaponModel is null");
if (playerHealth == null)
throw new ArgumentNullException("PlayerHealth is null");
this.weaponModel = weaponModel;
this.playerHealth = playerHealth;
weaponModel.OnNoAmmo += NoAmmoHandler;
playerHealth.Died += PlayerDiedHandler;
limitedByTime = sessionTimeMinutes > 0;
if (limitedByTime)
{
startTime = Time.time;
endTime = startTime + sessionTimeMinutes * 60;
_cts = new CancellationTokenSource();
CheckTimeout(_cts).Forget();
}
}
public void Dispose()
{
if (_isDisposed) return;
_isDisposed = true;
_cts?.Cancel();
_cts?.Dispose();
_cts = null;
weaponModel.OnNoAmmo -= NoAmmoHandler;
playerHealth.Died -= PlayerDiedHandler;
weaponModel = null;
playerHealth = null;
}
private void PlayerDiedHandler(Vector3 obj) => TerminateSession(EndgameReason.Death);
private void NoAmmoHandler() => TerminateSession(EndgameReason.NoAmmo);
private void TerminateSession(EndgameReason reason)
{
if (_isDisposed) return;
Dispose();
OnEndGameCondition?.Invoke(reason);
}
private async UniTaskVoid CheckTimeout(CancellationTokenSource cts)
{
while (!cts.IsCancellationRequested)
{
await UniTask.Delay(1000, cancellationToken: cts.Token);
// Проверяем после задержки, не отменена ли операция
if (cts.IsCancellationRequested)
break;
if (TimeRest <= 0)
{
TerminateSession(EndgameReason.Timeout);
break;
}
}
Debug.Log("Конец проверки по времени");
}
public enum EndgameReason
{
Timeout,
Death,
NoAmmo
}
}