using System; using System.Collections.Generic; namespace Engine.Core; public class BehaviourCollectorOrdered : BehaviourCollectorBase where TItem : class where TIndex : IComparable { private readonly Event.EventHandler delegateOnPriorityChanged = null!; private readonly SortedDictionary> behaviours = null!; private readonly Func getIndexFunc = null!; private readonly IComparer sortBy = null!; private int count = 0; public override int Count => count; public override TItem this[Index index] { get { int actualIndex = index.IsFromEnd ? count - index.Value : index.Value; if (actualIndex < 0 || actualIndex >= count) throw new IndexOutOfRangeException(); int leftIndex = actualIndex; foreach ((TIndex i, FastList list) in behaviours) { if (leftIndex < list.Count) return list[leftIndex]; leftIndex -= list.Count; } throw new IndexOutOfRangeException(); } } protected override bool RemoveBehaviour(TItem tBehaviour) { TIndex index = getIndexFunc(tBehaviour); if (!behaviours.TryGetValue(index, out FastList? list)) throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector"); if (!list.Remove(tBehaviour)) return false; count--; return true; } protected override void AddBehaviour(TItem behaviour) { TIndex key = getIndexFunc(behaviour); if (!behaviours.TryGetValue(key, out FastList? list)) behaviours[key] = list = []; count++; list.Add(behaviour); } protected override void OnBehaviourAdd(IBehaviour behaviour) => behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged); protected override void OnBehaviourRemove(IBehaviour behaviour) => behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged); private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args) { TItem behaviour = (TItem)sender; RemoveBehaviour(behaviour); AddBehaviour(behaviour); } public BehaviourCollectorOrdered(Func getIndexFunc, Comparison sortBy) { delegateOnPriorityChanged = OnPriorityChanged; this.getIndexFunc = getIndexFunc; this.sortBy = Comparer.Create(sortBy); behaviours = new(this.sortBy); } public BehaviourCollectorOrdered(IUniverse universe, Func getIndexFunc, Comparison sortBy) : base(universe) { delegateOnPriorityChanged = OnPriorityChanged; this.getIndexFunc = getIndexFunc; this.sortBy = Comparer.Create(sortBy); behaviours = new(this.sortBy); } public BehaviourCollectorOrdered(Func getIndexFunc, IComparer sortBy) { this.getIndexFunc = getIndexFunc; delegateOnPriorityChanged = OnPriorityChanged; this.sortBy = sortBy; behaviours = new(sortBy); } public BehaviourCollectorOrdered(IUniverse universe, Func getIndexFunc, IComparer sortBy) : base(universe) { delegateOnPriorityChanged = OnPriorityChanged; this.getIndexFunc = getIndexFunc; this.sortBy = sortBy; behaviours = new(sortBy); } }