using System; using System.Buffers; using System.Collections.Generic; namespace Net.Project.B.Buff { public interface IBuffComponent { Memory Buffs { get; } IReadOnlyDictionary Durations { get; } public event Action OnBuffAdded; public event Action OnBuffUpdated; public event Action OnBuffRemoved; public void AddBuff(IBuff buff = default, float duration = 0); public void RemoveBuff() where T : IBuff; public void RemoveBuff(ref IBuff buff); } public class BuffComponent:IBuffComponent { private readonly ArrayPool _pool=ArrayPool.Create(); public Memory Buffs=>_buff.AsMemory(0, _count); public IReadOnlyDictionary Durations => _durations; private readonly IBuff[] _buff = new IBuff[32]; public event Action OnBuffAdded; public event Action OnBuffUpdated; public event Action OnBuffRemoved; private readonly Dictionary _durations = new(); private readonly Queue _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() 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--; } } }