151 lines
3.9 KiB
C#
151 lines
3.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Aliciza.Services.Example
|
|
{
|
|
public sealed class TimerService : ServiceBase, ITimerService, IServiceTickable, IServiceOrder
|
|
{
|
|
private readonly List<TimerTask> _timers = new List<TimerTask>();
|
|
|
|
private int _nextTimerId = 1;
|
|
|
|
public float ElapsedTime { get; private set; }
|
|
|
|
public int Order => -1000;
|
|
|
|
public int Once(float delay, Action callback)
|
|
{
|
|
if (callback == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(callback));
|
|
}
|
|
|
|
return AddTimer(delay, 0f, 1, callback);
|
|
}
|
|
|
|
public int Repeat(float interval, Action callback, int repeatCount = -1, float firstDelay = -1f)
|
|
{
|
|
if (callback == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(callback));
|
|
}
|
|
|
|
if (interval <= 0f)
|
|
{
|
|
throw new ArgumentOutOfRangeException(nameof(interval), "Repeat interval must be greater than zero.");
|
|
}
|
|
|
|
var delay = firstDelay < 0f ? interval : firstDelay;
|
|
return AddTimer(delay, interval, repeatCount, callback);
|
|
}
|
|
|
|
public bool Cancel(int timerId)
|
|
{
|
|
for (var i = 0; i < _timers.Count; i++)
|
|
{
|
|
if (_timers[i].Id != timerId)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
_timers.RemoveAt(i);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public void CancelAll()
|
|
{
|
|
_timers.Clear();
|
|
}
|
|
|
|
public void Tick(float deltaTime)
|
|
{
|
|
ElapsedTime += deltaTime;
|
|
|
|
for (var i = _timers.Count - 1; i >= 0; i--)
|
|
{
|
|
var timer = _timers[i];
|
|
timer.Remaining -= deltaTime;
|
|
if (timer.Remaining > 0f)
|
|
{
|
|
_timers[i] = timer;
|
|
continue;
|
|
}
|
|
|
|
timer.Callback?.Invoke();
|
|
|
|
if (timer.RepeatCount == 1)
|
|
{
|
|
_timers.RemoveAt(i);
|
|
continue;
|
|
}
|
|
|
|
if (timer.RepeatCount > 1)
|
|
{
|
|
timer.RepeatCount--;
|
|
}
|
|
|
|
if (timer.Interval <= 0f)
|
|
{
|
|
_timers.RemoveAt(i);
|
|
continue;
|
|
}
|
|
|
|
timer.Remaining += timer.Interval;
|
|
if (timer.Remaining <= 0f)
|
|
{
|
|
timer.Remaining = timer.Interval;
|
|
}
|
|
|
|
_timers[i] = timer;
|
|
}
|
|
}
|
|
|
|
protected override void OnInitialize()
|
|
{
|
|
ElapsedTime = 0f;
|
|
}
|
|
|
|
protected override void OnDestroyService()
|
|
{
|
|
CancelAll();
|
|
ElapsedTime = 0f;
|
|
}
|
|
|
|
private int AddTimer(float delay, float interval, int repeatCount, Action callback)
|
|
{
|
|
if (delay < 0f)
|
|
{
|
|
throw new ArgumentOutOfRangeException(nameof(delay), "Delay cannot be negative.");
|
|
}
|
|
|
|
if (repeatCount == 0)
|
|
{
|
|
throw new ArgumentOutOfRangeException(nameof(repeatCount), "Repeat count cannot be zero.");
|
|
}
|
|
|
|
var id = _nextTimerId++;
|
|
_timers.Add(new TimerTask
|
|
{
|
|
Id = id,
|
|
Remaining = delay,
|
|
Interval = interval,
|
|
RepeatCount = repeatCount,
|
|
Callback = callback,
|
|
});
|
|
return id;
|
|
}
|
|
|
|
private struct TimerTask
|
|
{
|
|
public int Id;
|
|
public float Remaining;
|
|
public float Interval;
|
|
public int RepeatCount;
|
|
public Action Callback;
|
|
}
|
|
}
|
|
}
|