using System; using System.Collections.Generic; namespace Engine.Core; public class ActiveBehaviourCollectorOrdered : ActiveBehaviourCollector where T : class, IBehaviour { private readonly Event.EventHandler delegateOnPriorityChanged = null!; private readonly LinkedList behaviours = new(); private readonly List sortList = []; private IComparer? _sortBy = null; public IComparer? SortBy { get => _sortBy; set { _sortBy = value; if (value is not null) Sort(value); } } public override int Count => behaviours.Count; public override T this[Index index] { get { int actualIndex = index.IsFromEnd ? behaviours.Count - index.Value : index.Value; if (actualIndex < 0 || actualIndex >= behaviours.Count) throw new IndexOutOfRangeException(); int currentIndex = 0; foreach (T item in behaviours) if (currentIndex++ == actualIndex) return item; throw new IndexOutOfRangeException(); } } protected override bool RemoveBehaviour(T tBehaviour) => behaviours.Remove(tBehaviour); protected override void AddBehaviour(T behaviour) { if (SortBy is null) { behaviours.AddLast(behaviour); return; } LinkedListNode? insertionNode = FindInsertionNodeFor(behaviour, SortBy); if (insertionNode is not null) behaviours.AddAfter(insertionNode, behaviour); else behaviours.AddLast(behaviour); } private LinkedListNode? FindInsertionNodeFor(T behaviour, IComparer sortBy) { LinkedListNode? node = behaviours.First; while (node is not null) { int compareValue = sortBy.Compare(node.Value, behaviour); if (compareValue < 0) return node.Previous; node = node.Next; } return null; } 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) { T behaviour = (T)sender; behaviours.Remove(behaviour); AddBehaviour(behaviour); } private void Sort(IComparer comparer) { sortList.Sort(comparer); behaviours.Clear(); foreach (T item in sortList) behaviours.AddLast(item); } public ActiveBehaviourCollectorOrdered() => delegateOnPriorityChanged = OnPriorityChanged; public ActiveBehaviourCollectorOrdered(IUniverse universe, Comparison sortBy) : base(universe) { delegateOnPriorityChanged = OnPriorityChanged; SortBy = Comparer.Create(sortBy); } }