fix: ordered behaviour controllers not removing behaviours properly because of index getter function time dependence

This commit is contained in:
2025-11-02 10:54:13 +03:00
parent f28307be80
commit e9ba7867ac
2 changed files with 8 additions and 38 deletions

View File

@@ -5,9 +5,8 @@ namespace Engine.Core;
public class ActiveBehaviourCollectorOrdered<TIndex, TItem> : ActiveBehaviourCollector<TItem> where TItem : class, IBehaviour where TIndex : IComparable public class ActiveBehaviourCollectorOrdered<TIndex, TItem> : ActiveBehaviourCollector<TItem> where TItem : class, IBehaviour where TIndex : IComparable
{ {
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
private readonly SortedDictionary<TIndex, FastList<TItem>> behaviours = null!; private readonly SortedDictionary<TIndex, FastList<TItem>> behaviours = null!;
private readonly Dictionary<TItem, TIndex> indexCache = [];
private readonly Func<TItem, TIndex> getIndexFunc = null!; private readonly Func<TItem, TIndex> getIndexFunc = null!;
private readonly IComparer<TIndex> sortBy = null!; private readonly IComparer<TIndex> sortBy = null!;
@@ -39,11 +38,10 @@ public class ActiveBehaviourCollectorOrdered<TIndex, TItem> : ActiveBehaviourCol
protected override bool RemoveBehaviour(TItem tBehaviour) protected override bool RemoveBehaviour(TItem tBehaviour)
{ {
TIndex index = getIndexFunc(tBehaviour); if (!indexCache.TryGetValue(tBehaviour, out TIndex? index) || !behaviours.TryGetValue(index, out FastList<TItem>? list))
if (!behaviours.TryGetValue(index, out FastList<TItem>? list))
throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector"); throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector");
if (!list.Remove(tBehaviour)) if (!list.Remove(tBehaviour) || !indexCache.Remove(tBehaviour))
return false; return false;
count--; count--;
@@ -58,21 +56,11 @@ public class ActiveBehaviourCollectorOrdered<TIndex, TItem> : ActiveBehaviourCol
count++; count++;
list.Add(behaviour); list.Add(behaviour);
} indexCache.Add(behaviour, key);
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 ActiveBehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) public ActiveBehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy)
{ {
delegateOnPriorityChanged = OnPriorityChanged;
this.getIndexFunc = getIndexFunc; this.getIndexFunc = getIndexFunc;
this.sortBy = Comparer<TIndex>.Create(sortBy); this.sortBy = Comparer<TIndex>.Create(sortBy);
behaviours = new(this.sortBy); behaviours = new(this.sortBy);
@@ -80,7 +68,6 @@ public class ActiveBehaviourCollectorOrdered<TIndex, TItem> : ActiveBehaviourCol
public ActiveBehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) : base(universe) public ActiveBehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) : base(universe)
{ {
delegateOnPriorityChanged = OnPriorityChanged;
this.getIndexFunc = getIndexFunc; this.getIndexFunc = getIndexFunc;
this.sortBy = Comparer<TIndex>.Create(sortBy); this.sortBy = Comparer<TIndex>.Create(sortBy);
behaviours = new(this.sortBy); behaviours = new(this.sortBy);
@@ -89,14 +76,12 @@ public class ActiveBehaviourCollectorOrdered<TIndex, TItem> : ActiveBehaviourCol
public ActiveBehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) public ActiveBehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy)
{ {
this.getIndexFunc = getIndexFunc; this.getIndexFunc = getIndexFunc;
delegateOnPriorityChanged = OnPriorityChanged;
this.sortBy = sortBy; this.sortBy = sortBy;
behaviours = new(sortBy); behaviours = new(sortBy);
} }
public ActiveBehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) : base(universe) public ActiveBehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) : base(universe)
{ {
delegateOnPriorityChanged = OnPriorityChanged;
this.getIndexFunc = getIndexFunc; this.getIndexFunc = getIndexFunc;
this.sortBy = sortBy; this.sortBy = sortBy;
behaviours = new(sortBy); behaviours = new(sortBy);

View File

@@ -5,9 +5,8 @@ namespace Engine.Core;
public class BehaviourCollectorOrdered<TIndex, TItem> : BehaviourCollectorBase<TItem> where TItem : class where TIndex : IComparable public class BehaviourCollectorOrdered<TIndex, TItem> : BehaviourCollectorBase<TItem> where TItem : class where TIndex : IComparable
{ {
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
private readonly SortedDictionary<TIndex, FastList<TItem>> behaviours = null!; private readonly SortedDictionary<TIndex, FastList<TItem>> behaviours = null!;
private readonly Dictionary<TItem, TIndex> indexCache = null!;
private readonly Func<TItem, TIndex> getIndexFunc = null!; private readonly Func<TItem, TIndex> getIndexFunc = null!;
private readonly IComparer<TIndex> sortBy = null!; private readonly IComparer<TIndex> sortBy = null!;
@@ -39,11 +38,10 @@ public class BehaviourCollectorOrdered<TIndex, TItem> : BehaviourCollectorBase<T
protected override bool RemoveBehaviour(TItem tBehaviour) protected override bool RemoveBehaviour(TItem tBehaviour)
{ {
TIndex index = getIndexFunc(tBehaviour); if (!indexCache.TryGetValue(tBehaviour, out TIndex? index) || !behaviours.TryGetValue(index, out FastList<TItem>? list))
if (!behaviours.TryGetValue(index, out FastList<TItem>? list))
throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector"); throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector");
if (!list.Remove(tBehaviour)) if (!list.Remove(tBehaviour) || !indexCache.Remove(tBehaviour))
return false; return false;
count--; count--;
@@ -58,21 +56,11 @@ public class BehaviourCollectorOrdered<TIndex, TItem> : BehaviourCollectorBase<T
count++; count++;
list.Add(behaviour); list.Add(behaviour);
} indexCache.Add(behaviour, key);
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<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) public BehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy)
{ {
delegateOnPriorityChanged = OnPriorityChanged;
this.getIndexFunc = getIndexFunc; this.getIndexFunc = getIndexFunc;
this.sortBy = Comparer<TIndex>.Create(sortBy); this.sortBy = Comparer<TIndex>.Create(sortBy);
behaviours = new(this.sortBy); behaviours = new(this.sortBy);
@@ -80,7 +68,6 @@ public class BehaviourCollectorOrdered<TIndex, TItem> : BehaviourCollectorBase<T
public BehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) : base(universe) public BehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) : base(universe)
{ {
delegateOnPriorityChanged = OnPriorityChanged;
this.getIndexFunc = getIndexFunc; this.getIndexFunc = getIndexFunc;
this.sortBy = Comparer<TIndex>.Create(sortBy); this.sortBy = Comparer<TIndex>.Create(sortBy);
behaviours = new(this.sortBy); behaviours = new(this.sortBy);
@@ -89,14 +76,12 @@ public class BehaviourCollectorOrdered<TIndex, TItem> : BehaviourCollectorBase<T
public BehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) public BehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy)
{ {
this.getIndexFunc = getIndexFunc; this.getIndexFunc = getIndexFunc;
delegateOnPriorityChanged = OnPriorityChanged;
this.sortBy = sortBy; this.sortBy = sortBy;
behaviours = new(sortBy); behaviours = new(sortBy);
} }
public BehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) : base(universe) public BehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) : base(universe)
{ {
delegateOnPriorityChanged = OnPriorityChanged;
this.getIndexFunc = getIndexFunc; this.getIndexFunc = getIndexFunc;
this.sortBy = sortBy; this.sortBy = sortBy;
behaviours = new(sortBy); behaviours = new(sortBy);