fix: Fixes multi search (#1601)

This commit is contained in:
Kamron Batman 2023-11-18 12:37:26 -08:00 committed by GitHub
parent b5c984e5de
commit 021ebd0a88
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 87 additions and 35 deletions

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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()

View file

@ -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))
{

View file

@ -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)

View file

@ -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]))
{

View file

@ -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)
{