using System.Collections.Generic; using System.Numerics; using AcDream.App.Rendering; using AcDream.Core.World; using Xunit; namespace AcDream.App.Tests.Rendering; public class InteriorEntityPartitionTests { private const uint CellA = 0xA9B40170; private const uint CellB = 0xA9B40171; private static WorldEntity Ent(uint id, uint serverGuid, uint? parentCell) => new() { Id = id, ServerGuid = serverGuid, SourceGfxObjOrSetupId = 0x01000001, Position = Vector3.Zero, Rotation = Quaternion.Identity, MeshRefs = new[] { new MeshRef(0x01000001, Matrix4x4.Identity) }, ParentCellId = parentCell, }; private static IEnumerable<(uint, Vector3, Vector3, IReadOnlyList, IReadOnlyDictionary?)> OneLb(uint lbId, params WorldEntity[] ents) => new[] { (lbId, Vector3.Zero, Vector3.Zero, (IReadOnlyList)ents, (IReadOnlyDictionary?)null) }; [Fact] public void Partitions_ByServerGuidThenParentCell_IntoThreeBuckets() { var livePlayer = Ent(1, serverGuid: 0x5000000A, parentCell: null); // live-dynamic var liveNpcInCell = Ent(2, serverGuid: 0x80001234, parentCell: CellA); // live-dynamic WINS over cell var staticA = Ent(3, serverGuid: 0, parentCell: CellA); // per-cell static var staticB = Ent(4, serverGuid: 0, parentCell: CellB); // per-cell static var scenery = Ent(5, serverGuid: 0, parentCell: null); // outdoor scenery var visible = new HashSet { CellA, CellB }; var result = InteriorEntityPartition.Partition( visible, OneLb(0xA9B4FFFF, livePlayer, liveNpcInCell, staticA, staticB, scenery)); Assert.Equal(2, result.LiveDynamic.Count); // player + npc (serverGuid != 0) Assert.Contains(livePlayer, result.LiveDynamic); Assert.Contains(liveNpcInCell, result.LiveDynamic); Assert.Single(result.ByCell[CellA]); // only staticA (npc went live-dynamic) Assert.Contains(staticA, result.ByCell[CellA]); Assert.Single(result.ByCell[CellB]); Assert.Contains(staticB, result.ByCell[CellB]); Assert.Single(result.Outdoor); Assert.Contains(scenery, result.Outdoor); } [Fact] public void Static_InNonVisibleCell_IsDropped() { var staticHidden = Ent(3, serverGuid: 0, parentCell: 0xA9B40199); // not in the visible set var visible = new HashSet { CellA }; var result = InteriorEntityPartition.Partition(visible, OneLb(0xA9B4FFFF, staticHidden)); Assert.False(result.ByCell.ContainsKey(0xA9B40199)); Assert.Empty(result.Outdoor); Assert.Empty(result.LiveDynamic); } [Fact] public void EntityWithNoMeshRefs_IsSkipped() { var noMesh = new WorldEntity { Id = 9, ServerGuid = 0, SourceGfxObjOrSetupId = 0x01000001, Position = Vector3.Zero, Rotation = Quaternion.Identity, MeshRefs = System.Array.Empty(), ParentCellId = CellA, }; var result = InteriorEntityPartition.Partition( new HashSet { CellA }, OneLb(0xA9B4FFFF, noMesh)); Assert.False(result.ByCell.ContainsKey(CellA)); } }