/************************************************************************* * 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 . * *************************************************************************/ 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 MultiAtEnumerator _multis; private BaseMulti _currentMulti; private StaticTile[] _current; [MethodImpl(MethodImplOptions.AggressiveInlining)] public MultiTilesAtEnumerator(Map map, Point2D loc) { _multis = (map == null ? MultiAtEnumerable.Empty : map.GetMultisAt(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; } } }