fix: Fixes map iterators for Items (#1564)

### Summary

Modifying a ValueLinkList using one of the methods will bump the "version". This field is used by iterators (foreach loops) to determine if the link list was modified while iterating. The sector.Items (and in the future other lists), will no longer be safe to modify while iterating. The server will _CRASH_ if the ValueLinkList is modified.

Thanks to @stefanomerotta for help!


### Screenshots
<img width="588" alt="image" src="https://github.com/modernuo/ModernUO/assets/3953314/83ee0b6e-ff4f-4768-9e29-84456e04b1ec">
This commit is contained in:
Kamron Batman 2023-10-26 17:49:15 -07:00 committed by GitHub
parent 658f564f34
commit d919f71149
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 706 additions and 468 deletions

View file

@ -2241,7 +2241,6 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
public virtual bool CanDecay() => Decays && Parent == null && Map != Map.Internal;
public virtual bool OnDecay() =>
CanDecay() && Region.Find(Location, Map).OnDecay(this);
@ -2474,12 +2473,20 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Map.ItemEnumerable<Item> GetItemsInRange(int range) =>
m_Map == null ? Map.ItemEnumerable<Item>.Empty : m_Map.GetItemsInRange(m_Parent == null ? m_Location : GetWorldLocation(), range);
public Map.ItemAtEnumerable<Item> GetItemsAt() =>
m_Map == null ? Map.ItemAtEnumerable<Item>.Empty : m_Map.GetItemsAt(m_Parent == null ? m_Location : GetWorldLocation());
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Map.ItemEnumerable<T> GetItemsInRange<T>(int range) where T : Item =>
m_Map == null ? Map.ItemEnumerable<T>.Empty : m_Map.GetItemsInRange<T>(m_Parent == null ? m_Location : GetWorldLocation(), range);
public Map.ItemAtEnumerable<T> GetItemsAt<T>() where T : Item =>
m_Map == null ? Map.ItemAtEnumerable<T>.Empty : m_Map.GetItemsAt<T>(m_Parent == null ? m_Location : GetWorldLocation());
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Map.ItemBoundsEnumerable<Item> GetItemsInRange(int range) =>
m_Map == null ? Map.ItemBoundsEnumerable<Item>.Empty : m_Map.GetItemsInRange(m_Parent == null ? m_Location : GetWorldLocation(), range);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Map.ItemBoundsEnumerable<T> GetItemsInRange<T>(int range) where T : Item =>
m_Map == null ? Map.ItemBoundsEnumerable<T>.Empty : m_Map.GetItemsInRange<T>(m_Parent == null ? m_Location : GetWorldLocation(), range);
public IPooledEnumerable<Mobile> GetMobilesInRange(int range)
{