/************************************************************************* * 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 . * *************************************************************************/ using System.Runtime.CompilerServices; using Server.Items; namespace Server; public partial class Map { public readonly 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 _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 >> TileMatrix.SectorShift, p.Y >> TileMatrix.SectorShift); _tiles = tiles[p.X & 0x7][p.Y & 0x7]; _index = -1; } _multis = includeMultis ? _map.GetMultisInSector(p).GetEnumerator() : MultiSectorEnumerable.Empty.GetEnumerator(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool SetMulti() { ref var multis = ref _multis; ref readonly var p = ref _point; while (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 }; } } } }