using System.Collections.Generic; using Server.Items; using Xunit; namespace Server.Tests.Maps; [Collection("Sequential Server Tests")] public class StaticTileEnumeratorTests { [Fact] public void StaticTileEnumerator_IncludeStaticsOnlyWorks() { var map = Map.Felucca; var location = new Point2D(200, 200); // The synthetic map has no statics here; the multi must add nothing to the statics-only walk. var mapStatics = CollectTiles(map, location, includeStatics: true, includeMultis: false); TestMulti multi = null; try { multi = CreateMultiWithComponents(map, new Point3D(200, 200, 0)); var tiles = CollectTiles(map, location, includeStatics: true, includeMultis: false); Assert.Equal(mapStatics, tiles); } finally { multi?.Delete(); } } [Fact] public void StaticTileEnumerator_IncludeMultisOnlyWorks() { var map = Map.Felucca; var location = new Point2D(300, 300); TestMulti multi = null; try { // Create a multi at the location with components multi = CreateMultiWithComponents(map, new Point3D(300, 300, 0)); // Get tiles with multis only (no statics) var tiles = new List(); foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: false, includeMultis: true)) { tiles.Add(tile); } // Should include multi tiles Assert.NotEmpty(tiles); } finally { multi?.Delete(); } } [Fact] public void StaticTileEnumerator_IncludeBothStaticsAndMultisWorks() { var map = Map.Felucca; var location = new Point2D(400, 400); var mapStatics = CollectTiles(map, location, includeStatics: true, includeMultis: false); TestMulti multi = null; try { multi = CreateMultiWithComponents(map, new Point3D(400, 400, 0)); var multiTiles = CollectTiles(map, location, includeStatics: false, includeMultis: true); var tiles = CollectTiles(map, location, includeStatics: true, includeMultis: true); Assert.NotEmpty(multiTiles); Assert.Equal(mapStatics.Count + multiTiles.Count, tiles.Count); Assert.All(mapStatics, tile => Assert.Contains(tile, tiles)); Assert.All(multiTiles, tile => Assert.Contains(tile, tiles)); } finally { multi?.Delete(); } } [Fact] public void StaticTileEnumerator_MultiTileZOffsetApplied() { var map = Map.Felucca; var location = new Point2D(500, 500); var multiZ = 10; TestMulti multi = null; try { // Create a multi at Z=10 multi = CreateMultiWithComponents(map, new Point3D(500, 500, multiZ)); // Get multi tiles var tiles = new List(); foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: false, includeMultis: true)) { tiles.Add(tile); } // All tiles should have Z offset by the multi's Z position Assert.NotEmpty(tiles); Assert.All(tiles, tile => Assert.True(tile.Z >= multiZ)); } finally { multi?.Delete(); } } [Fact] public void StaticTileEnumerator_TileMatrixGetStaticAndMultiTilesWorks() { var map = Map.Felucca; var x = 700; var y = 700; TestMulti multi = null; try { // Create a multi at the location multi = CreateMultiWithComponents(map, new Point3D(700, 700, 0)); // Test the TileMatrix.GetStaticAndMultiTiles method var tiles = new List(); foreach (var tile in map.Tiles.GetStaticAndMultiTiles(x, y)) { tiles.Add(tile); } // Should include multi tiles Assert.NotEmpty(tiles); } finally { multi?.Delete(); } } [Fact] public void StaticTileEnumerator_TileMatrixGetMultiTilesWorks() { var map = Map.Felucca; var x = 800; var y = 800; TestMulti multi = null; try { // Create a multi at the location multi = CreateMultiWithComponents(map, new Point3D(800, 800, 0)); // Test the TileMatrix.GetMultiTiles method var tiles = new List(); foreach (var tile in map.Tiles.GetMultiTiles(x, y)) { tiles.Add(tile); } // Should include multi tiles Assert.NotEmpty(tiles); } finally { multi?.Delete(); } } [Fact] public void StaticTileEnumerator_MultipleMultisAtSameLocation() { var map = Map.Felucca; var location = new Point2D(900, 900); var multis = new TestMulti[2]; try { // Create two multis at the same location multis[0] = CreateMultiWithComponents(map, new Point3D(900, 900, 0)); multis[1] = CreateMultiWithComponents(map, new Point3D(900, 900, 5)); // Get all multi tiles var tiles = new List(); foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: false, includeMultis: true)) { tiles.Add(tile); } // Should include tiles from both multis Assert.NotEmpty(tiles); // We expect at least tiles from both multis Assert.True(tiles.Count >= 2); } finally { multis[0]?.Delete(); multis[1]?.Delete(); } } [Fact] public void StaticTileEnumerator_DeletedMultiSkipped() { var map = Map.Felucca; var location = new Point2D(1000, 1000); var multis = new TestMulti[2]; try { // Create two multis multis[0] = CreateMultiWithComponents(map, new Point3D(1000, 1000, 0)); multis[1] = CreateMultiWithComponents(map, new Point3D(1000, 1000, 5)); // Delete the first multi multis[0].Delete(); // Get all multi tiles var tiles = new List(); foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: false, includeMultis: true)) { tiles.Add(tile); } // Should only include tiles from the second multi Assert.NotEmpty(tiles); Assert.All(tiles, tile => Assert.True(tile.Z >= 5)); } finally { multis[0]?.Delete(); multis[1]?.Delete(); } } [Fact] public void StaticTileEnumerator_MultiWithEmptyCellDoesNotHideLaterMultis() { var map = Map.Felucca; var location = new Point2D(1101, 1100); TestMulti outer = null; TestMulti inner = null; try { // Outer's bounds cover the probe cell but it has no tile there; placing it first puts it // ahead of inner in the sector's multi list outer = new TestMulti(GappedComponents); outer.MoveToWorld(new Point3D(1100, 1100, 0), map); inner = new TestMulti(SingleTileComponents); inner.MoveToWorld(new Point3D(location.X, location.Y, 20), map); var tiles = new List(); foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics: false, includeMultis: true)) { tiles.Add(tile); } // Only inner sits at z 20; item ids are masked by tiledata, which CI does not have var single = Assert.Single(tiles); Assert.Equal(20, single.Z); } finally { outer?.Delete(); inner?.Delete(); } } // Entries after the first need non-zero flags or MultiComponentList drops them private static readonly MultiComponentList GappedComponents = new( [ new MultiTileEntry(0x1, 0, 0, 0, TileFlag.Background), new MultiTileEntry(0x2, 2, 0, 0, TileFlag.Background) ] ); private static readonly MultiComponentList SingleTileComponents = new( [ new MultiTileEntry(0x3, 0, 0, 0, TileFlag.Background) ] ); private static readonly MultiComponentList DefaultComponents = new( [ new MultiTileEntry(0x1, 0, 0, 0, 0x0), new MultiTileEntry(0x2, 1, 0, 0, 0x0) ] ); private static List CollectTiles(Map map, Point2D location, bool includeStatics, bool includeMultis) { var tiles = new List(); foreach (var tile in new Map.StaticTileEnumerable(map, location, includeStatics, includeMultis)) { tiles.Add(tile); } return tiles; } private static TestMulti CreateMultiWithComponents(Map map, Point3D location) { var multi = new TestMulti(DefaultComponents); multi.MoveToWorld(location, map); return multi; } }