94 lines
2.8 KiB
C#
94 lines
2.8 KiB
C#
|
using System;
|
||
|
using System.Buffers;
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
namespace Net.Project.B.Buff
|
||
|
{
|
||
|
public interface IBuffComponent
|
||
|
{
|
||
|
Memory<IBuff> Buffs { get; }
|
||
|
IReadOnlyDictionary<IBuff, float> Durations { get; }
|
||
|
public event Action<IBuff> OnBuffAdded;
|
||
|
public event Action<IBuff, float> OnBuffUpdated;
|
||
|
public event Action<IBuff> OnBuffRemoved;
|
||
|
|
||
|
public void AddBuff(IBuff buff = default, float duration = 0);
|
||
|
public void RemoveBuff<T>() where T : IBuff;
|
||
|
public void RemoveBuff(ref IBuff buff);
|
||
|
}
|
||
|
|
||
|
public class BuffComponent:IBuffComponent
|
||
|
{
|
||
|
private readonly ArrayPool<int> _pool=ArrayPool<int>.Create();
|
||
|
public Memory<IBuff> Buffs=>_buff.AsMemory(0, _count);
|
||
|
public IReadOnlyDictionary<IBuff, float> Durations => _durations;
|
||
|
private readonly IBuff[] _buff = new IBuff[32];
|
||
|
public event Action<IBuff> OnBuffAdded;
|
||
|
public event Action<IBuff, float> OnBuffUpdated;
|
||
|
public event Action<IBuff> OnBuffRemoved;
|
||
|
|
||
|
private readonly Dictionary<IBuff, float> _durations = new();
|
||
|
|
||
|
private readonly Queue<IBuff> _removeQueue = new();
|
||
|
|
||
|
private int _count;
|
||
|
|
||
|
public void AddBuff(IBuff buff, float duration = 0)
|
||
|
{
|
||
|
_buff[_count++] = buff;
|
||
|
OnBuffAdded?.Invoke(buff);
|
||
|
if (duration > 0)
|
||
|
{
|
||
|
if (_durations.TryGetValue(buff, out var currentDuration))
|
||
|
{
|
||
|
currentDuration += duration;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
currentDuration = duration;
|
||
|
}
|
||
|
_durations[buff] = currentDuration;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void RemoveBuff<T>() where T : IBuff
|
||
|
{
|
||
|
for (var index = 0; index < Buffs.Span.Length; index++)
|
||
|
{
|
||
|
ref var buff =ref Buffs.Span[index];
|
||
|
if (buff is T)
|
||
|
{
|
||
|
_removeQueue.Enqueue(buff);
|
||
|
}
|
||
|
}
|
||
|
while (_removeQueue.TryDequeue(out var remove))
|
||
|
{
|
||
|
RemoveBuff(ref remove);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void RemoveBuff(ref IBuff buff)
|
||
|
{
|
||
|
var prev = false;
|
||
|
for (var i = 0; i < _count; i++)
|
||
|
{
|
||
|
ref var b = ref _buff[i];
|
||
|
if (b == buff)
|
||
|
{
|
||
|
prev = true;
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
if (!prev) continue;
|
||
|
ref var p = ref _buff[i - 1];
|
||
|
p = b;
|
||
|
}
|
||
|
if (prev)
|
||
|
{
|
||
|
OnBuffRemoved?.Invoke(buff);
|
||
|
}
|
||
|
_count--;
|
||
|
}
|
||
|
}
|
||
|
}
|