fix: Refactors getting static tiles to use enumerators (#1611)
### Summary
* Refactors getting static/multi tiles to not use allocations.
* `TileList` is now only used during bootstrapping and uses rented buffers to eliminate extra allocations.
* Replaces `StaticTile[] GetStaticTiles` with:
```cs
Map.StaticTileEnumerable GetStaticTiles(int x, int y);
Map.StaticTileEnumerable GetStaticAndMultiTiles(int x, int y);
Map.StaticTileEnumerable GetMultiTiles(int x, int y);
```
* Removes `Synchronized` and `lock` from TileMatrix. It is no longer considered a multi-thread safe system.
This commit is contained in:
parent
3b1637b2da
commit
f21c9687b2
23 changed files with 359 additions and 512 deletions
|
|
@ -462,30 +462,10 @@ namespace Server.Engines.ConPVP
|
|||
return;
|
||||
}
|
||||
|
||||
var statics = Map.Tiles.GetStaticTiles(point.X, point.Y, true);
|
||||
|
||||
if (landTile.ID == 0x244 && statics.Length == 0) // 0x244 = invalid land tile
|
||||
var foundStatics = false;
|
||||
foreach (var t in Map.Tiles.GetStaticAndMultiTiles(point.X, point.Y))
|
||||
{
|
||||
var empty = true;
|
||||
foreach (var item in Map.GetItemsAt(point))
|
||||
{
|
||||
if (item != this)
|
||||
{
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty)
|
||||
{
|
||||
HitObject(point, landTop, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (var j = 0; j < statics.Length; j++)
|
||||
{
|
||||
var t = statics[j];
|
||||
foundStatics = true;
|
||||
|
||||
var id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
|
||||
height = id.CalcHeight;
|
||||
|
|
@ -506,6 +486,25 @@ namespace Server.Engines.ConPVP
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (landTile.ID == 0x244 && foundStatics) // 0x244 = invalid land tile
|
||||
{
|
||||
var empty = true;
|
||||
foreach (var item in Map.GetItemsAt(point))
|
||||
{
|
||||
if (item != this)
|
||||
{
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty)
|
||||
{
|
||||
HitObject(point, landTop, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rect = new Rectangle2D(pTop.X, pTop.Y, pBottom.X - pTop.X + 1, pBottom.Y - pTop.Y + 1);
|
||||
|
|
@ -640,14 +639,10 @@ namespace Server.Engines.ConPVP
|
|||
|
||||
var myZ = Map?.GetAverageZ(X, Y) ?? 0;
|
||||
|
||||
var statics = Map?.Tiles?.GetStaticTiles(X, Y, true);
|
||||
|
||||
if (statics != null)
|
||||
if (Map?.Tiles != null)
|
||||
{
|
||||
for (var j = 0; j < statics.Length; j++)
|
||||
foreach (var t in Map.Tiles.GetStaticAndMultiTiles(X, Y))
|
||||
{
|
||||
var t = statics[j];
|
||||
|
||||
var id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
|
||||
height = id.CalcHeight;
|
||||
|
||||
|
|
|
|||
|
|
@ -402,12 +402,10 @@ namespace Server.Engines.Craft
|
|||
var vx = from.X + x;
|
||||
var vy = from.Y + y;
|
||||
|
||||
var tiles = map.Tiles.GetStaticTiles(vx, vy, true);
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(vx, vy))
|
||||
{
|
||||
var z = tiles[i].Z;
|
||||
var id = tiles[i].ID;
|
||||
var z = tile.Z;
|
||||
var id = tile.ID;
|
||||
|
||||
if (z + 16 > from.Z && from.Z + 16 > z && Find(id, itemIDs))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,19 +67,17 @@ public class DefBlacksmithy : CraftSystem
|
|||
{
|
||||
for (var y = -range; (!anvil || !forge) && y <= range; ++y)
|
||||
{
|
||||
var tiles = map.Tiles.GetStaticTiles(from.X + x, from.Y + y, true);
|
||||
|
||||
for (var i = 0; (!anvil || !forge) && i < tiles.Length; ++i)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(from.X + x, from.Y + y))
|
||||
{
|
||||
var id = tiles[i].ID;
|
||||
var id = tile.ID;
|
||||
|
||||
var isAnvil = id is 4015 or 4016 or 11733 or 11734;
|
||||
var isForge = id is 4017 or >= 6522 and <= 6569 or 11736;
|
||||
|
||||
if (isAnvil || isForge)
|
||||
{
|
||||
if (from.Z + 16 < tiles[i].Z || tiles[i].Z + 16 < from.Z ||
|
||||
!from.InLOS(new Point3D(from.X + x, from.Y + y, tiles[i].Z + tiles[i].Height / 2 + 1)))
|
||||
if (from.Z + 16 < tile.Z || tile.Z + 16 < from.Z ||
|
||||
!from.InLOS(new Point3D(from.X + x, from.Y + y, tile.Z + tile.Height / 2 + 1)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
@ -177,15 +179,15 @@ namespace Server.Movement
|
|||
return moveIsOk;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool CheckMovement(Mobile m, Direction d, out int newZ) => CheckMovement(m, m.Map, m.Location, d, out newZ);
|
||||
|
||||
private static bool IsOk(
|
||||
bool ignoreDoors, bool ignoreSpellFields, int ourZ, int ourTop, StaticTile[] tiles, List<Item> items
|
||||
bool ignoreDoors, bool ignoreSpellFields, int ourZ, int ourTop, Map map, int x, int y, List<Item> items
|
||||
)
|
||||
{
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var check in map.Tiles.GetStaticAndMultiTiles(x, y))
|
||||
{
|
||||
var check = tiles[i];
|
||||
var itemData = TileData.ItemTable[check.ID & TileData.MaxItemValue];
|
||||
|
||||
if (itemData.ImpassableSurface)
|
||||
|
|
@ -247,7 +249,6 @@ namespace Server.Movement
|
|||
|
||||
var cantWalk = m.CantWalk;
|
||||
var canSwim = m.CanSwim;
|
||||
var tiles = map.Tiles.GetStaticTiles(x, y, true);
|
||||
var landTile = map.Tiles.GetLandTile(x, y);
|
||||
var flags = TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags;
|
||||
var impassable = (flags & TileFlag.Impassable) != 0;
|
||||
|
|
@ -269,9 +270,8 @@ namespace Server.Movement
|
|||
|
||||
int testTop;
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(x, y))
|
||||
{
|
||||
var tile = tiles[i];
|
||||
var itemData = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
|
||||
if (m.Flying && itemData.Name.InsensitiveEquals("hover over"))
|
||||
|
|
@ -348,23 +348,14 @@ namespace Server.Movement
|
|||
continue;
|
||||
}
|
||||
|
||||
var landCheck = itemZ;
|
||||
|
||||
if (itemData.Height >= StepHeight)
|
||||
{
|
||||
landCheck += StepHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
landCheck += itemData.Height;
|
||||
}
|
||||
var landCheck = itemZ + Math.Min(itemData.Height, StepHeight);
|
||||
|
||||
if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items))
|
||||
if (IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, map, x, y, items))
|
||||
{
|
||||
newZ = ourZ;
|
||||
moveIsOk = true;
|
||||
|
|
@ -429,23 +420,14 @@ namespace Server.Movement
|
|||
continue;
|
||||
}
|
||||
|
||||
var landCheck = itemZ;
|
||||
|
||||
if (itemData.Height >= StepHeight)
|
||||
{
|
||||
landCheck += StepHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
landCheck += itemData.Height;
|
||||
}
|
||||
var landCheck = itemZ + Math.Min(itemData.Height, StepHeight);
|
||||
|
||||
if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items))
|
||||
if (IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, map, x, y, items))
|
||||
{
|
||||
newZ = ourZ;
|
||||
moveIsOk = true;
|
||||
|
|
@ -476,7 +458,7 @@ namespace Server.Movement
|
|||
}
|
||||
}
|
||||
|
||||
if (shouldCheck && IsOk(ignoreDoors, ignoreSpellFields, landCenter, testTop, tiles, items))
|
||||
if (shouldCheck && IsOk(ignoreDoors, ignoreSpellFields, landCenter, testTop, map, x, y, items))
|
||||
{
|
||||
newZ = landCenter;
|
||||
moveIsOk = true;
|
||||
|
|
@ -498,6 +480,7 @@ namespace Server.Movement
|
|||
return moveIsOk;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool CanMoveOver(Mobile m, Mobile t) =>
|
||||
!t.Alive || !m.Alive || t.IsDeadBondedPet || m.IsDeadBondedPet || t.Hidden && t.AccessLevel > AccessLevel.Player;
|
||||
|
||||
|
|
@ -529,11 +512,8 @@ namespace Server.Movement
|
|||
isSet = true;
|
||||
}
|
||||
|
||||
var staticTiles = map.Tiles.GetStaticTiles(xCheck, yCheck, true);
|
||||
|
||||
for (var i = 0; i < staticTiles.Length; ++i)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(xCheck, yCheck))
|
||||
{
|
||||
var tile = staticTiles[i];
|
||||
var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
var calcTop = tile.Z + id.CalcHeight;
|
||||
|
||||
|
|
@ -599,38 +579,55 @@ namespace Server.Movement
|
|||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Offset(Direction d, ref int x, ref int y)
|
||||
{
|
||||
switch (d & Direction.Mask)
|
||||
{
|
||||
case Direction.North:
|
||||
--y;
|
||||
break;
|
||||
{
|
||||
--y;
|
||||
break;
|
||||
}
|
||||
case Direction.South:
|
||||
++y;
|
||||
break;
|
||||
{
|
||||
++y;
|
||||
break;
|
||||
}
|
||||
case Direction.West:
|
||||
--x;
|
||||
break;
|
||||
{
|
||||
--x;
|
||||
break;
|
||||
}
|
||||
case Direction.East:
|
||||
++x;
|
||||
break;
|
||||
{
|
||||
++x;
|
||||
break;
|
||||
}
|
||||
case Direction.Right:
|
||||
++x;
|
||||
--y;
|
||||
break;
|
||||
{
|
||||
++x;
|
||||
--y;
|
||||
break;
|
||||
}
|
||||
case Direction.Left:
|
||||
--x;
|
||||
++y;
|
||||
break;
|
||||
{
|
||||
--x;
|
||||
++y;
|
||||
break;
|
||||
}
|
||||
case Direction.Down:
|
||||
++x;
|
||||
++y;
|
||||
break;
|
||||
{
|
||||
++x;
|
||||
++y;
|
||||
break;
|
||||
}
|
||||
case Direction.Up:
|
||||
--x;
|
||||
--y;
|
||||
break;
|
||||
{
|
||||
--x;
|
||||
--y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,12 +61,8 @@ namespace Server.Engines.Spawners
|
|||
return true;
|
||||
}
|
||||
|
||||
var staticTiles = map.Tiles.GetStaticTiles(x, y, true);
|
||||
|
||||
for (var i = 0; i < staticTiles.Length; ++i)
|
||||
foreach (var staticTile in map.Tiles.GetStaticAndMultiTiles(x, y))
|
||||
{
|
||||
var staticTile = staticTiles[i];
|
||||
|
||||
if (staticTile.Z == z && TileData.ItemTable[staticTile.ID & TileData.MaxItemValue].Wet)
|
||||
{
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue