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;
|
||||
|
|
|
|||
|
|
@ -217,11 +217,8 @@ namespace Server.Items
|
|||
return false;
|
||||
}
|
||||
|
||||
var tiles = map.Tiles.GetStaticTiles(x, y, true);
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var t in map.Tiles.GetStaticAndMultiTiles(x, y))
|
||||
{
|
||||
var t = tiles[i];
|
||||
var id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
|
||||
|
||||
if ((id.Flags & TileFlag.Wall) != 0 && z + 16 > t.Z && t.Z + t.Height > z)
|
||||
|
|
|
|||
|
|
@ -328,13 +328,10 @@ public partial class InteriorDecorator : Item
|
|||
return int.MinValue;
|
||||
}
|
||||
|
||||
var tiles = map.Tiles.GetStaticTiles(item.X, item.Y, true);
|
||||
|
||||
var z = int.MinValue;
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(item.X, item.Y))
|
||||
{
|
||||
var tile = tiles[i];
|
||||
var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
|
||||
var top = tile.Z; // Confirmed : no height checks here
|
||||
|
|
|
|||
|
|
@ -431,12 +431,8 @@ namespace Server
|
|||
|
||||
public static bool IsEastFrame(int x, int y, int z)
|
||||
{
|
||||
var tiles = m_Map.Tiles.GetStaticTiles(x, y);
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var tile in m_Map.Tiles.GetStaticTiles(x, y))
|
||||
{
|
||||
var tile = tiles[i];
|
||||
|
||||
if (tile.Z == z && IsEastFrame(tile.ID))
|
||||
{
|
||||
return true;
|
||||
|
|
@ -448,12 +444,8 @@ namespace Server
|
|||
|
||||
public static bool IsSouthFrame(int x, int y, int z)
|
||||
{
|
||||
var tiles = m_Map.Tiles.GetStaticTiles(x, y);
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var tile in m_Map.Tiles.GetStaticTiles(x, y))
|
||||
{
|
||||
var tile = tiles[i];
|
||||
|
||||
if (tile.Z == z && IsSouthFrame(tile.ID))
|
||||
{
|
||||
return true;
|
||||
|
|
@ -510,12 +502,8 @@ namespace Server
|
|||
var vx = rx + region.X;
|
||||
var vy = ry + region.Y;
|
||||
|
||||
var tiles = m_Map.Tiles.GetStaticTiles(vx, vy);
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var tile in m_Map.Tiles.GetStaticTiles(vx, vy))
|
||||
{
|
||||
var tile = tiles[i];
|
||||
|
||||
var id = tile.ID;
|
||||
var z = tile.Z;
|
||||
|
||||
|
|
|
|||
|
|
@ -1462,10 +1462,9 @@ namespace Server.Multis
|
|||
}
|
||||
|
||||
var landTile = map.Tiles.GetLandTile(tx, ty);
|
||||
var tiles = map.Tiles.GetStaticTiles(tx, ty, true);
|
||||
|
||||
var hasWater = landTile.Z == p.Z &&
|
||||
(landTile.ID >= 168 && landTile.ID <= 171 || landTile.ID >= 310 && landTile.ID <= 311);
|
||||
landTile.ID is >= 168 and <= 171 or >= 310 and <= 311;
|
||||
|
||||
// int z = p.Z;
|
||||
|
||||
|
|
@ -1476,9 +1475,8 @@ namespace Server.Multis
|
|||
// if (!landTile.Ignored && top > landZ && landTop > z)
|
||||
// return false;
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(tx, ty))
|
||||
{
|
||||
var tile = tiles[i];
|
||||
var isWater = tile.ID >= 0x1796 && tile.ID <= 0x17B2;
|
||||
|
||||
if (tile.Z == p.Z && isWater)
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ namespace Server.Multis
|
|||
SetInitialState();
|
||||
}
|
||||
|
||||
return m_Current.Components;
|
||||
return m_Current!.Components;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,8 +137,6 @@ namespace Server.Multis
|
|||
var landTile = map.Tiles.GetLandTile(tileX, tileY);
|
||||
var landID = landTile.ID & TileData.MaxLandValue;
|
||||
|
||||
var oldTiles = map.Tiles.GetStaticTiles(tileX, tileY, true);
|
||||
|
||||
items.Clear();
|
||||
|
||||
foreach (var item in map.GetItemsAt(tileX, tileY))
|
||||
|
|
@ -202,13 +200,12 @@ namespace Server.Multis
|
|||
hasSurface = true;
|
||||
}
|
||||
|
||||
for (var j = 0; j < oldTiles.Length; ++j)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(tileX, tileY))
|
||||
{
|
||||
var oldTile = oldTiles[j];
|
||||
var id = TileData.ItemTable[oldTile.ID & TileData.MaxItemValue];
|
||||
var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
|
||||
if ((id.Impassable || id.Surface && !id.Background) &&
|
||||
addTileTop > oldTile.Z && oldTile.Z + id.CalcHeight > addTileZ)
|
||||
addTileTop > tile.Z && tile.Z + id.CalcHeight > addTileZ)
|
||||
{
|
||||
return HousePlacementResult.BadStatic; // Broke rule #2
|
||||
}
|
||||
|
|
@ -341,11 +338,8 @@ namespace Server.Multis
|
|||
}
|
||||
}
|
||||
|
||||
var tiles = map.Tiles.GetStaticTiles(borderPoint.X, borderPoint.Y, true);
|
||||
|
||||
for (var j = 0; j < tiles.Length; ++j)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(borderPoint.X, borderPoint.Y))
|
||||
{
|
||||
var tile = tiles[j];
|
||||
var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
|
||||
if (id.Impassable || id.Surface && !id.Background && tile.Z + id.CalcHeight > center.Z + 2)
|
||||
|
|
|
|||
|
|
@ -83,10 +83,6 @@ public static class IncomingTargetingPackets
|
|||
}
|
||||
else
|
||||
{
|
||||
var tiles = map.Tiles.GetStaticTiles(x, y, !t.DisallowMultis);
|
||||
|
||||
var valid = false;
|
||||
|
||||
if (state.HighSeas)
|
||||
{
|
||||
var id = TileData.ItemTable[graphic & TileData.MaxItemValue];
|
||||
|
|
@ -97,14 +93,19 @@ public static class IncomingTargetingPackets
|
|||
}
|
||||
|
||||
int hue = 0;
|
||||
var valid = false;
|
||||
|
||||
for (var i = 0; !valid && i < tiles.Length; ++i)
|
||||
var eable = t.DisallowMultis
|
||||
? map.Tiles.GetStaticTiles(x, y)
|
||||
: map.Tiles.GetStaticAndMultiTiles(x, y);
|
||||
|
||||
foreach (var tile in eable)
|
||||
{
|
||||
var tile = tiles[i];
|
||||
if (tile.Z == z && tile.ID == graphic)
|
||||
{
|
||||
valid = true;
|
||||
hue = tile.Hue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,11 +77,8 @@ namespace Server.Spells.Spellweaving
|
|||
return true;
|
||||
}
|
||||
|
||||
var tiles = map.Tiles.GetStaticTiles(location.X, location.Y); // Static Tiles
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var t in map.Tiles.GetStaticTiles(location.X, location.Y))
|
||||
{
|
||||
var t = tiles[i];
|
||||
var id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
|
||||
|
||||
var tand = t.ID;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue