fix: Removes LINQ from Map.cs (#834)
* Removes LINQ from Map * Removes broken GetObjectsInRange with items/mobile flags.
This commit is contained in:
parent
5019ce9694
commit
284c3d0f34
6 changed files with 833 additions and 87 deletions
665
Projects/Benchmarks/Benchmarks/Map/MapSelectors.cs
Normal file
665
Projects/Benchmarks/Benchmarks/Map/MapSelectors.cs
Normal file
|
|
@ -0,0 +1,665 @@
|
|||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using Server;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Benchmarks
|
||||
{
|
||||
[SimpleJob(RuntimeMoniker.NetCoreApp50)]
|
||||
public class MapSelectors
|
||||
{
|
||||
static readonly Sector sector = new Sector();
|
||||
static Server.Rectangle2D bounds = new Server.Rectangle2D(0, 0, 100, 100);
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
for (int i = 0; i < 50; ++i)
|
||||
{
|
||||
sector.Multis.Add(new BaseMulti());
|
||||
}
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
{
|
||||
sector.BItems.Add(new BItem());
|
||||
}
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
{
|
||||
sector.Mobiles.Add(new Mobile());
|
||||
}
|
||||
}
|
||||
|
||||
#region MultiTiles
|
||||
[Benchmark]
|
||||
public void SelectMultiTilesNew()
|
||||
{
|
||||
foreach(StaticTile[] tiles in SelectMultiTiles(sector, bounds))
|
||||
{
|
||||
for(int i = 0; i < tiles.Length; ++i)
|
||||
{
|
||||
int id = tiles[i].ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SelectMultiTilesLinq()
|
||||
{
|
||||
foreach(StaticTile[] tiles in SelectMultiTilesLinq(sector, bounds))
|
||||
{
|
||||
for(int i = 0; i < tiles.Length; ++i)
|
||||
{
|
||||
int id = tiles[i].ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<StaticTile[]> SelectMultiTilesLinq(Sector s, Server.Rectangle2D bounds)
|
||||
{
|
||||
foreach (var o in s.Multis.Where(o => o != null && !o.Deleted))
|
||||
{
|
||||
var c = o.Components;
|
||||
|
||||
int x, y, xo, yo;
|
||||
StaticTile[] t, r;
|
||||
|
||||
for (x = bounds.Start.X; x < bounds.End.X; x++)
|
||||
{
|
||||
xo = x - (o.X + c.Min.X);
|
||||
|
||||
if (xo < 0 || xo >= c.Width)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (y = bounds.Start.Y; y < bounds.End.Y; y++)
|
||||
{
|
||||
yo = y - (o.Y + c.Min.Y);
|
||||
|
||||
if (yo < 0 || yo >= c.Height)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
t = c.Tiles[xo][yo];
|
||||
|
||||
if (t.Length <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
r = new StaticTile[t.Length];
|
||||
|
||||
for (var i = 0; i < t.Length; i++)
|
||||
{
|
||||
r[i] = t[i];
|
||||
r[i].Z += o.Z;
|
||||
}
|
||||
|
||||
yield return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<StaticTile[]> SelectMultiTiles(Sector s, Server.Rectangle2D bounds)
|
||||
{
|
||||
for (int l = s.Multis.Count - 1; l >= 0; --l)
|
||||
{
|
||||
BaseMulti o = s.Multis[l];
|
||||
if (o != null && !o.Deleted)
|
||||
{
|
||||
MultiComponentList c = o.Components;
|
||||
|
||||
int x, y, xo, yo;
|
||||
StaticTile[] t, r;
|
||||
|
||||
for (x = bounds.Start.X; x < bounds.End.X; x++)
|
||||
{
|
||||
xo = x - (o.X + c.Min.X);
|
||||
|
||||
if (xo < 0 || xo >= c.Width)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (y = bounds.Start.Y; y < bounds.End.Y; y++)
|
||||
{
|
||||
yo = y - (o.Y + c.Min.Y);
|
||||
|
||||
if (yo < 0 || yo >= c.Height)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
t = c.Tiles[xo][yo];
|
||||
|
||||
if (t.Length <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
r = new StaticTile[t.Length];
|
||||
|
||||
for (var i = 0; i < t.Length; i++)
|
||||
{
|
||||
r[i] = t[i];
|
||||
r[i].Z += o.Z;
|
||||
}
|
||||
|
||||
yield return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Multis
|
||||
[Benchmark]
|
||||
public void SelectMultisNew()
|
||||
{
|
||||
SelectMultis(sector, bounds);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SelectMultisLinq()
|
||||
{
|
||||
SelectMultisLinq(sector, bounds);
|
||||
}
|
||||
|
||||
public IEnumerable<BaseMulti> SelectMultisLinq(Sector s, Server.Rectangle2D bounds)
|
||||
{
|
||||
return s.Multis.Where(o => o != null && !o.Deleted && bounds.Contains(o.Location));
|
||||
}
|
||||
|
||||
public IEnumerable<BaseMulti> SelectMultis(Sector s, Server.Rectangle2D bounds)
|
||||
{
|
||||
List<BaseMulti> entities = new List<BaseMulti>(s.Multis.Count);
|
||||
for (int i = s.Multis.Count - 1; i >= 0; --i)
|
||||
{
|
||||
BaseMulti BItem = s.Multis[i];
|
||||
if (BItem != null && !BItem.Deleted && bounds.Contains(BItem.Location))
|
||||
entities.Add(BItem);
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BItems
|
||||
[Benchmark]
|
||||
public void SelectBItemsNew()
|
||||
{
|
||||
SelectBItems<BItem>(sector, bounds);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SelectBItemsLinq()
|
||||
{
|
||||
SelectBItemsLinq<BItem>(sector, bounds);
|
||||
}
|
||||
|
||||
public IEnumerable<T> SelectBItemsLinq<T>(Sector s, Server.Rectangle2D bounds) where T : BItem
|
||||
{
|
||||
return s.BItems.OfType<T>().Where(o => o != null && !o.Deleted && o.Parent == null && bounds.Contains(o.Location));
|
||||
}
|
||||
|
||||
public IEnumerable<T> SelectBItems<T>(Sector s, Server.Rectangle2D bounds) where T : BItem
|
||||
{
|
||||
List<T> entities = new List<T>(s.BItems.Count);
|
||||
Type type = typeof(T);
|
||||
for (int i = s.BItems.Count - 1; i >= 0; --i)
|
||||
{
|
||||
BItem BItem = s.BItems[i];
|
||||
if (BItem != null && !BItem.Deleted && BItem.Parent == null && bounds.Contains(BItem.Location) && type.IsAssignableFrom(BItem.GetType()))
|
||||
entities.Add(BItem as T);
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
[Benchmark]
|
||||
public void SelectMobilesNew()
|
||||
{
|
||||
SelectMobiles<Mobile>(sector, bounds);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SelectMobilesLinq()
|
||||
{
|
||||
SelectMobilesLinq<Mobile>(sector, bounds);
|
||||
}
|
||||
|
||||
public IEnumerable<T> SelectMobilesLinq<T>(Sector s, Server.Rectangle2D bounds) where T : Mobile
|
||||
{
|
||||
return s.Mobiles.OfType<T>().Where(o => o != null && !o.Deleted && bounds.Contains(o.Location));
|
||||
}
|
||||
|
||||
public IEnumerable<T> SelectMobiles<T>(Sector s, Server.Rectangle2D bounds) where T : Mobile
|
||||
{
|
||||
List<T> entities = new List<T>(s.Mobiles.Count);
|
||||
Type type = typeof(T);
|
||||
for (int i = s.Mobiles.Count - 1; i >= 0; --i)
|
||||
{
|
||||
Mobile mob = s.Mobiles[i];
|
||||
if (mob != null && !mob.Deleted && bounds.Contains(mob.Location) && type.IsAssignableFrom(mob.GetType()))
|
||||
entities.Add(mob as T);
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Entities
|
||||
[Benchmark]
|
||||
public void SelectEntitiesNew()
|
||||
{
|
||||
SelectEntities(sector, bounds);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void SelectEntitiesLinq()
|
||||
{
|
||||
SelectEntitiesLinq(sector, bounds);
|
||||
}
|
||||
|
||||
public IEnumerable<Server.IEntity> SelectEntitiesLinq(Sector s, Server.Rectangle2D bounds)
|
||||
{
|
||||
return Enumerable.Empty<IEntity>()
|
||||
.Union(s.Mobiles.Where(o => o != null && !o.Deleted))
|
||||
.Union(s.BItems.Where(o => o != null && !o.Deleted && o.Parent == null))
|
||||
.Where(o => bounds.Contains(o.Location));
|
||||
}
|
||||
|
||||
private readonly List<Server.IEntity> entities = new (10);
|
||||
public IEnumerable<Server.IEntity> SelectEntities(Sector s, Server.Rectangle2D bounds)
|
||||
{
|
||||
entities.Clear();
|
||||
entities.Capacity = s.Mobiles.Count + s.BItems.Count;
|
||||
for (int i = s.Mobiles.Count - 1, j = s.BItems.Count - 1; i >= 0 || j >= 0; --i, --j)
|
||||
{
|
||||
if (j >= 0)
|
||||
{
|
||||
BItem BItem = s.BItems[j];
|
||||
if (BItem != null && !BItem.Deleted && BItem.Parent == null && bounds.Contains(BItem.Location))
|
||||
entities.Add(BItem);
|
||||
}
|
||||
if (i >= 0)
|
||||
{
|
||||
Mobile mob = s.Mobiles[i];
|
||||
if (mob != null && !mob.Deleted && bounds.Contains(mob.Location))
|
||||
entities.Add(mob);
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
public class BItem : Server.IPoint3D, IEntity
|
||||
{
|
||||
public object Parent { get; set; } = null;
|
||||
|
||||
public bool Deleted { get; set; } = false;
|
||||
|
||||
public int Z { get; set; } = 1;
|
||||
|
||||
public int X { get; set; } = 1;
|
||||
|
||||
public int Y { get; set; } = 1;
|
||||
|
||||
public Serial Serial => throw new System.NotImplementedException();
|
||||
|
||||
public Point3D Location { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
public Map Map { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
|
||||
public Region Region => throw new System.NotImplementedException();
|
||||
|
||||
public string Name { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
public int Hue { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
public Direction Direction { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
public DateTime Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
public int TypeRef => throw new NotImplementedException();
|
||||
|
||||
Point3D IEntity.Location => throw new NotImplementedException();
|
||||
|
||||
Map IEntity.Map => throw new NotImplementedException();
|
||||
|
||||
int IPoint3D.Z => throw new NotImplementedException();
|
||||
|
||||
int IPoint2D.X => throw new NotImplementedException();
|
||||
|
||||
int IPoint2D.Y => throw new NotImplementedException();
|
||||
|
||||
DateTime ISerializable.Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
DateTime ISerializable.LastSerialized { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
long ISerializable.SavePosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
BufferWriter ISerializable.SaveBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
int ISerializable.TypeRef => throw new NotImplementedException();
|
||||
|
||||
Serial ISerializable.Serial => throw new NotImplementedException();
|
||||
|
||||
bool ISerializable.Deleted => throw new NotImplementedException();
|
||||
|
||||
public BItem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void ProcessDelta()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnStatsQuery(Server.Mobile m)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void InvalidateProperties()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public int CompareTo(IEntity other)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void MoveToWorld(Point3D location, Map map)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool InRange(Point2D p, int range)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool InRange(Point3D p, int range)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RemoveBItem(BItem BItem)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void BeforeSerialize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Deserialize(IGenericReader reader)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Serialize(IGenericWriter writer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetTypeRef(Type type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void IEntity.MoveToWorld(Point3D location, Map map)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void IEntity.ProcessDelta()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool IEntity.InRange(Point2D p, int range)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool IEntity.InRange(Point3D p, int range)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void ISerializable.BeforeSerialize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void ISerializable.Deserialize(IGenericReader reader)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void ISerializable.Serialize(IGenericWriter writer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void ISerializable.Delete()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void ISerializable.SetTypeRef(Type type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RemoveItem(Item item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class Mobile : Server.IPoint3D, IEntity
|
||||
{
|
||||
public bool Deleted { get; set; } = false;
|
||||
|
||||
public int Z { get; set; } = 1;
|
||||
|
||||
public int X { get; set; } = 1;
|
||||
|
||||
public int Y { get; set; } = 1;
|
||||
|
||||
public Serial Serial => throw new System.NotImplementedException();
|
||||
|
||||
public Point3D Location { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
public Map Map { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
|
||||
public Region Region => throw new System.NotImplementedException();
|
||||
|
||||
public string Name { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
public int Hue { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
public Direction Direction { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); }
|
||||
public DateTime Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
public int TypeRef => throw new NotImplementedException();
|
||||
|
||||
Point3D IEntity.Location => throw new NotImplementedException();
|
||||
|
||||
Map IEntity.Map => throw new NotImplementedException();
|
||||
|
||||
int IPoint3D.Z => throw new NotImplementedException();
|
||||
|
||||
int IPoint2D.X => throw new NotImplementedException();
|
||||
|
||||
int IPoint2D.Y => throw new NotImplementedException();
|
||||
|
||||
DateTime ISerializable.Created { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
DateTime ISerializable.LastSerialized { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
long ISerializable.SavePosition { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
BufferWriter ISerializable.SaveBuffer { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
int ISerializable.TypeRef => throw new NotImplementedException();
|
||||
|
||||
Serial ISerializable.Serial => throw new NotImplementedException();
|
||||
|
||||
bool ISerializable.Deleted => throw new NotImplementedException();
|
||||
|
||||
public Mobile()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void ProcessDelta()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnStatsQuery(Server.Mobile m)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void InvalidateProperties()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public int CompareTo(IEntity other)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void MoveToWorld(Point3D location, Map map)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool InRange(Point2D p, int range)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool InRange(Point3D p, int range)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RemoveBItem(BItem BItem)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void BeforeSerialize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Deserialize(IGenericReader reader)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Serialize(IGenericWriter writer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetTypeRef(Type type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void IEntity.MoveToWorld(Point3D location, Map map)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void IEntity.ProcessDelta()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool IEntity.InRange(Point2D p, int range)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool IEntity.InRange(Point3D p, int range)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void ISerializable.BeforeSerialize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void ISerializable.Deserialize(IGenericReader reader)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void ISerializable.Serialize(IGenericWriter writer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void ISerializable.Delete()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void ISerializable.SetTypeRef(Type type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RemoveItem(Item item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class BaseMulti : BItem
|
||||
{
|
||||
public MultiComponentList Components = MultiComponentList.Empty;
|
||||
|
||||
public BaseMulti()
|
||||
{
|
||||
for (int i = 0; i < 20; ++i)
|
||||
for (int j = 0; j < 20; ++j)
|
||||
for (int z = 0; z < 20; ++z)
|
||||
Components.Add(123, i, j, z);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class Sector
|
||||
{
|
||||
public List<BItem> BItems { get; set; } = new List<BItem>();
|
||||
public List<Mobile> Mobiles { get; set; } = new List<Mobile>();
|
||||
public List<BaseMulti> Multis { get; set; } = new List<BaseMulti>();
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,8 @@ namespace Benchmarks
|
|||
// var textEncoding = BenchmarkRunner.Run<BenchmarkTextEncoding>();
|
||||
// var logging = BenchmarkRunner.Run<BenchmarkConsoleLogging>();
|
||||
// var gumpPacket = BenchmarkRunner.Run<OutgoingGumpPacketBenchmarks>();
|
||||
// MapSelectors.Init();
|
||||
// var mapSelectors = BenchmarkRunner.Run<MapSelectors>();
|
||||
// var rngTest = BenchmarkRunner.Run<BenchmarkXoshiro>();
|
||||
var doubleRngText = BenchmarkRunner.Run<BenchmarkDoubleVsFixed>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
|
@ -54,49 +55,97 @@ namespace Server
|
|||
|
||||
public static IEnumerable<NetState> SelectClients(Sector s, Rectangle2D bounds)
|
||||
{
|
||||
return s.Clients.Where(o => o?.Mobile?.Deleted == false && bounds.Contains(o.Mobile.Location));
|
||||
var clients = new List<NetState>(s.Clients.Count);
|
||||
foreach (var client in s.Clients)
|
||||
{
|
||||
var m = client.Mobile;
|
||||
|
||||
if (m?.Deleted == false && bounds.Contains(m.Location))
|
||||
{
|
||||
clients.Add(client);
|
||||
}
|
||||
}
|
||||
|
||||
return clients;
|
||||
}
|
||||
|
||||
public static IEnumerable<IEntity> SelectEntities(Sector s, Rectangle2D bounds) =>
|
||||
SelectEntities(s, true, true, bounds);
|
||||
|
||||
public static IEnumerable<IEntity> SelectEntities(Sector s, bool items, bool mobiles, Rectangle2D bounds)
|
||||
public static IEnumerable<IEntity> SelectEntities(Sector s, Rectangle2D bounds)
|
||||
{
|
||||
var eable = Enumerable.Empty<IEntity>();
|
||||
if (mobiles)
|
||||
var entities = new List<IEntity>(s.Mobiles.Count + s.Items.Count);
|
||||
for (int i = s.Mobiles.Count - 1, j = s.Items.Count - 1; i >= 0 || j >= 0; --i, --j)
|
||||
{
|
||||
eable = eable.Union(s.Mobiles.Where(o => o?.Deleted == false));
|
||||
}
|
||||
if (j >= 0)
|
||||
{
|
||||
Item item = s.Items[j];
|
||||
if (item is { Deleted: false, Parent: null } && bounds.Contains(item.Location))
|
||||
{
|
||||
entities.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (items)
|
||||
{
|
||||
eable = eable.Union(s.Items.Where(o => o?.Deleted == false && o.Parent == null));
|
||||
if (i >= 0)
|
||||
{
|
||||
Mobile mob = s.Mobiles[i];
|
||||
if (mob is { Deleted: false } && bounds.Contains(mob.Location))
|
||||
{
|
||||
entities.Add(mob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return eable.Where(o => bounds.Contains(o.Location));
|
||||
return entities;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> SelectMobiles<T>(Sector s, Rectangle2D bounds) where T : Mobile
|
||||
{
|
||||
return s.Mobiles.OfType<T>().Where(o => !o.Deleted && bounds.Contains(o.Location));
|
||||
var entities = new List<T>(s.Mobiles.Count);
|
||||
for (int i = s.Mobiles.Count - 1; i >= 0; --i)
|
||||
{
|
||||
if (s.Mobiles[i] is T { Deleted: false } mob && bounds.Contains(mob.Location))
|
||||
{
|
||||
entities.Add(mob);
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> SelectItems<T>(Sector s, Rectangle2D bounds) where T : Item
|
||||
{
|
||||
return s.Items.OfType<T>()
|
||||
.Where(o => o.Deleted == false && o.Parent == null && bounds.Contains(o.Location));
|
||||
var entities = new List<T>(s.Items.Count);
|
||||
for (int i = s.Items.Count - 1; i >= 0; --i)
|
||||
{
|
||||
if (s.Items[i] is T { Deleted: false, Parent: null } item && bounds.Contains(item.Location))
|
||||
{
|
||||
entities.Add(item);
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public static IEnumerable<BaseMulti> SelectMultis(Sector s, Rectangle2D bounds)
|
||||
{
|
||||
return s.Multis.Where(o => o?.Deleted == false && bounds.Contains(o.Location));
|
||||
var entities = new List<BaseMulti>(s.Multis.Count);
|
||||
for (int i = s.Multis.Count - 1; i >= 0; --i)
|
||||
{
|
||||
BaseMulti multi = s.Multis[i];
|
||||
if (multi is { Deleted: false } && bounds.Contains(multi.Location))
|
||||
{
|
||||
entities.Add(multi);
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public static IEnumerable<StaticTile[]> SelectMultiTiles(Sector s, Rectangle2D bounds)
|
||||
{
|
||||
foreach (var o in s.Multis.Where(o => o?.Deleted == false))
|
||||
for (int l = s.Multis.Count - 1; l >= 0; --l)
|
||||
{
|
||||
var c = o.Components;
|
||||
BaseMulti o = s.Multis[l];
|
||||
if (o?.Deleted != false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
MultiComponentList c = o.Components;
|
||||
|
||||
int x, y, xo, yo;
|
||||
StaticTile[] t, r;
|
||||
|
|
@ -143,10 +192,8 @@ namespace Server
|
|||
public static Map.PooledEnumerable<NetState> GetClients(Map map, Rectangle2D bounds) =>
|
||||
Map.PooledEnumerable<NetState>.Instantiate(map, bounds, ClientSelector ?? SelectClients);
|
||||
|
||||
public static Map.PooledEnumerable<IEntity> GetEntities(
|
||||
Map map, Rectangle2D bounds, bool items = true,
|
||||
bool mobiles = true
|
||||
) => Map.PooledEnumerable<IEntity>.Instantiate(map, bounds, EntitySelector ?? SelectEntities);
|
||||
public static Map.PooledEnumerable<IEntity> GetEntities(Map map, Rectangle2D bounds) =>
|
||||
Map.PooledEnumerable<IEntity>.Instantiate(map, bounds, EntitySelector ?? SelectEntities);
|
||||
|
||||
public static Map.PooledEnumerable<Mobile> GetMobiles(Map map, Rectangle2D bounds) =>
|
||||
GetMobiles<Mobile>(map, bounds);
|
||||
|
|
@ -272,9 +319,6 @@ namespace Server
|
|||
public const int SectorShift = 4;
|
||||
public const int SectorActiveRange = 2;
|
||||
|
||||
private static readonly Queue<List<Item>> m_FixPool = new(128);
|
||||
private static readonly List<Item> m_EmptyFixItems = new();
|
||||
|
||||
private static ILogger _logger;
|
||||
private static ILogger Logger => _logger ??= LogFactory.GetLogger(typeof(Map));
|
||||
|
||||
|
|
@ -389,9 +433,55 @@ namespace Server
|
|||
|
||||
public int CompareTo(Map other) => other == null ? -1 : MapID.CompareTo(other.MapID);
|
||||
|
||||
public static string[] GetMapNames() => Maps.Where(m => m != null).Select(m => m.Name).ToArray();
|
||||
public static string[] GetMapNames()
|
||||
{
|
||||
var mapCount = 0;
|
||||
for (var i = 0; i < Maps.Length; i++)
|
||||
{
|
||||
var map = Maps[i];
|
||||
if (map != null)
|
||||
{
|
||||
mapCount++;
|
||||
}
|
||||
}
|
||||
|
||||
public static Map[] GetMapValues() => Maps.Where(m => m != null).ToArray();
|
||||
var mapNames = new string[mapCount];
|
||||
for (int i = 0, mIndex = 0; i < Maps.Length; i++)
|
||||
{
|
||||
var map = Maps[i];
|
||||
if (map != null)
|
||||
{
|
||||
mapNames[mIndex++] = map.Name;
|
||||
}
|
||||
}
|
||||
|
||||
return mapNames;
|
||||
}
|
||||
|
||||
public static Map[] GetMapValues()
|
||||
{
|
||||
var mapCount = 0;
|
||||
for (var i = 0; i < Maps.Length; i++)
|
||||
{
|
||||
var map = Maps[i];
|
||||
if (map != null)
|
||||
{
|
||||
mapCount++;
|
||||
}
|
||||
}
|
||||
|
||||
var mapValues = new Map[mapCount];
|
||||
for (int i = 0, mIndex = 0; i < Maps.Length; i++)
|
||||
{
|
||||
var map = Maps[i];
|
||||
if (map != null)
|
||||
{
|
||||
mapValues[mIndex++] = map;
|
||||
}
|
||||
}
|
||||
|
||||
return mapValues;
|
||||
}
|
||||
|
||||
public static Map Parse(string value)
|
||||
{
|
||||
|
|
@ -498,54 +588,31 @@ namespace Server
|
|||
public IPooledEnumerable<StaticTile[]> GetMultiTilesAt(int x, int y) =>
|
||||
PooledEnumeration.GetMultiTiles(this, new Rectangle2D(x, y, 1, 1));
|
||||
|
||||
private static List<Item> AcquireFixItems(Map map, int x, int y)
|
||||
private static void AcquireFixItems(Map map, int x, int y, Item[] pool, out int length)
|
||||
{
|
||||
length = 0;
|
||||
if (map == null || map == Internal || x < 0 || x > map.Width || y < 0 || y > map.Height)
|
||||
{
|
||||
return m_EmptyFixItems;
|
||||
}
|
||||
|
||||
List<Item> pool = null;
|
||||
|
||||
lock (m_FixPool)
|
||||
{
|
||||
if (m_FixPool.Count > 0)
|
||||
{
|
||||
pool = m_FixPool.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
pool ??= new List<Item>(128); // Arbitrary limit
|
||||
|
||||
var eable = map.GetItemsInRange(new Point3D(x, y, 0), 0);
|
||||
|
||||
pool.AddRange(
|
||||
eable.Where(item => item.ItemID <= TileData.MaxItemValue && item is not BaseMulti)
|
||||
.OrderBy(item => item.Z)
|
||||
.Take(pool.Capacity)
|
||||
);
|
||||
|
||||
eable.Free();
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
private static void FreeFixItems(List<Item> pool)
|
||||
{
|
||||
if (pool == m_EmptyFixItems)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pool.Clear();
|
||||
|
||||
lock (m_FixPool)
|
||||
var eable = map.GetItemsInRange(new Point3D(x, y, 0), 0);
|
||||
foreach (var item in eable)
|
||||
{
|
||||
if (m_FixPool.Count < 128)
|
||||
if (item is not BaseMulti && item.ItemID <= TileData.MaxItemValue)
|
||||
{
|
||||
m_FixPool.Enqueue(pool);
|
||||
if (length == 128)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pool[length++] = item;
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
|
||||
Array.Sort(pool, ZComparer.Default);
|
||||
}
|
||||
|
||||
public void FixColumn(int x, int y)
|
||||
|
|
@ -555,9 +622,10 @@ namespace Server
|
|||
|
||||
GetAverageZ(x, y, out _, out var landAvg, out _);
|
||||
|
||||
var items = AcquireFixItems(this, x, y);
|
||||
var items = ArrayPool<Item>.Shared.Rent(128);
|
||||
AcquireFixItems(this, x, y, items, out var length);
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
var toFix = items[i];
|
||||
|
||||
|
|
@ -592,7 +660,7 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
for (var j = 0; j < items.Count; ++j)
|
||||
for (var j = 0; j < length; ++j)
|
||||
{
|
||||
if (j == i)
|
||||
{
|
||||
|
|
@ -622,7 +690,7 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
FreeFixItems(items);
|
||||
ArrayPool<Item>.Shared.Return(items);
|
||||
}
|
||||
|
||||
/* This could probably be re-implemented if necessary (perhaps via an ITile interface?).
|
||||
|
|
@ -1031,15 +1099,11 @@ namespace Server
|
|||
|
||||
public IPooledEnumerable<IEntity> GetObjectsInRange(Point3D p) => GetObjectsInRange(p, Core.GlobalMaxUpdateRange);
|
||||
|
||||
public IPooledEnumerable<IEntity> GetObjectsInRange(Point3D p, int range, bool items = true, bool mobiles = true) =>
|
||||
GetObjectsInBounds(
|
||||
new Rectangle2D(p.m_X - range, p.m_Y - range, range * 2 + 1, range * 2 + 1),
|
||||
items,
|
||||
mobiles
|
||||
);
|
||||
public IPooledEnumerable<IEntity> GetObjectsInRange(Point3D p, int range) =>
|
||||
GetObjectsInBounds(new Rectangle2D(p.m_X - range, p.m_Y - range, range * 2 + 1, range * 2 + 1));
|
||||
|
||||
public IPooledEnumerable<IEntity> GetObjectsInBounds(Rectangle2D bounds, bool items = true, bool mobiles = true) =>
|
||||
PooledEnumeration.GetEntities(this, bounds, items, mobiles);
|
||||
public IPooledEnumerable<IEntity> GetObjectsInBounds(Rectangle2D bounds) =>
|
||||
PooledEnumeration.GetEntities(this, bounds);
|
||||
|
||||
public IPooledEnumerable<NetState> GetClientsInRange(Point3D p) => GetClientsInRange(p, Core.GlobalMaxUpdateRange);
|
||||
|
||||
|
|
@ -1188,6 +1252,13 @@ namespace Server
|
|||
public bool CanSpawnMobile(int x, int y, int z) =>
|
||||
Region.Find(new Point3D(x, y, z), this).AllowSpawn() && CanFit(x, y, z, 16);
|
||||
|
||||
private class ZComparer : IComparer<Item>
|
||||
{
|
||||
public static readonly ZComparer Default = new();
|
||||
|
||||
public int Compare(Item x, Item y) => x!.Z.CompareTo(y!.Z);
|
||||
}
|
||||
|
||||
public Sector GetSector(Point3D p) => InternalGetSector(p.m_X >> SectorShift, p.m_Y >> SectorShift);
|
||||
|
||||
public Sector GetSector(Point2D p) => InternalGetSector(p.m_X >> SectorShift, p.m_Y >> SectorShift);
|
||||
|
|
@ -1529,9 +1600,7 @@ namespace Server
|
|||
{
|
||||
public static readonly NullEnumerable<T> Instance = new();
|
||||
|
||||
private readonly IEnumerable<T> m_Empty;
|
||||
|
||||
private NullEnumerable() => m_Empty = Enumerable.Empty<T>();
|
||||
private readonly IEnumerable<T> m_Empty = Enumerable.Empty<T>();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => m_Empty.GetEnumerator();
|
||||
|
||||
|
|
|
|||
|
|
@ -43,13 +43,18 @@ namespace Server.Commands.Generic
|
|||
return;
|
||||
}
|
||||
|
||||
var eable = map.GetObjectsInBounds(rect, items, mobiles);
|
||||
var eable = map.GetObjectsInBounds(rect);
|
||||
|
||||
var objs = new List<object>();
|
||||
|
||||
foreach (var obj in eable)
|
||||
{
|
||||
if ((!mobiles || obj is not Mobile || BaseCommand.IsAccessible(from, obj)) && ext.IsValid(obj))
|
||||
if (!mobiles && obj is Mobile || !items && obj is Item)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BaseCommand.IsAccessible(from, obj) && ext.IsValid(obj))
|
||||
{
|
||||
objs.Add(obj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,9 +273,14 @@ namespace Server.Factions
|
|||
return false;
|
||||
}
|
||||
|
||||
var eable = mob.Map.GetObjectsInRange(mob.Location, range, items, mobs);
|
||||
var eable = mob.Map.GetObjectsInRange(mob.Location, range);
|
||||
foreach (var obj in eable)
|
||||
{
|
||||
if (!mobs && obj is Mobile || !items && obj is Item)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type.IsInstanceOfType(obj))
|
||||
{
|
||||
eable.Free();
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ namespace Server.Items
|
|||
alchemyBonus = (int)(from.Skills.Alchemy.Value / (Core.AOS ? 5 : 10));
|
||||
}
|
||||
|
||||
var eable = map.GetObjectsInRange(loc, ExplosionRange, LeveledExplosion);
|
||||
var eable = map.GetObjectsInRange(loc, ExplosionRange);
|
||||
using var queue = PooledRefQueue<IEntity>.Create();
|
||||
|
||||
var toDamage = 0;
|
||||
|
|
@ -234,7 +234,7 @@ namespace Server.Items
|
|||
queue.Enqueue(entity);
|
||||
}
|
||||
}
|
||||
else if (entity is BaseExplosionPotion)
|
||||
else if (LeveledExplosion && entity is BaseExplosionPotion)
|
||||
{
|
||||
queue.Enqueue(entity);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue