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
|
|
@ -43,7 +43,6 @@ public class PacketSendProfile : BasePacketProfile
|
|||
|
||||
public static IEnumerable<PacketSendProfile> Profiles => _profiles.Values;
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public static PacketSendProfile Acquire(int packetId)
|
||||
{
|
||||
if (!_profiles.TryGetValue(packetId, out var prof))
|
||||
|
|
@ -78,7 +77,6 @@ public class PacketReceiveProfile : BasePacketProfile
|
|||
|
||||
public static IEnumerable<PacketReceiveProfile> Profiles => _profiles.Values;
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public static PacketReceiveProfile Acquire(int packetId)
|
||||
{
|
||||
if (!_profiles.TryGetValue(packetId, out var prof))
|
||||
|
|
|
|||
|
|
@ -3518,11 +3518,8 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
|
|||
}
|
||||
}
|
||||
|
||||
var tiles = map.Tiles.GetStaticTiles(x, y, true);
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(x, y))
|
||||
{
|
||||
var tile = tiles[i];
|
||||
var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
|
||||
if (!id.Surface)
|
||||
|
|
@ -3576,9 +3573,8 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
|
|||
|
||||
var surfaceZ = z;
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(x, y))
|
||||
{
|
||||
var tile = tiles[i];
|
||||
var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
|
||||
var checkZ = tile.Z;
|
||||
|
|
@ -3681,9 +3677,8 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
|
|||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
foreach (var tile in map.Tiles.GetStaticAndMultiTiles(x, y))
|
||||
{
|
||||
var tile = tiles[i];
|
||||
var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
|
||||
var checkZ = tile.Z;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,6 @@ public partial class Map
|
|||
|
||||
public ref struct MultiSectorEnumerator<T> where T : BaseMulti
|
||||
{
|
||||
private Point2D _location;
|
||||
private readonly Span<BaseMulti> _list;
|
||||
private int _index;
|
||||
private T _current;
|
||||
|
|
@ -105,8 +104,6 @@ public partial class Map
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiSectorEnumerator(Map map, Point2D loc)
|
||||
{
|
||||
_location = loc;
|
||||
|
||||
_list = map == null
|
||||
? Span<BaseMulti>.Empty
|
||||
: CollectionsMarshal.AsSpan(map.GetSector(loc.m_X, loc.m_Y).Multis);
|
||||
|
|
@ -118,8 +115,6 @@ public partial class Map
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool MoveNext()
|
||||
{
|
||||
ref var loc = ref _location;
|
||||
|
||||
while ((uint)_index < (uint)_list.Length)
|
||||
{
|
||||
var current = _list[_index++];
|
||||
|
|
|
|||
|
|
@ -1,121 +0,0 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2023 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: Map.MultiTileEnumerator.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server;
|
||||
|
||||
public partial class Map
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiTilesAtEnumerable GetMultiTilesAt(int x, int y) => GetMultiTilesAt(new Point2D(x, y));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiTilesAtEnumerable GetMultiTilesAt(Point2D p) => new(this, p);
|
||||
|
||||
public ref struct MultiTilesAtEnumerable
|
||||
{
|
||||
public static MultiTilesAtEnumerable Empty
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => new();
|
||||
}
|
||||
|
||||
private readonly Map _map;
|
||||
private readonly Point2D _location;
|
||||
|
||||
public MultiTilesAtEnumerable(Map map, Point2D loc)
|
||||
{
|
||||
_map = map;
|
||||
_location = loc;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiTilesAtEnumerator GetEnumerator() => new(_map, _location);
|
||||
}
|
||||
|
||||
public ref struct MultiTilesAtEnumerator
|
||||
{
|
||||
private Point2D _location;
|
||||
private MultiSectorEnumerator<BaseMulti> _multis;
|
||||
private BaseMulti _currentMulti;
|
||||
private StaticTile[] _current;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public MultiTilesAtEnumerator(Map map, Point2D loc)
|
||||
{
|
||||
_multis = (map == null ? MultiSectorEnumerable<BaseMulti>.Empty : map.GetMultisInSector(loc)).GetEnumerator();
|
||||
|
||||
_current = null;
|
||||
_location = loc;
|
||||
_currentMulti = null;
|
||||
}
|
||||
|
||||
private bool SetStaticTiles()
|
||||
{
|
||||
var mcl = _currentMulti.Components;
|
||||
var x = _location.X;
|
||||
var xo = x - (_currentMulti.X + mcl.Min.X);
|
||||
|
||||
var y = _location.Y;
|
||||
if (xo < 0 || xo >= mcl.Width)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var yo = y - (_currentMulti.Y + mcl.Min.Y);
|
||||
if (yo < 0 || yo >= mcl.Height)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var t = mcl.Tiles[xo][yo];
|
||||
|
||||
// TODO: Remove the allocation.
|
||||
var r = new StaticTile[t.Length];
|
||||
|
||||
for (var i = 0; i < t.Length; i++)
|
||||
{
|
||||
r[i] = t[i];
|
||||
r[i].Z += _currentMulti.Z;
|
||||
}
|
||||
|
||||
_current = r;
|
||||
return true;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool MoveNext()
|
||||
{
|
||||
while (_multis.MoveNext())
|
||||
{
|
||||
_currentMulti = _multis.Current;
|
||||
if (SetStaticTiles())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public StaticTile[] Current
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _current;
|
||||
}
|
||||
}
|
||||
}
|
||||
138
Projects/Server/Maps/Map.StaticTileEnumerator.cs
Normal file
138
Projects/Server/Maps/Map.StaticTileEnumerator.cs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2023 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: Map.StaticTileEnumerator.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server;
|
||||
|
||||
public partial class Map
|
||||
{
|
||||
public ref struct StaticTileEnumerable
|
||||
{
|
||||
public static StaticTileEnumerable Empty
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => new();
|
||||
}
|
||||
|
||||
private readonly Map _map;
|
||||
private readonly Point2D _location;
|
||||
private readonly bool _includeStatics;
|
||||
private readonly bool _includeMultis;
|
||||
|
||||
public StaticTileEnumerable(Map map, Point2D loc, bool includeStatics = true, bool includeMultis = true)
|
||||
{
|
||||
_map = map;
|
||||
_location = loc;
|
||||
_includeStatics = includeStatics;
|
||||
_includeMultis = includeMultis;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public StaticTileEnumerator GetEnumerator() => new(_map, _location, _includeStatics, _includeMultis);
|
||||
}
|
||||
|
||||
public ref struct StaticTileEnumerator
|
||||
{
|
||||
private readonly Map _map;
|
||||
private readonly Point2D _point;
|
||||
|
||||
private StaticTile[] _tiles;
|
||||
private MultiSectorEnumerator<BaseMulti> _multis;
|
||||
private BaseMulti _currentMulti;
|
||||
|
||||
private int _index;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public StaticTileEnumerator(Map map, Point2D p, bool includeStatics, bool includeMultis)
|
||||
{
|
||||
_map = map;
|
||||
_point = p;
|
||||
|
||||
if (_map == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (includeStatics)
|
||||
{
|
||||
var tiles = map.Tiles.GetStaticBlock(p.X >> SectorShift, p.Y >> SectorShift);
|
||||
_tiles = tiles[p.X & 0x7][p.Y & 0x7];
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
_multis = includeMultis
|
||||
? _map.GetMultisInSector(p).GetEnumerator()
|
||||
: MultiSectorEnumerable<BaseMulti>.Empty.GetEnumerator();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool SetMulti()
|
||||
{
|
||||
ref var multis = ref _multis;
|
||||
ref readonly var p = ref _point;
|
||||
|
||||
if (multis.MoveNext())
|
||||
{
|
||||
var multi = multis.Current;
|
||||
_currentMulti = multi;
|
||||
var components = multi!.Components;
|
||||
var location = multi!.Location;
|
||||
|
||||
int offsetX = p.X - location.X - components.Min.X;
|
||||
int offsetY = p.Y - location.Y - components.Min.Y;
|
||||
|
||||
if (offsetX >= 0 && offsetY >= 0 && offsetX < components.Width && offsetY < components.Height)
|
||||
{
|
||||
_tiles = multi.Components.Tiles[offsetX][offsetY];
|
||||
_index = -1;
|
||||
return SetTile();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool SetTile() => _tiles != null && ++_index < _tiles.Length;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool MoveNext() => _map != null && (SetTile() || SetMulti());
|
||||
|
||||
public StaticTile Current
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
if (_currentMulti == null)
|
||||
{
|
||||
return _tiles[_index];
|
||||
}
|
||||
|
||||
var location = _currentMulti.Location;
|
||||
ref readonly var tile = ref _tiles[_index];
|
||||
return new StaticTile
|
||||
{
|
||||
m_ID = tile.m_ID,
|
||||
X = tile.m_X,
|
||||
Y = tile.m_Y,
|
||||
Z = tile.m_Z + location.Z,
|
||||
m_Hue = tile.m_Hue
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -51,7 +51,6 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
|
||||
private readonly int m_SectorsWidth;
|
||||
|
||||
private readonly object tileLock = new();
|
||||
private Region m_DefaultRegion;
|
||||
|
||||
private string m_Name;
|
||||
|
|
@ -89,21 +88,7 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
|
||||
public int Season { get; set; }
|
||||
|
||||
public TileMatrix Tiles
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Tiles == null)
|
||||
{
|
||||
lock (tileLock)
|
||||
{
|
||||
m_Tiles = new TileMatrix(this, m_FileIndex, MapID, Width, Height);
|
||||
}
|
||||
}
|
||||
|
||||
return m_Tiles;
|
||||
}
|
||||
}
|
||||
public TileMatrix Tiles => m_Tiles ??= new TileMatrix(this, m_FileIndex, MapID, Width, Height);
|
||||
|
||||
public int MapID { get; }
|
||||
|
||||
|
|
@ -325,7 +310,6 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
public void FixColumn(int x, int y)
|
||||
{
|
||||
var landTile = Tiles.GetLandTile(x, y);
|
||||
var tiles = Tiles.GetStaticTiles(x, y, true);
|
||||
|
||||
GetAverageZ(x, y, out _, out var landAvg, out _);
|
||||
|
||||
|
|
@ -349,7 +333,7 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
z = landAvg;
|
||||
}
|
||||
|
||||
foreach (var tile in tiles)
|
||||
foreach (var tile in Tiles.GetStaticAndMultiTiles(x, y))
|
||||
{
|
||||
var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
|
||||
|
|
@ -400,33 +384,6 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
STArrayPool<Item>.Shared.Return(items, true);
|
||||
}
|
||||
|
||||
/* This could probably be re-implemented if necessary (perhaps via an ITile interface?).
|
||||
public List<Tile> GetTilesAt( Point2D p, bool items, bool land, bool statics )
|
||||
{
|
||||
List<Tile> list = new List<Tile>();
|
||||
|
||||
if (this == Internal)
|
||||
return list;
|
||||
|
||||
if (land)
|
||||
list.Add( Tiles.GetLandTile( p.m_X, p.m_Y ) );
|
||||
|
||||
if (statics)
|
||||
list.AddRange( Tiles.GetStaticTiles( p.m_X, p.m_Y, true ) );
|
||||
|
||||
if (items)
|
||||
{
|
||||
Sector sector = GetSector( p );
|
||||
|
||||
foreach ( Item item in sector.Items )
|
||||
if (item.AtWorldPoint( p.m_X, p.m_Y ))
|
||||
list.Add( new StaticTile( (ushort)item.ItemID, (sbyte) item.Z ) );
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets the highest surface that is lower than <paramref name="p" />.
|
||||
/// </summary>
|
||||
|
|
@ -460,11 +417,8 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
}
|
||||
}
|
||||
|
||||
var staticTiles = Tiles.GetStaticTiles(p.X, p.Y, true);
|
||||
|
||||
for (var i = 0; i < staticTiles.Length; i++)
|
||||
foreach (var tile in Tiles.GetStaticAndMultiTiles(p.X, p.Y))
|
||||
{
|
||||
var tile = staticTiles[i];
|
||||
var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
|
||||
if (id.Surface || id.Wet)
|
||||
|
|
@ -862,14 +816,14 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
return p;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool CanFit(
|
||||
Point3D p, int height, bool checkBlocksFit = false, bool checkMobiles = true,
|
||||
bool requireSurface = true
|
||||
Point3D p, int height, bool checkBlocksFit = false, bool checkMobiles = true, bool requireSurface = true
|
||||
) => CanFit(p.m_X, p.m_Y, p.m_Z, height, checkBlocksFit, checkMobiles, requireSurface);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool CanFit(
|
||||
Point2D p, int z, int height, bool checkBlocksFit = false, bool checkMobiles = true,
|
||||
bool requireSurface = true
|
||||
Point2D p, int z, int height, bool checkBlocksFit = false, bool checkMobiles = true, bool requireSurface = true
|
||||
) => CanFit(p.m_X, p.m_Y, z, height, checkBlocksFit, checkMobiles, requireSurface);
|
||||
|
||||
public bool CanFit(
|
||||
|
|
@ -903,29 +857,26 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
hasSurface = true;
|
||||
}
|
||||
|
||||
var staticTiles = Tiles.GetStaticTiles(x, y, true);
|
||||
|
||||
bool surface, impassable;
|
||||
|
||||
for (var i = 0; i < staticTiles.Length; ++i)
|
||||
foreach (var tile in Tiles.GetStaticAndMultiTiles(x, y))
|
||||
{
|
||||
var id = TileData.ItemTable[staticTiles[i].ID & TileData.MaxItemValue];
|
||||
var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
|
||||
surface = id.Surface;
|
||||
impassable = id.Impassable;
|
||||
|
||||
if ((surface || impassable) && staticTiles[i].Z + id.CalcHeight > z && z + height > staticTiles[i].Z)
|
||||
if ((surface || impassable) && tile.Z + id.CalcHeight > z && z + height > tile.Z)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (surface && !impassable && z == staticTiles[i].Z + id.CalcHeight)
|
||||
if (surface && !impassable && z == tile.Z + id.CalcHeight)
|
||||
{
|
||||
hasSurface = true;
|
||||
}
|
||||
}
|
||||
|
||||
var sector = GetSector(x, y);
|
||||
var mobs = sector.Mobiles;
|
||||
|
||||
foreach (var item in sector.Items)
|
||||
{
|
||||
|
|
@ -1122,8 +1073,6 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
return false;
|
||||
*/
|
||||
|
||||
var statics = Tiles.GetStaticTiles(point.m_X, point.m_Y, true);
|
||||
|
||||
var contains = false;
|
||||
var ltID = landTile.ID;
|
||||
|
||||
|
|
@ -1132,26 +1081,11 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
contains = ltID == InvalidLandTiles[j];
|
||||
}
|
||||
|
||||
if (contains && statics.Length == 0)
|
||||
{
|
||||
foreach (Item item in GetItemsInRange(point, 0))
|
||||
{
|
||||
if (item.Visible)
|
||||
{
|
||||
contains = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool foundStatic = false;
|
||||
|
||||
if (contains)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (var j = 0; j < statics.Length; ++j)
|
||||
foreach (var t in Tiles.GetStaticAndMultiTiles(point.m_X, point.m_Y))
|
||||
{
|
||||
var t = statics[j];
|
||||
foundStatic = true;
|
||||
|
||||
var id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
|
||||
|
||||
|
|
@ -1168,6 +1102,23 @@ public sealed partial class Map : IComparable<Map>, ISpanFormattable, ISpanParsa
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (contains && !foundStatic)
|
||||
{
|
||||
foreach (Item item in GetItemsAt(point))
|
||||
{
|
||||
if (item.Visible)
|
||||
{
|
||||
contains = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (contains)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rect = new Rectangle2D(pTop.m_X, pTop.m_Y, pBottom.m_X - pTop.m_X + 1, pBottom.m_Y - pTop.m_Y + 1);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,18 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2023 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: MultiData.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -508,13 +523,9 @@ public sealed class MultiComponentList
|
|||
oldTiles = Tiles[vx][vy];
|
||||
|
||||
var newTiles = new StaticTile[oldTiles.Length + 1];
|
||||
Array.Copy(oldTiles, newTiles, oldTiles.Length);
|
||||
|
||||
for (var i = 0; i < oldTiles.Length; ++i)
|
||||
{
|
||||
newTiles[i] = oldTiles[i];
|
||||
}
|
||||
|
||||
newTiles[oldTiles.Length] = new StaticTile((ushort)itemID, (sbyte)z);
|
||||
newTiles[^1] = new StaticTile((ushort)itemID, (sbyte)z);
|
||||
|
||||
Tiles[vx][vy] = newTiles;
|
||||
|
||||
|
|
@ -574,16 +585,8 @@ public sealed class MultiComponentList
|
|||
if (tile.Z == z && tile.Height >= minHeight)
|
||||
{
|
||||
var newTiles = new StaticTile[oldTiles.Length - 1];
|
||||
|
||||
for (var j = 0; j < i; ++j)
|
||||
{
|
||||
newTiles[j] = oldTiles[j];
|
||||
}
|
||||
|
||||
for (var j = i + 1; j < oldTiles.Length; ++j)
|
||||
{
|
||||
newTiles[j - 1] = oldTiles[j];
|
||||
}
|
||||
Array.Copy(oldTiles, newTiles, i);
|
||||
Array.Copy(oldTiles, i + 1, newTiles, i, oldTiles.Length - i - 1);
|
||||
|
||||
Tiles[vx][vy] = newTiles;
|
||||
|
||||
|
|
@ -601,16 +604,8 @@ public sealed class MultiComponentList
|
|||
TileData.ItemTable[tile.ItemId & TileData.MaxItemValue].Height >= minHeight)
|
||||
{
|
||||
var newList = new MultiTileEntry[oldList.Length - 1];
|
||||
|
||||
for (var j = 0; j < i; ++j)
|
||||
{
|
||||
newList[j] = oldList[j];
|
||||
}
|
||||
|
||||
for (var j = i + 1; j < oldList.Length; ++j)
|
||||
{
|
||||
newList[j - 1] = oldList[j];
|
||||
}
|
||||
Array.Copy(oldList, newList, i);
|
||||
Array.Copy(oldList, i + 1, newList, i, oldList.Length - i - 1);
|
||||
|
||||
List = newList;
|
||||
|
||||
|
|
@ -636,16 +631,8 @@ public sealed class MultiComponentList
|
|||
if (tile.ID == itemID && tile.Z == z)
|
||||
{
|
||||
var newTiles = new StaticTile[oldTiles.Length - 1];
|
||||
|
||||
for (var j = 0; j < i; ++j)
|
||||
{
|
||||
newTiles[j] = oldTiles[j];
|
||||
}
|
||||
|
||||
for (var j = i + 1; j < oldTiles.Length; ++j)
|
||||
{
|
||||
newTiles[j - 1] = oldTiles[j];
|
||||
}
|
||||
Array.Copy(oldTiles, newTiles, i);
|
||||
Array.Copy(oldTiles, i + 1, newTiles, i, oldTiles.Length - i - 1);
|
||||
|
||||
Tiles[vx][vy] = newTiles;
|
||||
|
||||
|
|
@ -663,16 +650,8 @@ public sealed class MultiComponentList
|
|||
tile.OffsetZ == (short)z)
|
||||
{
|
||||
var newList = new MultiTileEntry[oldList.Length - 1];
|
||||
|
||||
for (var j = 0; j < i; ++j)
|
||||
{
|
||||
newList[j] = oldList[j];
|
||||
}
|
||||
|
||||
for (var j = i + 1; j < oldList.Length; ++j)
|
||||
{
|
||||
newList[j - 1] = oldList[j];
|
||||
}
|
||||
Array.Copy(oldList, newList, i);
|
||||
Array.Copy(oldList, i + 1, newList, i, oldList.Length - i - 1);
|
||||
|
||||
List = newList;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Server.Buffers;
|
||||
|
||||
namespace Server;
|
||||
|
||||
|
|
@ -34,10 +35,8 @@ public class TileList
|
|||
}
|
||||
|
||||
TryResize(tiles.Length);
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
{
|
||||
_tiles[Count++] = tiles[i];
|
||||
}
|
||||
tiles.CopyTo(_tiles.AsSpan(Count));
|
||||
Count += tiles.Length;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
@ -46,43 +45,42 @@ public class TileList
|
|||
public void Add(StaticTile tile)
|
||||
{
|
||||
TryResize(1);
|
||||
_tiles[Count] = tile;
|
||||
++Count;
|
||||
_tiles[Count++] = tile;
|
||||
}
|
||||
|
||||
public void Add(ushort id, byte x, byte y, sbyte z, short hue = 0)
|
||||
{
|
||||
TryResize(1);
|
||||
ref var tile = ref _tiles[Count];
|
||||
ref var tile = ref _tiles[Count++];
|
||||
tile.m_ID = id;
|
||||
tile.m_X = x;
|
||||
tile.m_Y = y;
|
||||
tile.m_Z = z;
|
||||
tile.m_Hue = hue;
|
||||
++Count;
|
||||
}
|
||||
|
||||
public void Add(ushort id, sbyte z)
|
||||
{
|
||||
TryResize(1);
|
||||
_tiles[Count].m_ID = id;
|
||||
_tiles[Count].m_Z = z;
|
||||
++Count;
|
||||
ref var tile = ref _tiles[Count++];
|
||||
tile.m_ID = id;
|
||||
tile.m_X = 0;
|
||||
tile.m_Y = 0;
|
||||
tile.m_Z = z;
|
||||
tile.m_Hue = 0;
|
||||
}
|
||||
|
||||
private void TryResize(int length)
|
||||
{
|
||||
_tiles ??= new StaticTile[length];
|
||||
_tiles ??= STArrayPool<StaticTile>.Shared.Rent(length);
|
||||
|
||||
if (Count + length > _tiles.Length)
|
||||
var newLength = Count + length;
|
||||
if (newLength > _tiles.Length)
|
||||
{
|
||||
var old = _tiles;
|
||||
_tiles = new StaticTile[old.Length * 2];
|
||||
|
||||
for (var i = 0; i < old.Length; ++i)
|
||||
{
|
||||
_tiles[i] = old[i];
|
||||
}
|
||||
_tiles = STArrayPool<StaticTile>.Shared.Rent(newLength);
|
||||
old.CopyTo(_tiles.AsSpan());
|
||||
STArrayPool<StaticTile>.Shared.Return(old);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -93,9 +91,11 @@ public class TileList
|
|||
return _emptyTiles;
|
||||
}
|
||||
|
||||
Array.Resize(ref _tiles, Count);
|
||||
var tiles = _tiles;
|
||||
var tiles = new StaticTile[Count];
|
||||
_tiles.AsSpan(0, Count).CopyTo(tiles);
|
||||
|
||||
// Cleanup
|
||||
STArrayPool<StaticTile>.Shared.Return(_tiles);
|
||||
_tiles = null;
|
||||
Count = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using Server.Logging;
|
||||
|
||||
namespace Server;
|
||||
|
|
@ -158,7 +160,6 @@ public class TileMatrix
|
|||
|
||||
public StaticTile[][][] EmptyStaticBlock => _emptyStaticBlock;
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public void SetStaticBlock(int x, int y, StaticTile[][][] value)
|
||||
{
|
||||
if (x < 0 || y < 0 || x >= BlockWidth || y >= BlockHeight)
|
||||
|
|
@ -173,7 +174,6 @@ public class TileMatrix
|
|||
_staticPatches[x][y >> 5] |= 1 << (y & 0x1F);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public StaticTile[][][] GetStaticBlock(int x, int y)
|
||||
{
|
||||
if (x < 0 || y < 0 || x >= BlockWidth || y >= BlockHeight || DataStream == null || IndexStream == null)
|
||||
|
|
@ -187,31 +187,28 @@ public class TileMatrix
|
|||
|
||||
if (tiles == null)
|
||||
{
|
||||
lock (_fileShare)
|
||||
for (var i = 0; tiles == null && i < _fileShare.Count; ++i)
|
||||
{
|
||||
for (var i = 0; tiles == null && i < _fileShare.Count; ++i)
|
||||
var shared = _fileShare[i];
|
||||
|
||||
lock (shared)
|
||||
{
|
||||
var shared = _fileShare[i];
|
||||
|
||||
lock (shared)
|
||||
if (x < shared.BlockWidth && y < shared.BlockHeight)
|
||||
{
|
||||
if (x < shared.BlockWidth && y < shared.BlockHeight)
|
||||
var theirTiles = shared._staticTiles[x];
|
||||
|
||||
if (theirTiles != null)
|
||||
{
|
||||
var theirTiles = shared._staticTiles[x];
|
||||
tiles = theirTiles[y];
|
||||
}
|
||||
|
||||
if (theirTiles != null)
|
||||
if (tiles != null)
|
||||
{
|
||||
var theirBits = shared._staticPatches[x];
|
||||
|
||||
if (theirBits != null && (theirBits[y >> 5] & (1 << (y & 0x1F))) != 0)
|
||||
{
|
||||
tiles = theirTiles[y];
|
||||
}
|
||||
|
||||
if (tiles != null)
|
||||
{
|
||||
var theirBits = shared._staticPatches[x];
|
||||
|
||||
if (theirBits != null && (theirBits[y >> 5] & (1 << (y & 0x1F))) != 0)
|
||||
{
|
||||
tiles = null;
|
||||
}
|
||||
tiles = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -226,44 +223,15 @@ public class TileMatrix
|
|||
return tiles;
|
||||
}
|
||||
|
||||
public StaticTile[] GetStaticTiles(int x, int y)
|
||||
{
|
||||
var tiles = GetStaticBlock(x >> 3, y >> 3);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Map.StaticTileEnumerable GetStaticTiles(int x, int y) => new(_map, new Point2D(x, y), includeMultis: false);
|
||||
|
||||
return tiles[x & 0x7][y & 0x7];
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Map.StaticTileEnumerable GetStaticAndMultiTiles(int x, int y) => new(_map, new Point2D(x, y));
|
||||
|
||||
private readonly TileList m_TilesList = new();
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Map.StaticTileEnumerable GetMultiTiles(int x, int y) => new(_map, new Point2D(x, y), false);
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public StaticTile[] GetStaticTiles(int x, int y, bool multis)
|
||||
{
|
||||
var tiles = GetStaticBlock(x >> 3, y >> 3);
|
||||
|
||||
if (!multis)
|
||||
{
|
||||
return tiles[x & 0x7][y & 0x7];
|
||||
}
|
||||
|
||||
var any = false;
|
||||
|
||||
foreach (var multiTiles in _map.GetMultiTilesAt(x, y))
|
||||
{
|
||||
any = true;
|
||||
m_TilesList.AddRange(multiTiles);
|
||||
}
|
||||
|
||||
if (!any)
|
||||
{
|
||||
return tiles[x & 0x7][y & 0x7];
|
||||
}
|
||||
|
||||
m_TilesList.AddRange(tiles[x & 0x7][y & 0x7]);
|
||||
|
||||
return m_TilesList.ToArray();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public void SetLandBlock(int x, int y, LandTile[] value)
|
||||
{
|
||||
if (x < 0 || y < 0 || x >= BlockWidth || y >= BlockHeight)
|
||||
|
|
@ -278,7 +246,6 @@ public class TileMatrix
|
|||
_landPatches[x][y >> 5] |= 1 << (y & 0x1F);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public LandTile[] GetLandBlock(int x, int y)
|
||||
{
|
||||
if (x < 0 || y < 0 || x >= BlockWidth || y >= BlockHeight || MapStream == null)
|
||||
|
|
@ -295,32 +262,26 @@ public class TileMatrix
|
|||
return tiles;
|
||||
}
|
||||
|
||||
lock (_fileShare)
|
||||
for (var i = 0; tiles == null && i < _fileShare.Count; ++i)
|
||||
{
|
||||
for (var i = 0; tiles == null && i < _fileShare.Count; ++i)
|
||||
var shared = _fileShare[i];
|
||||
|
||||
if (x < shared.BlockWidth && y < shared.BlockHeight)
|
||||
{
|
||||
var shared = _fileShare[i];
|
||||
var theirTiles = shared._landTiles[x];
|
||||
|
||||
lock (shared)
|
||||
if (theirTiles != null)
|
||||
{
|
||||
if (x < shared.BlockWidth && y < shared.BlockHeight)
|
||||
tiles = theirTiles[y];
|
||||
}
|
||||
|
||||
if (tiles != null)
|
||||
{
|
||||
var theirBits = shared._landPatches[x];
|
||||
|
||||
if (theirBits != null && (theirBits[y >> 5] & (1 << (y & 0x1F))) != 0)
|
||||
{
|
||||
var theirTiles = shared._landTiles[x];
|
||||
|
||||
if (theirTiles != null)
|
||||
{
|
||||
tiles = theirTiles[y];
|
||||
}
|
||||
|
||||
if (tiles != null)
|
||||
{
|
||||
var theirBits = shared._landPatches[x];
|
||||
|
||||
if (theirBits != null && (theirBits[y >> 5] & (1 << (y & 0x1F))) != 0)
|
||||
{
|
||||
tiles = null;
|
||||
}
|
||||
}
|
||||
tiles = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -344,7 +305,6 @@ public class TileMatrix
|
|||
|
||||
private StaticTile[] m_TileBuffer = new StaticTile[128];
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
private unsafe StaticTile[][][] ReadStaticBlock(int x, int y)
|
||||
{
|
||||
try
|
||||
|
|
@ -440,7 +400,6 @@ public class TileMatrix
|
|||
throw new Exception("No assemblies were loaded, therefore we cannot load TileMatrix.");
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
private unsafe LandTile[] ReadLandBlock(int x, int y)
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Server;
|
||||
|
||||
|
|
@ -72,7 +71,6 @@ public class TileMatrixPatch
|
|||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
private unsafe int PatchLand(TileMatrix matrix, string dataPath, string indexPath)
|
||||
{
|
||||
using var fsData = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
|
|
@ -100,7 +98,6 @@ public class TileMatrixPatch
|
|||
return count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
private unsafe int PatchStatics(TileMatrix matrix, string dataPath, string indexPath, string lookupPath)
|
||||
{
|
||||
using var fsData = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
|
|
|
|||
|
|
@ -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