94 lines
2.5 KiB
C#
94 lines
2.5 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using Cysharp.Threading.Tasks;
|
|
using System.Threading;
|
|
|
|
public class EndGameConditionChecker : IDisposable
|
|
{
|
|
public event Action<EndgameReason> OnEndGameCondition;
|
|
|
|
private bool _isDisposed = false;
|
|
private float startTime;
|
|
private float endTime;
|
|
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;
|
|
|
|
bool limitedByTime = sessionTimeMinutes > 0;
|
|
if(limitedByTime )
|
|
{
|
|
startTime = Time.unscaledTime;
|
|
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;
|
|
OnEndGameCondition?.Invoke(reason);
|
|
Dispose();
|
|
}
|
|
|
|
private async UniTaskVoid CheckTimeout(CancellationTokenSource cts)
|
|
{
|
|
try
|
|
{
|
|
while (!cts.IsCancellationRequested)
|
|
{
|
|
float timeRest = endTime - Time.unscaledTime;
|
|
if (timeRest <= 0)
|
|
{
|
|
TerminateSession(EndgameReason.Timeout);
|
|
break;
|
|
}
|
|
await UniTask.Delay(1000, cancellationToken: cts.Token);
|
|
}
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
// ожидаемая отмена
|
|
}
|
|
}
|
|
|
|
public enum EndgameReason
|
|
{
|
|
Timeout,
|
|
Death,
|
|
NoAmmo
|
|
}
|
|
}
|