fix: Fixes multi search (#1601)
This commit is contained in:
parent
b5c984e5de
commit
021ebd0a88
8 changed files with 87 additions and 35 deletions
|
|
@ -116,6 +116,47 @@ public abstract partial class BaseMulti : Item
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Contains(Item item) => item.Map == Map && Contains(item.X, item.Y);
|
||||
|
||||
public bool Intersects(Rectangle2D bounds)
|
||||
{
|
||||
if (bounds.X > Location.X + Components.Max.X || bounds.X + bounds.Width < Location.X + Components.Min.X)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bounds.Y > Location.Y + Components.Max.Y || bounds.Y + bounds.Height < Location.Y + Components.Min.Y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int minX = Math.Max(bounds.X, Location.X + Components.Min.X);
|
||||
int maxX = Math.Min(bounds.X + bounds.Width, Location.X + Components.Max.X);
|
||||
int minY = Math.Max(bounds.Y, Location.Y + Components.Min.Y);
|
||||
int maxY = Math.Min(bounds.Y + bounds.Height, Location.Y + Components.Max.Y);
|
||||
|
||||
for (int x = minX; x <= maxX; x++)
|
||||
{
|
||||
for (int y = minY; y <= maxY; y++)
|
||||
{
|
||||
int offsetX = x - Location.X - Components.Min.X;
|
||||
int offsetY = y - Location.Y - Components.Min.Y;
|
||||
|
||||
if (offsetX < 0 || offsetY < 0 || offsetX >= Components.Width || offsetY >= Components.Height)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Use a ref struct
|
||||
var tiles = Components.Tiles[offsetX][offsetY];
|
||||
if (tiles.Length > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Server.Items;
|
||||
|
|
@ -26,22 +27,23 @@ public partial class Map
|
|||
public static ref readonly SectorMultiValueLinkList EmptyMultiLinkList => ref _emptyMultiLinkList;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiAtEnumerable<BaseMulti> GetMultisAt(Point3D p) => GetMultisAt<BaseMulti>(p);
|
||||
public MultiSectorEnumerable<BaseMulti> GetMultisInSector(Point3D p) => GetMultisInSector<BaseMulti>(p);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiAtEnumerable<T> GetMultisAt<T>(Point3D p) where T : BaseMulti => GetMultisAt<T>(new Point2D(p.X, p.Y));
|
||||
public MultiSectorEnumerable<BaseMulti> GetMultisInSector(Point2D p) => GetMultisInSector<BaseMulti>(p);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiAtEnumerable<BaseMulti> GetMultisAt(int x, int y) => GetMultisAt<BaseMulti>(new Point2D(x, y));
|
||||
public MultiSectorEnumerable<BaseMulti> GetMultisInSector(int x, int y) => GetMultisInSector<BaseMulti>(x, y);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiAtEnumerable<T> GetMultisAt<T>(int x, int y) where T : BaseMulti => GetMultisAt<T>(new Point2D(x, y));
|
||||
public MultiSectorEnumerable<T> GetMultisInSector<T>(Point3D p) where T : BaseMulti =>
|
||||
new(this, new Point2D(p.X, p.Y));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiAtEnumerable<BaseMulti> GetMultisAt(Point2D p) => GetMultisAt<BaseMulti>(p);
|
||||
public MultiSectorEnumerable<T> GetMultisInSector<T>(Point2D p) where T : BaseMulti => new(this, p);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiAtEnumerable<T> GetMultisAt<T>(Point2D p) where T : BaseMulti => new(this, p);
|
||||
public MultiSectorEnumerable<T> GetMultisInSector<T>(int x, int y) where T : BaseMulti => new(this, new Point2D(x, y));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiBoundsEnumerable<BaseMulti> GetMultisInRange(Point3D p) => GetMultisInRange<BaseMulti>(p);
|
||||
|
|
@ -74,34 +76,26 @@ public partial class Map
|
|||
GetMultisInBounds<T>(new Rectangle2D(x - range, y - range, range * 2 + 1, range * 2 + 1));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiBoundsEnumerable<BaseMulti> GetMultisInBounds(Rectangle2D bounds) => GetMultisInBounds<BaseMulti>(bounds);
|
||||
public MultiBoundsEnumerable<BaseMulti> GetMultisInBounds(Rectangle2D bounds, bool makeBoundsInclusive = false) =>
|
||||
GetMultisInBounds<BaseMulti>(bounds, makeBoundsInclusive);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiBoundsEnumerable<T> GetMultisInBounds<T>(Rectangle2D bounds, bool makeBoundsInclusive = false) where T : BaseMulti =>
|
||||
new(this, bounds, makeBoundsInclusive);
|
||||
|
||||
public ref struct MultiAtEnumerable<T> where T : BaseMulti
|
||||
public ref struct MultiSectorEnumerable<T>(Map map, Point2D loc) where T : BaseMulti
|
||||
{
|
||||
public static MultiAtEnumerable<T> Empty
|
||||
public static MultiSectorEnumerable<T> Empty
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => new();
|
||||
}
|
||||
|
||||
private readonly Map _map;
|
||||
private readonly Point2D _location;
|
||||
|
||||
public MultiAtEnumerable(Map map, Point2D loc)
|
||||
{
|
||||
_map = map;
|
||||
_location = loc;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiAtEnumerator<T> GetEnumerator() => new(_map, _location);
|
||||
public MultiSectorEnumerator<T> GetEnumerator() => new(map, loc);
|
||||
}
|
||||
|
||||
public ref struct MultiAtEnumerator<T> where T : BaseMulti
|
||||
public ref struct MultiSectorEnumerator<T> where T : BaseMulti
|
||||
{
|
||||
private Point2D _location;
|
||||
private readonly Span<BaseMulti> _list;
|
||||
|
|
@ -109,12 +103,13 @@ public partial class Map
|
|||
private T _current;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiAtEnumerator(Map map, Point2D loc)
|
||||
public MultiSectorEnumerator(Map map, Point2D loc)
|
||||
{
|
||||
_location = loc;
|
||||
|
||||
_list = map == null
|
||||
? Span<BaseMulti>.Empty
|
||||
: CollectionsMarshal.AsSpan(map.GetRealSector(loc.m_X, loc.m_Y).Multis);
|
||||
: CollectionsMarshal.AsSpan(map.GetSector(loc.m_X, loc.m_Y).Multis);
|
||||
|
||||
_index = 0;
|
||||
_current = null;
|
||||
|
|
@ -128,7 +123,7 @@ public partial class Map
|
|||
while ((uint)_index < (uint)_list.Length)
|
||||
{
|
||||
var current = _list[_index++];
|
||||
if (current is T { Deleted: false } o && o.X == loc.m_X && o.Y == loc.m_Y)
|
||||
if (current is T { Deleted: false } o)
|
||||
{
|
||||
_current = o;
|
||||
return true;
|
||||
|
|
@ -165,10 +160,10 @@ public partial class Map
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiEnumerator<T> GetEnumerator() => new(_map, _bounds, _makeBoundsInclusive);
|
||||
public MultiBoundsEnumerator<T> GetEnumerator() => new(_map, _bounds, _makeBoundsInclusive);
|
||||
}
|
||||
|
||||
public ref struct MultiEnumerator<T> where T : BaseMulti
|
||||
public ref struct MultiBoundsEnumerator<T> where T : BaseMulti
|
||||
{
|
||||
private readonly Map _map;
|
||||
private readonly int _sectorStartX;
|
||||
|
|
@ -183,8 +178,10 @@ public partial class Map
|
|||
private T _current;
|
||||
private int _index;
|
||||
|
||||
private HashSet<Serial> _dupes;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiEnumerator(Map map, Rectangle2D bounds, bool makeBoundsInclusive)
|
||||
public MultiBoundsEnumerator(Map map, Rectangle2D bounds, bool makeBoundsInclusive)
|
||||
{
|
||||
_map = map;
|
||||
_bounds = bounds;
|
||||
|
|
@ -213,8 +210,11 @@ public partial class Map
|
|||
while ((uint)_index < (uint)_list.Length)
|
||||
{
|
||||
var current = _list[_index++];
|
||||
if (current is T { Deleted: false } o && bounds.Contains(o.Location))
|
||||
_dupes ??= new HashSet<Serial>();
|
||||
|
||||
if (current is T { Deleted: false } o && bounds.Contains(o.Location) && !_dupes.Contains(o.Serial))
|
||||
{
|
||||
_dupes.Add(o.Serial);
|
||||
_current = o;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,14 +50,14 @@ public partial class Map
|
|||
public ref struct MultiTilesAtEnumerator
|
||||
{
|
||||
private Point2D _location;
|
||||
private MultiAtEnumerator<BaseMulti> _multis;
|
||||
private MultiSectorEnumerator<BaseMulti> _multis;
|
||||
private BaseMulti _currentMulti;
|
||||
private StaticTile[] _current;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiTilesAtEnumerator(Map map, Point2D loc)
|
||||
{
|
||||
_multis = (map == null ? MultiAtEnumerable<BaseMulti>.Empty : map.GetMultisAt(loc)).GetEnumerator();
|
||||
_multis = (map == null ? MultiSectorEnumerable<BaseMulti>.Empty : map.GetMultisInSector(loc)).GetEnumerator();
|
||||
|
||||
_current = null;
|
||||
_location = loc;
|
||||
|
|
|
|||
|
|
@ -6943,6 +6943,16 @@ public partial class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPro
|
|||
item.SendInfoTo(ns);
|
||||
}
|
||||
}
|
||||
|
||||
var range = new Rectangle2D(m_Location.X - Core.GlobalMaxUpdateRange,
|
||||
m_Location.Y - Core.GlobalMaxUpdateRange,
|
||||
Core.GlobalMaxUpdateRange * 2 + 1,
|
||||
Core.GlobalMaxUpdateRange * 2 + 1);
|
||||
|
||||
foreach (var multi in m_Map.GetMultisInBounds(range))
|
||||
{
|
||||
multi.SendInfoTo(ns);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateRegion()
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ namespace Server.Multis
|
|||
|
||||
public static BaseBoat FindBoatAt(Point3D loc, Map map)
|
||||
{
|
||||
foreach (var boat in map.GetMultisAt<BaseBoat>(loc))
|
||||
foreach (var boat in map.GetMultisInSector<BaseBoat>(loc))
|
||||
{
|
||||
if (boat.Contains(loc.X, loc.Y))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1401,7 +1401,7 @@ namespace Server.Multis
|
|||
return null;
|
||||
}
|
||||
|
||||
foreach (var house in map.GetMultisAt<BaseHouse>(loc))
|
||||
foreach (var house in map.GetMultisInSector<BaseHouse>(loc))
|
||||
{
|
||||
if (house.IsInside(loc, height))
|
||||
{
|
||||
|
|
@ -1482,8 +1482,8 @@ namespace Server.Multis
|
|||
|
||||
var mcl = Components;
|
||||
|
||||
var x = p.X - (X + mcl.Min.X);
|
||||
var y = p.Y - (Y + mcl.Min.Y);
|
||||
var x = p.X - X - mcl.Min.X;
|
||||
var y = p.Y - Y - mcl.Min.Y;
|
||||
|
||||
if (x < 0 || x >= mcl.Width || y < 0 || y >= mcl.Height)
|
||||
{
|
||||
|
|
@ -1495,6 +1495,7 @@ namespace Server.Multis
|
|||
return true;
|
||||
}
|
||||
|
||||
// TODO: Use ref struct
|
||||
var tiles = mcl.Tiles[x][y];
|
||||
|
||||
for (var j = 0; j < tiles.Length; ++j)
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ namespace Server.Multis
|
|||
{
|
||||
var yardPoint = yard[i];
|
||||
|
||||
foreach (var house in map.GetMultisAt<BaseHouse>(yardPoint))
|
||||
foreach (var house in map.GetMultisInSector<BaseHouse>(yardPoint))
|
||||
{
|
||||
if (house.Contains(yard[i]))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ namespace Server.Spells
|
|||
return false;
|
||||
}
|
||||
|
||||
foreach (var multi in map.GetMultisAt(p))
|
||||
foreach (var multi in map.GetMultisInSector(p))
|
||||
{
|
||||
if (multi is BaseHouse bh)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue