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 const uint HiddenCell = 0xA9B40199; private const uint OutdoorCell = 0xA9B40020; 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_LiveAndStaticEntities_ByCellOutdoorAndFallback() { var unresolvedLive = Ent(1, serverGuid: 0x5000000A, parentCell: null); var liveNpcInCell = Ent(2, serverGuid: 0x80001234, parentCell: CellA); var staticA = Ent(3, serverGuid: 0, parentCell: CellA); var staticB = Ent(4, serverGuid: 0, parentCell: CellB); var scenery = Ent(5, serverGuid: 0, parentCell: null); var liveOutdoor = Ent(6, serverGuid: 0x80005678, parentCell: OutdoorCell); var visible = new HashSet { CellA, CellB }; var result = InteriorEntityPartition.Partition( visible, OneLb(0xA9B4FFFF, unresolvedLive, liveNpcInCell, staticA, staticB, scenery, liveOutdoor)); Assert.Single(result.LiveDynamic); Assert.Contains(unresolvedLive, result.LiveDynamic); Assert.Equal(2, result.ByCell[CellA].Count); Assert.Contains(liveNpcInCell, result.ByCell[CellA]); Assert.Contains(staticA, result.ByCell[CellA]); Assert.Single(result.ByCell[CellB]); Assert.Contains(staticB, result.ByCell[CellB]); Assert.Equal(2, result.Outdoor.Count); Assert.Contains(scenery, result.Outdoor); Assert.Contains(liveOutdoor, result.Outdoor); } [Fact] public void IndoorEntity_InNonVisibleCell_IsDropped() { var staticHidden = Ent(3, serverGuid: 0, parentCell: HiddenCell); var liveHidden = Ent(4, serverGuid: 0x80001234, parentCell: HiddenCell); var visible = new HashSet { CellA }; var result = InteriorEntityPartition.Partition( visible, OneLb(0xA9B4FFFF, staticHidden, liveHidden)); Assert.False(result.ByCell.ContainsKey(HiddenCell)); 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)); } }