Files
abysmal-isle/Scripts/SubSystem/VitaNex/Core/Effects/EffectQueue.cs
Unstable Kitsune b918192e4e Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
2023-11-28 23:20:26 -05:00

319 lines
5.9 KiB
C#

#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections;
using System.Collections.Generic;
using Server;
#endregion
namespace VitaNex.FX
{
public class EffectQueue<TEffectInfo> : IDisposable, IEnumerable<TEffectInfo>
where TEffectInfo : EffectInfo
{
protected Timer DeferTimer { get; set; }
public bool IsDisposed { get; private set; }
public bool Processing { get; protected set; }
public int Processed { get; protected set; }
public Queue<TEffectInfo> Queue { get; private set; }
public virtual Action<TEffectInfo> Handler { get; set; }
public virtual Action<TEffectInfo> Mutator { get; set; }
public virtual Action Callback { get; set; }
public virtual bool Deferred { get; set; }
public int Count => Queue.Count;
public EffectQueue(Action callback = null, Action<TEffectInfo> handler = null, bool deferred = true)
{
Queue = new Queue<TEffectInfo>();
Callback = callback;
Handler = handler;
Deferred = deferred;
}
public EffectQueue(int capacity, Action callback = null, Action<TEffectInfo> handler = null, bool deferred = true)
{
Queue = new Queue<TEffectInfo>(capacity);
Callback = callback;
Handler = handler;
Deferred = deferred;
}
public EffectQueue(
IEnumerable<TEffectInfo> queue,
Action callback = null,
Action<TEffectInfo> handler = null,
bool deferred = true)
{
Queue = new Queue<TEffectInfo>(queue);
Callback = callback;
Handler = handler;
Deferred = deferred;
}
~EffectQueue()
{
Dispose();
}
public virtual void Dispose()
{
if (IsDisposed)
{
return;
}
IsDisposed = true;
//GC.SuppressFinalize(this);
if (DeferTimer != null)
{
DeferTimer.Stop();
DeferTimer = null;
}
Processed = 0;
Processing = false;
Queue.Free(true);
Queue = null;
Handler = null;
Mutator = null;
Callback = null;
}
IEnumerator IEnumerable.GetEnumerator()
{
return Queue.GetEnumerator();
}
public virtual IEnumerator<TEffectInfo> GetEnumerator()
{
return Queue.GetEnumerator();
}
public void Add(TEffectInfo info)
{
Enqueue(info);
}
public virtual void Enqueue(TEffectInfo info)
{
if (!IsDisposed)
{
Queue.Enqueue(info);
}
}
public virtual TEffectInfo Dequeue()
{
return Queue.Dequeue();
}
public virtual void Clear()
{
Queue.Clear();
}
public virtual void Process()
{
if (IsDisposed /* || Processing*/)
{
return;
}
if (Queue.Count == 0)
{
OnProcessed();
return;
}
Processing = true;
var info = Dequeue();
if (!OnProcess(info))
{
++Processed;
Process();
return;
}
++Processed;
if (!Deferred)
{
Process();
return;
}
var delay = GetDeferDelay(info);
if (delay > TimeSpan.Zero)
{
DeferTimer = Timer.DelayCall(delay, InternalDeferredCallback);
return;
}
InternalDeferredCallback();
}
private void InternalDeferredCallback()
{
if (DeferTimer != null)
{
DeferTimer.Stop();
DeferTimer = null;
}
Process();
}
protected virtual bool OnProcess(TEffectInfo info)
{
if (IsDisposed || info == null || info.IsDisposed)
{
return false;
}
if (Mutator != null)
{
Mutator(info);
}
if (info.IsDisposed)
{
return false;
}
info.Send();
if (Handler != null)
{
Handler(info);
}
return true;
}
protected virtual void OnProcessed()
{
if (IsDisposed)
{
return;
}
if (Callback != null)
{
Callback();
}
Processed = 0;
Processing = false;
Queue.Free(false);
}
public virtual TimeSpan GetDeferDelay(TEffectInfo info)
{
return !IsDisposed && info != null
? TimeSpan.FromMilliseconds(info.Delay.TotalMilliseconds + ((info.Duration * 100.0) / info.Speed))
: TimeSpan.Zero;
}
}
public class EffectQueue : EffectQueue<EffectInfo>
{
public EffectQueue(Action callback = null, Action<EffectInfo> handler = null, bool deferred = true)
: base(callback, handler, deferred)
{ }
public EffectQueue(int capacity, Action callback = null, Action<EffectInfo> handler = null, bool deferred = true)
: base(capacity, callback, handler, deferred)
{ }
public EffectQueue(
IEnumerable<EffectInfo> queue,
Action callback = null,
Action<EffectInfo> handler = null,
bool deferred = true)
: base(queue, callback, handler, deferred)
{ }
}
public class MovingEffectQueue : EffectQueue<MovingEffectInfo>
{
protected Timer DelayTimer { get; set; }
public MovingEffectQueue(Action callback = null, Action<MovingEffectInfo> handler = null, bool deferred = true)
: base(callback, handler, deferred)
{ }
public MovingEffectQueue(
int capacity,
Action callback = null,
Action<MovingEffectInfo> handler = null,
bool deferred = true)
: base(capacity, callback, handler, deferred)
{ }
public MovingEffectQueue(
IEnumerable<MovingEffectInfo> queue,
Action callback = null,
Action<MovingEffectInfo> handler = null,
bool deferred = true)
: base(queue, callback, handler, deferred)
{ }
protected override bool OnProcess(MovingEffectInfo info)
{
if (IsDisposed || info == null)
{
return false;
}
info.Send();
if (Handler == null)
{
return true;
}
var d = GetDeferDelay(info);
if (d > TimeSpan.Zero)
{
Timer.DelayCall(d, h => h(info), Handler);
}
else
{
Handler(info);
}
return true;
}
public override TimeSpan GetDeferDelay(MovingEffectInfo info)
{
return info != null ? info.Delay + info.GetTravelTime() : TimeSpan.Zero;
}
}
}