fix: Fixes searching multis/clients. Adds missing map enumeration tests (#2278)
> [!IMPORTANT] > **Dev Note:** This is an **important** patch as the bug could lead to major issues like: > * Multis/Players disappearing from view or not being counted during game logic. > * World processes (e.g., area checks, targeting) failing to detect entities correctly. > * General stability and correctness concerns for core map functionality. > > **Important Breaking Change**: Multis now properly use the map link list. This means modifying a multi while iterating will cause the server to crash. The crash _is expected_. Please modify/fix code accordingly to create a list using `PooledRefQueue` or `PooledRefList` instead of moving/deleting multis while inside the foreach. ### Summary * Fixes a bug where deleting/moving a multi (boat/house) in some circumstances can use undefined behavior due to unsafe changes to List<BaseMulti> * Fixes a bug where Multis may not be considered while searching due to a bug causing the sector search to end early.
This commit is contained in:
parent
5aed018232
commit
d3fdb180b3
9 changed files with 1923 additions and 571 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2023 - ModernUO Development Team *
|
||||
* Copyright 2019-2025 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: Map.cs *
|
||||
* *
|
||||
|
|
@ -1355,11 +1355,13 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
{
|
||||
// TODO: Can we avoid this?
|
||||
private static readonly List<Region> m_DefaultRectList = new();
|
||||
private static readonly List<BaseMulti> m_DefaultMultiList = new();
|
||||
private bool m_Active;
|
||||
private ValueLinkList<NetState> _clients;
|
||||
private ValueLinkList<Item> _items;
|
||||
private ValueLinkList<Mobile> _mobiles;
|
||||
private List<BaseMulti> _multis = new();
|
||||
private List<BaseMulti> _multis;
|
||||
private int _multisVersion;
|
||||
private List<Region> _regions;
|
||||
|
||||
public Sector(int x, int y, Map owner)
|
||||
|
|
@ -1372,9 +1374,11 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
|
||||
public List<Region> Regions => _regions ?? m_DefaultRectList;
|
||||
|
||||
internal List<BaseMulti> Multis => _multis;
|
||||
internal List<BaseMulti> Multis => _multis ?? m_DefaultMultiList;
|
||||
|
||||
internal ref ValueLinkList<Mobile> Mobiles => ref _mobiles;
|
||||
internal int MultisVersion => _multisVersion;
|
||||
|
||||
internal ref readonly ValueLinkList<Mobile> Mobiles => ref _mobiles;
|
||||
|
||||
internal ref readonly ValueLinkList<Item> Items => ref _items;
|
||||
|
||||
|
|
@ -1503,12 +1507,17 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
|
||||
public void OnMultiEnter(BaseMulti multi)
|
||||
{
|
||||
_multis ??= new List<BaseMulti>();
|
||||
_multis.Add(multi);
|
||||
_multisVersion++;
|
||||
}
|
||||
|
||||
public void OnMultiLeave(BaseMulti multi)
|
||||
{
|
||||
_multis.Remove(multi);
|
||||
if (_multis?.Remove(multi) == true)
|
||||
{
|
||||
_multisVersion++;
|
||||
}
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue