using System.Numerics; using AcDream.App.Rendering.Scene; using AcDream.App.Rendering.Walk; namespace AcDream.App.Tests.Rendering.Walk; public sealed class WalkProductionWorldDataTests { [Fact] public void BuildingShellBucketCellId_PortalLessBuildingUsesLandscapePositionCell() { const uint positionCellId = 0xF4180011u; RenderProjectionRecord record = Record( id: 0xCF418060u, position: new Vector3(53.57f, 13.874f, 160f)) with { Source = new RenderSourceMetadata() with { LocalEntityId = 0xCF418060u, SourceId = 0x01001FD3u, EffectCellId = positionCellId, BuildingShellAnchorCellId = 0, }, EntityPayload = new RenderEntityPayload() with { IsBuildingShell = true, }, }; var building = new WalkBuilding { PositionCellId = positionCellId, Portals = [], }; Assert.Equal( positionCellId, WalkProductionWorldData.BuildingShellBucketCellId(in record)); Assert.Equal( positionCellId, WalkProductionWorldData.BuildingShellBucketCellId(building)); } [Fact] public void BuildingShellBucketCellId_PortalBearingBuildingKeepsInteriorAnchor() { const uint anchorCellId = 0xF4180112u; RenderProjectionRecord record = Record( id: 0xCF41805Fu, position: new Vector3(36f, 13.8349f, 160f)) with { Source = new RenderSourceMetadata() with { LocalEntityId = 0xCF41805Fu, SourceId = 0x01001FB7u, EffectCellId = 0xF4180009u, BuildingShellAnchorCellId = anchorCellId, }, EntityPayload = new RenderEntityPayload() with { IsBuildingShell = true, }, }; var building = new WalkBuilding { PositionCellId = 0xF4180009u, Portals = [ new WalkBldPortal { OtherCellId = anchorCellId }, ], }; Assert.Equal( anchorCellId, WalkProductionWorldData.BuildingShellBucketCellId(in record)); Assert.Equal( anchorCellId, WalkProductionWorldData.BuildingShellBucketCellId(building)); } [Fact] public void BucketOutdoorRecord_UsesEveryOutdoorPhysicsShadowCellAcrossLandblockEdge() { RenderProjectionRecord record = Record( id: 0x1234u, position: new Vector3(191f, 191f, 0f)); var buckets = new Dictionary>(); WalkProductionWorldData.BucketOutdoorRecord( in record, [0xF07F0040u, 0xF0800001u, 0xF4180101u], buckets, renderCenterLbX: 0xF0, renderCenterLbY: 0x7F); Assert.Equal([0xF07F0040u, 0xF0800001u], buckets.Keys.Order()); Assert.All(buckets.Values, bucket => Assert.Equal(record, Assert.Single(bucket))); } [Fact] public void BucketOutdoorRecord_UnregisteredEffectFallsBackToRootPositionCell() { RenderProjectionRecord record = Record( id: 0x5678u, position: new Vector3(193f, 25f, 0f)); var buckets = new Dictionary>(); WalkProductionWorldData.BucketOutdoorRecord( in record, Array.Empty(), buckets, renderCenterLbX: 0xEF, renderCenterLbY: 0x7F); Assert.Equal([0xF07F0002u], buckets.Keys); Assert.Equal(record, Assert.Single(buckets[0xF07F0002u])); } [Fact] public void BucketIndoorRecord_InstallsCrossCellPartInBothInteriorCells() { RenderProjectionRecord record = Record( id: 0x48A02035u, position: new Vector3(55.25f, -46.47f, -3f)) with { Source = new RenderSourceMetadata() with { LocalEntityId = 0x48A02035u, ParentCellId = 0x8A02015Fu, }, }; var indoor = new Dictionary>(); var outdoor = new Dictionary>(); WalkProductionWorldData.BucketIndoorRecord( in record, [0x8A02015Fu, 0x8A02015Eu], indoor, outdoor); Assert.Equal([0x8A02015Eu, 0x8A02015Fu], indoor.Keys.Order()); Assert.All(indoor.Values, bucket => Assert.Equal(record, Assert.Single(bucket))); Assert.Empty(outdoor); } [Fact] public void BucketIndoorRecord_CanCrossAnExitIntoLandscapeCell() { RenderProjectionRecord record = Record( id: 0x48A02035u, position: Vector3.Zero) with { Source = new RenderSourceMetadata() with { LocalEntityId = 0x48A02035u, ParentCellId = 0x8A02015Fu, }, }; var indoor = new Dictionary>(); var outdoor = new Dictionary>(); WalkProductionWorldData.BucketIndoorRecord( in record, [0x8A02015Fu, 0x8A020021u], indoor, outdoor); Assert.Equal(record, Assert.Single(indoor[0x8A02015Fu])); Assert.Equal(record, Assert.Single(outdoor[0x8A020021u])); } [Fact] public void BucketDynamicRecord_InstallsMultipartPlayerInEveryCrossedInteriorCell() { RenderProjectionRecord record = Record( id: 0x000F4243u, position: new Vector3(58.81f, -49.42f, -0.85f)) with { Source = new RenderSourceMetadata() with { LocalEntityId = 0x000F4243u, ParentCellId = 0x8A02015Eu, }, }; var indoor = new Dictionary>(); var outdoor = new Dictionary>(); WalkProductionWorldData.BucketDynamicRecord( in record, [0x8A02015Eu, 0x8A02015Fu, 0x8A0201C1u], indoor, outdoor, renderCenterLbX: 0x8A, renderCenterLbY: 0x02); Assert.Equal( [0x8A02015Eu, 0x8A02015Fu, 0x8A0201C1u], indoor.Keys.Order()); Assert.All( indoor.Values, bucket => Assert.Equal(record, Assert.Single(bucket))); Assert.Empty(outdoor); } [Fact] public void BucketDynamicRecord_UnregisteredInteriorEffectFallsBackToParentCell() { RenderProjectionRecord record = Record( id: 0x00001234u, position: Vector3.Zero) with { Source = new RenderSourceMetadata() with { LocalEntityId = 0x00001234u, ParentCellId = 0x8A02015Fu, }, }; var indoor = new Dictionary>(); var outdoor = new Dictionary>(); WalkProductionWorldData.BucketDynamicRecord( in record, Array.Empty(), indoor, outdoor, renderCenterLbX: 0x8A, renderCenterLbY: 0x02); Assert.Equal(record, Assert.Single(indoor[0x8A02015Fu])); Assert.Empty(outdoor); } [Fact] public void ResolveDynamicRenderCells_EquippedDescendantInheritsRootCellArray() { RenderProjectionRecord wand = Record( id: 0x800045EEu, position: Vector3.Zero) with { Source = new RenderSourceMetadata() with { LocalEntityId = 0x800045EEu, ParentCellId = 0xF4180104u, }, EntityPayload = new RenderEntityPayload() with { CasterIdentity = RenderCasterIdentityKind.EquippedChild, }, }; var owners = new Dictionary> { [0x5000000Au] = [0xF4180106u, 0xF4180104u], }; var parents = new Dictionary { [0x800045EEu] = 0x80000461u, [0x80000461u] = 0x5000000Au, }; IReadOnlyList cells = WalkProductionWorldData.ResolveDynamicRenderCells( in wand, id => owners.TryGetValue(id, out IReadOnlyList? value) ? value : Array.Empty(), id => parents.TryGetValue(id, out uint value) ? value : null); Assert.Equal([0xF4180106u, 0xF4180104u], cells); } private static RenderProjectionRecord Record(uint id, Vector3 position) => new RenderProjectionRecord() with { Id = RenderProjectionId.FromRaw(id), Transform = new RenderTransform(Matrix4x4.CreateTranslation(position)), Source = new RenderSourceMetadata() with { LocalEntityId = id }, }; }