From c631e09fe899fbbad63f9de0af82a4e9142885f8 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 17 Oct 2026 13:47:52 +0200 Subject: [PATCH 1/7] Floater fixtures: the grab-point test and the wiring verify run over a moving well PickupTests builds the zone over a sun and a planet on a rail, asserts the field differs between the ship's point and the item's and between start and end of the run, and checks each grab event at the zone time it was published. DrawnPoseWiringVerify gets a sun and a planet near the pickup and mine, requires the field under each to move with the drawn time, and checks the pickup's y as well as the mine's. Not compiled or run yet. Co-Authored-By: Claude Opus 5.5 --- .../Scripts/Editor/DrawnPoseWiringVerify.cs | 27 ++++++++++- tests/Aetheria.Shared.Tests/PickupTests.cs | 45 ++++++++++++++++--- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs index 8a170dbde..c24740d24 100644 --- a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs +++ b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs @@ -116,7 +116,23 @@ namespace Aetheria.EditorTools cache.FlushAsync().Wait(); var ledger = new ProvenanceLedger(); var items = new ItemManager(cache, ledger, settings, _ => { }); - var zone = new Zone(items, new PlanetSettings(), new ZonePack(), null, null); + + // A sun and a planet on a moving rail round it, both near the bodies below: the field under a floater changes with the + // drawn time, so a presenter that samples it at the step's time, drops it, or reads lead 0 for the height draws a different y. + var sunOrbit = cache.Upsert(new OrbitData { FixedPosition = new float2(-60, -40) }).Key; + var planetOrbit = cache.Upsert(new OrbitData { Parent = new CultRecordRef(sunOrbit), Distance = 40f, Phase = .3f }).Key; + var pack = new ZonePack { Radius = 5000f, Mass = 10000f }; + pack.Orbits.Add(new CultRecordRef(sunOrbit)); + pack.Orbits.Add(new CultRecordRef(planetOrbit)); + pack.Planets.Add(new CultRecordRef(cache.Upsert(new PlanetData { Name = "Wiring Sun", Orbit = new CultRecordRef(sunOrbit), Mass = 400f }).Key)); + pack.Planets.Add(new CultRecordRef(cache.Upsert(new PlanetData { Name = "Wiring Planet", Orbit = new CultRecordRef(planetOrbit), Mass = 100f }).Key)); + var curves = new PlanetSettings + { + BodyRadius = new ExponentialCurve(), + WellStrength = new ExponentialCurve { Multiplier = 1f, Exponent = 1f }, + RocheLimit = new ExponentialCurve { Constant = 2f } + }; + var zone = new Zone(items, curves, pack, null, null); var rootObject = new GameObject("Wiring Zone Root"); var rendererObject = new GameObject("Wiring Zone Renderer"); @@ -162,6 +178,12 @@ namespace Aetheria.EditorTools var mineVelocity = mine.Body.TotalVelocity; Require(Mathf.Abs(pickupVelocity.x) > 1f && Mathf.Abs(mineVelocity.y) > 1f, "The fixture's bodies stopped: a lead would not move them."); + // The field under each floater really is a function of the drawn time here, by more than the tolerance at the largest lead. + const float LargestLead = .015f; + foreach (var at in new[] { floating.Body.Position + pickupVelocity * LargestLead, mine.Body.Position + mineVelocity * LargestLead }) + Require(Mathf.Abs(DrawAhead.Height(zone, at, LargestLead) - zone.GetHeight(at, zone.ExactTime)) > 5 * Tolerance, + "The fixture's field is flat under a floater: a drawn time would not move its height."); + Vector2 baseline = default; foreach (var leadSeconds in new[] { 0f, .008f, .015f }) { @@ -176,6 +198,9 @@ namespace Aetheria.EditorTools Require(Mathf.Abs(seen.x - want.x) < Tolerance && Mathf.Abs(seen.z - want.y) < Tolerance, $"ItemPickup at lead {lead}: drawn x/z {seen.x},{seen.z}, the step plus velocity times lead {want.x},{want.y}."); + Require(Mathf.Abs(seen.y - DrawAhead.FloaterHeight(zone, settings, new float2(want.x, want.y), lead)) < Tolerance, + $"ItemPickup y {seen.y} is not on the floater layer."); + seen = mineInstance.transform.position; want = mine.Body.Position + mineVelocity * lead; Require(Mathf.Abs(seen.x - want.x) < Tolerance && Mathf.Abs(seen.z - want.y) < Tolerance, diff --git a/tests/Aetheria.Shared.Tests/PickupTests.cs b/tests/Aetheria.Shared.Tests/PickupTests.cs index 78e1d478a..acaff0075 100644 --- a/tests/Aetheria.Shared.Tests/PickupTests.cs +++ b/tests/Aetheria.Shared.Tests/PickupTests.cs @@ -64,7 +64,9 @@ public sealed class PickupTests : IDisposable }; } - private Lab Build(PickupData beam, float lifetime = 30f) + // With `wells`, the zone has a sun (a parentless rail off the ship's side, strength 400) and a planet on a moving rail round + // it (strength 25), the field a floater layer is read against; without, the zone is flat and nothing pulls on anything. + private Lab Build(PickupData beam, float lifetime = 30f, bool wells = false) { var settings = new GameplaySettings { @@ -104,7 +106,26 @@ public sealed class PickupTests : IDisposable var ledger = new ProvenanceLedger(); for (var i = 1; i <= 9000; i++) ledger.Lots[i] = new Lot { Origin = new Attributed(), Quality = 1 }; var items = new ItemManager(cache, ledger, settings, _ => { }); - var zone = new Zone(items, new PlanetSettings(), new ZonePack { Radius = 0 }, new GalaxyZone { Name = "Pickup", Owner = null }, null); + var pack = new ZonePack { Radius = 0 }; + var curves = new PlanetSettings(); + if (wells) + { + curves = new PlanetSettings + { + BodyRadius = new ExponentialCurve(), + WellStrength = new ExponentialCurve { Multiplier = 1f, Exponent = 1f }, + RocheLimit = new ExponentialCurve { Constant = 2f } + }; + var sunOrbit = cache.Upsert(new OrbitData { FixedPosition = float2(-50, 0) }).Key; + var planetOrbit = cache.Upsert(new OrbitData { Parent = new CultRecordRef(sunOrbit), Distance = 60f, Phase = .3f }).Key; + pack.Radius = 5000f; + pack.Mass = 10000f; + pack.Orbits.Add(new CultRecordRef(sunOrbit)); + pack.Orbits.Add(new CultRecordRef(planetOrbit)); + pack.Planets.Add(new CultRecordRef(cache.Upsert(new PlanetData { Name = "Sun", Orbit = new CultRecordRef(sunOrbit), Mass = 400f }).Key)); + pack.Planets.Add(new CultRecordRef(cache.Upsert(new PlanetData { Name = "Planet", Orbit = new CultRecordRef(planetOrbit), Mass = 25f }).Key)); + } + var zone = new Zone(items, curves, pack, new GalaxyZone { Name = "Pickup", Owner = null }, null); return new Lab { Items = items, Zone = zone }; } @@ -251,14 +272,26 @@ public sealed class PickupTests : IDisposable public void AGrabPointRidesTheFloaterLayerNotTheShips() { using var bag = new CompositeDisposable(); - var lab = Build(Beam()); + var lab = Build(Beam(), wells: true); var ship = Spawn(lab, float3(0, 0, 0)); var item = Drift(lab, 40, 0); - var events = Watch(ship, bag); + + // The fixture has a field to ride: it differs between the ship's point and the item's, and between the start and + // the end of the run, so a grab point read at the ship's xz or at the wrong time cannot agree with it. + var atShip = lab.Zone.GetHeight(float2(0, 0), lab.Zone.ExactTime); + var atItem = lab.Zone.GetHeight(float2(40, 0), lab.Zone.ExactTime); + Assert.True(abs(atItem - atShip) > 1f, $"the field is flat under the grab: ship {atShip}, item {atItem}"); + var start = lab.Zone.ExactTime; + + // Each event is checked at the zone time it was published, where the sim read the field. + var seen = new List<(GrabEvent Event, double Time)>(); + ship.Capabilities.Grab.Subscribe(e => seen.Add((e, lab.Zone.ExactTime))).AddTo(bag); ship.TractorCommand = 1; for (var tick = 1; tick <= 150; tick++) lab.Zone.Update(1 / 60f); - Assert.NotEmpty(events); - Assert.All(events, e => Assert.Equal(lab.Zone.GetHeight(e.TargetPosition.xz, lab.Zone.ExactTime) - 1.5f, e.TargetPosition.y, 3)); + Assert.NotEmpty(seen); + Assert.True(abs(lab.Zone.GetHeight(float2(40, 0), lab.Zone.ExactTime) - lab.Zone.GetHeight(float2(40, 0), start)) > .01f, "the wells did not move"); + Assert.All(seen, s => Assert.Equal(lab.Zone.GetHeight(s.Event.TargetPosition.xz, s.Time) - 1.5f, s.Event.TargetPosition.y, 3)); + Assert.All(seen, s => Assert.True(abs(s.Event.TargetPosition.y - (-1.5f)) > 1f, "the grab point sits on the bare layer, the field dropped")); } [Fact] From be198593ccb7d119643baa46177e319ba713f22d Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 17 Oct 2026 13:53:09 +0200 Subject: [PATCH 2/7] Floater fixtures: orbits and planets live in the run store, so the fixtures open one Co-Authored-By: Claude Opus 5.5 --- Assets/Scripts/Editor/DrawnPoseWiringVerify.cs | 2 +- tests/Aetheria.Shared.Tests/PickupTests.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs index c24740d24..6a9f8bbea 100644 --- a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs +++ b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs @@ -110,7 +110,7 @@ namespace Aetheria.EditorTools var oneCell = new Shape(1, 1); oneCell[new CultMath.int2(0, 0)] = true; - var cache = AetheriaStores.Open(Path.Combine(_work, "wiring.cc"), catalogWritable: true); + var cache = AetheriaStores.Open(Path.Combine(_work, "wiring.cc"), Path.Combine(_work, "wiring-run.cc"), catalogWritable: true); cache.Upsert(new VerseGrammar { Revision = 1 }); cache.Upsert(new SimpleCommodityData { Name = "Wiring Ore", Shape = oneCell, MaxStack = 100 }); cache.FlushAsync().Wait(); diff --git a/tests/Aetheria.Shared.Tests/PickupTests.cs b/tests/Aetheria.Shared.Tests/PickupTests.cs index acaff0075..1fee7d5a9 100644 --- a/tests/Aetheria.Shared.Tests/PickupTests.cs +++ b/tests/Aetheria.Shared.Tests/PickupTests.cs @@ -79,7 +79,8 @@ public sealed class PickupTests : IDisposable LootDropProbability = 0, LootDropVelocity = 25, FloatingItemLifetime = lifetime, ShipLayerHeight = 3f, FloaterLayerHeight = -1.5f }; - var cache = AetheriaStores.Open(Path.Combine(_root, Guid.NewGuid().ToString("N") + ".cc"), catalogWritable: true); + var id = Guid.NewGuid().ToString("N"); + var cache = AetheriaStores.Open(Path.Combine(_root, id + ".cc"), Path.Combine(_root, id + "-run.cc"), catalogWritable: true); _caches.Add(cache); cache.Upsert(new VerseGrammar { Revision = 1 }); cache.Upsert(new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = Solid(5, 5), Durability = 1000000, Mass = 1000 }); From b708d51617ba2d73d99123fdb9e606c24170fb96 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 17 Oct 2026 13:54:38 +0200 Subject: [PATCH 3/7] probe (temporary) --- tests/Aetheria.Shared.Tests/PickupTests.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/Aetheria.Shared.Tests/PickupTests.cs b/tests/Aetheria.Shared.Tests/PickupTests.cs index 1fee7d5a9..19c3dbcdf 100644 --- a/tests/Aetheria.Shared.Tests/PickupTests.cs +++ b/tests/Aetheria.Shared.Tests/PickupTests.cs @@ -118,7 +118,7 @@ public sealed class PickupTests : IDisposable RocheLimit = new ExponentialCurve { Constant = 2f } }; var sunOrbit = cache.Upsert(new OrbitData { FixedPosition = float2(-50, 0) }).Key; - var planetOrbit = cache.Upsert(new OrbitData { Parent = new CultRecordRef(sunOrbit), Distance = 60f, Phase = .3f }).Key; + var planetOrbit = cache.Upsert(new OrbitData { Parent = new CultRecordRef(sunOrbit), Distance = 90f, Phase = .9f }).Key; pack.Radius = 5000f; pack.Mass = 10000f; pack.Orbits.Add(new CultRecordRef(sunOrbit)); @@ -290,11 +290,22 @@ public sealed class PickupTests : IDisposable ship.TractorCommand = 1; for (var tick = 1; tick <= 150; tick++) lab.Zone.Update(1 / 60f); Assert.NotEmpty(seen); - Assert.True(abs(lab.Zone.GetHeight(float2(40, 0), lab.Zone.ExactTime) - lab.Zone.GetHeight(float2(40, 0), start)) > .01f, "the wells did not move"); + Assert.True(abs(lab.Zone.GetHeight(float2(40, 0), lab.Zone.ExactTime) - lab.Zone.GetHeight(float2(40, 0), start)) > .01f, $"the wells did not move: {lab.Zone.GetHeight(float2(40, 0), lab.Zone.ExactTime)} vs {lab.Zone.GetHeight(float2(40, 0), start)}"); Assert.All(seen, s => Assert.Equal(lab.Zone.GetHeight(s.Event.TargetPosition.xz, s.Time) - 1.5f, s.Event.TargetPosition.y, 3)); Assert.All(seen, s => Assert.True(abs(s.Event.TargetPosition.y - (-1.5f)) > 1f, "the grab point sits on the bare layer, the field dropped")); } + + [Fact] + public void ZProbe() + { + var lab = Build(Beam(), wells: true); + var t0 = lab.Zone.ExactTime; + var o = new System.Text.StringBuilder(); + for (var i = 0; i < 3; i++) { foreach (var p in new[] { float2(0,0), float2(40,0) }) o.Append($"[t+{lab.Zone.ExactTime - t0:0.0} {p.x}: {lab.Zone.GetHeight(p, lab.Zone.ExactTime)}] "); for (var k = 0; k < 60; k++) lab.Zone.Update(1/60f); } + Assert.Fail(o.ToString()); + } + [Fact] public void GrabEventsNameTheFloatingItem() { From b3eb6b0c37b14a1564f59f8e460394f6af59ce91 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 17 Oct 2026 13:56:32 +0200 Subject: [PATCH 4/7] Floater fixtures: planets placed where the field changes under the floaters; probe removed Co-Authored-By: Claude Opus 5.5 --- Assets/Scripts/Editor/DrawnPoseWiringVerify.cs | 2 +- tests/Aetheria.Shared.Tests/PickupTests.cs | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs index 6a9f8bbea..bba726be6 100644 --- a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs +++ b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs @@ -120,7 +120,7 @@ namespace Aetheria.EditorTools // A sun and a planet on a moving rail round it, both near the bodies below: the field under a floater changes with the // drawn time, so a presenter that samples it at the step's time, drops it, or reads lead 0 for the height draws a different y. var sunOrbit = cache.Upsert(new OrbitData { FixedPosition = new float2(-60, -40) }).Key; - var planetOrbit = cache.Upsert(new OrbitData { Parent = new CultRecordRef(sunOrbit), Distance = 40f, Phase = .3f }).Key; + var planetOrbit = cache.Upsert(new OrbitData { Parent = new CultRecordRef(sunOrbit), Distance = 40f, Phase = .125f }).Key; var pack = new ZonePack { Radius = 5000f, Mass = 10000f }; pack.Orbits.Add(new CultRecordRef(sunOrbit)); pack.Orbits.Add(new CultRecordRef(planetOrbit)); diff --git a/tests/Aetheria.Shared.Tests/PickupTests.cs b/tests/Aetheria.Shared.Tests/PickupTests.cs index 19c3dbcdf..af979eea5 100644 --- a/tests/Aetheria.Shared.Tests/PickupTests.cs +++ b/tests/Aetheria.Shared.Tests/PickupTests.cs @@ -290,22 +290,12 @@ public sealed class PickupTests : IDisposable ship.TractorCommand = 1; for (var tick = 1; tick <= 150; tick++) lab.Zone.Update(1 / 60f); Assert.NotEmpty(seen); - Assert.True(abs(lab.Zone.GetHeight(float2(40, 0), lab.Zone.ExactTime) - lab.Zone.GetHeight(float2(40, 0), start)) > .01f, $"the wells did not move: {lab.Zone.GetHeight(float2(40, 0), lab.Zone.ExactTime)} vs {lab.Zone.GetHeight(float2(40, 0), start)}"); + Assert.True(abs(lab.Zone.GetHeight(float2(40, 0), lab.Zone.ExactTime) - lab.Zone.GetHeight(float2(40, 0), start)) > .01f, "the wells did not move"); Assert.All(seen, s => Assert.Equal(lab.Zone.GetHeight(s.Event.TargetPosition.xz, s.Time) - 1.5f, s.Event.TargetPosition.y, 3)); Assert.All(seen, s => Assert.True(abs(s.Event.TargetPosition.y - (-1.5f)) > 1f, "the grab point sits on the bare layer, the field dropped")); } - [Fact] - public void ZProbe() - { - var lab = Build(Beam(), wells: true); - var t0 = lab.Zone.ExactTime; - var o = new System.Text.StringBuilder(); - for (var i = 0; i < 3; i++) { foreach (var p in new[] { float2(0,0), float2(40,0) }) o.Append($"[t+{lab.Zone.ExactTime - t0:0.0} {p.x}: {lab.Zone.GetHeight(p, lab.Zone.ExactTime)}] "); for (var k = 0; k < 60; k++) lab.Zone.Update(1/60f); } - Assert.Fail(o.ToString()); - } - [Fact] public void GrabEventsNameTheFloatingItem() { From cc243e7f7c30a26e5c7a0427671f96c143a80d47 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 17 Oct 2026 14:14:05 +0200 Subject: [PATCH 5/7] DrawnPoseWiringVerify: bind the prefabs to the wells zone directly, no ZoneRenderer A renderer loading a zone with a sun and a planet needs the planet prefab, the map and a GPU; the check pins the presenters' Place, so the prefabs are bound as LoadFloatingItem and LoadMine bind them. Co-Authored-By: Claude Opus 5.5 --- .../Scripts/Editor/DrawnPoseWiringVerify.cs | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs index bba726be6..33e443ccf 100644 --- a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs +++ b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs @@ -10,8 +10,8 @@ using float2 = CultMath.float2; using float3 = CultMath.float3; // Batch proof that the presenters read the drawn pose through the clock: DrawnPoseTests pins the pose maths headlessly, -// and this is what pins that each presenter passes ActionGameManager.Clock.Lead into it. A zone is loaded into a fresh -// ZoneRenderer with the pickup and mine prefabs ARPG.unity's ZoneRenderer names; a loose Projectile is launched on the +// and this is what pins that each presenter passes ActionGameManager.Clock.Lead into it. A zone with a sun and a planet on a moving rail +// is built and the pickup and mine prefabs ARPG.unity's ZoneRenderer names are bound to it as the renderer binds them; a loose Projectile is launched on the // zone. The zone is stepped once, then the clock is set to leads 0, 0.008 and 0.015 s with no step, and each presenter's // own Update places its transform. A body is drawn at its last step plus its step velocity times the lead, spelled here // from the body's fields, so a presenter that reads lead 0 (or half the lead) sits on the step and fails. @@ -135,20 +135,6 @@ namespace Aetheria.EditorTools var zone = new Zone(items, curves, pack, null, null); var rootObject = new GameObject("Wiring Zone Root"); - var rendererObject = new GameObject("Wiring Zone Renderer"); - rendererObject.SetActive(false); // inactive: ZoneRenderer.Update needs a GPU and is not part of this check - var renderer = rendererObject.AddComponent(); - renderer.ZoneRoot = rootObject.transform; - renderer.SimpleCommodityPickup = pickupPrefab; - renderer.MinePrefab = minePrefab; - renderer.ItemManager = items; - renderer.SectorBrushes = new GameObject("Wiring Brushes").transform; - renderer.AmbientLight = AmbientEdgeVerify.NewAmbientLight(); - renderer.SlimeGravityCamera = new GameObject("Wiring Gravity Camera").AddComponent(); - var slimeObject = new GameObject("Wiring Slime"); - slimeObject.SetActive(false); - renderer.SlimeRenderer = slimeObject.AddComponent(); - renderer.LoadZone(zone); var ore = new SimpleCommodity { Data = items.ItemData.RefOf(items.ItemData.GetByName("Wiring Ore")), Quantity = 7 }; var floating = zone.Release(ore, new float2(3, 4), new float2(10, 0)); @@ -159,6 +145,13 @@ namespace Aetheria.EditorTools }; zone.Lay(mine); + // Bound the way ZoneRenderer.LoadFloatingItem and LoadMine bind them: the prefab ARPG.unity names, Bind(zone, body, settings). + // (A ZoneRenderer would load this zone's sun and planet too, and that needs the planet prefab, the map and a GPU.) + var pickup = UnityEngine.Object.Instantiate(pickupPrefab, rootObject.transform); + pickup.Bind(zone, floating, settings); + var mineInstance = UnityEngine.Object.Instantiate(minePrefab, rootObject.transform); + mineInstance.Bind(zone, mine, settings); + // A round on its frozen line, no target and no outcome known: drawn at FireOrigin + direction * speed * (T - FireTime). var shot = new PendingShot { @@ -171,8 +164,6 @@ namespace Aetheria.EditorTools zone.Update(.5f); - var pickup = rootObject.GetComponentsInChildren(true).Single(p => p.Item == ore); - var mineInstance = UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None).Single(); var pickupVelocity = floating.Body.TotalVelocity; var mineVelocity = mine.Body.TotalVelocity; From 417ac9c76a1cc50035377877df3b9aebff047ead Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 17 Oct 2026 14:23:17 +0200 Subject: [PATCH 6/7] DrawnPoseWiringVerify: the planet passes within about 20 u of the pickup and mine, with a wider softening, so the field moves over a lead Co-Authored-By: Claude Opus 5.5 --- Assets/Scripts/Editor/DrawnPoseWiringVerify.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs index 33e443ccf..48a5ee3e3 100644 --- a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs +++ b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs @@ -119,8 +119,8 @@ namespace Aetheria.EditorTools // A sun and a planet on a moving rail round it, both near the bodies below: the field under a floater changes with the // drawn time, so a presenter that samples it at the step's time, drops it, or reads lead 0 for the height draws a different y. - var sunOrbit = cache.Upsert(new OrbitData { FixedPosition = new float2(-60, -40) }).Key; - var planetOrbit = cache.Upsert(new OrbitData { Parent = new CultRecordRef(sunOrbit), Distance = 40f, Phase = .125f }).Key; + var sunOrbit = cache.Upsert(new OrbitData { FixedPosition = new float2(-46, 9) }).Key; + var planetOrbit = cache.Upsert(new OrbitData { Parent = new CultRecordRef(sunOrbit), Distance = 40f, Phase = 0f }).Key; var pack = new ZonePack { Radius = 5000f, Mass = 10000f }; pack.Orbits.Add(new CultRecordRef(sunOrbit)); pack.Orbits.Add(new CultRecordRef(planetOrbit)); @@ -130,7 +130,7 @@ namespace Aetheria.EditorTools { BodyRadius = new ExponentialCurve(), WellStrength = new ExponentialCurve { Multiplier = 1f, Exponent = 1f }, - RocheLimit = new ExponentialCurve { Constant = 2f } + RocheLimit = new ExponentialCurve { Constant = 10f } }; var zone = new Zone(items, curves, pack, null, null); From d6380ca8e05e3d2d327a9fa68603aa45e6a4c235 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 17 Oct 2026 14:28:27 +0200 Subject: [PATCH 7/7] DrawnPoseWiringVerify: the planet passes within about 8 u of both floaters; the guard names the heights it saw Co-Authored-By: Claude Opus 5.5 --- Assets/Scripts/Editor/DrawnPoseWiringVerify.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs index 48a5ee3e3..c1994ebeb 100644 --- a/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs +++ b/Assets/Scripts/Editor/DrawnPoseWiringVerify.cs @@ -119,13 +119,13 @@ namespace Aetheria.EditorTools // A sun and a planet on a moving rail round it, both near the bodies below: the field under a floater changes with the // drawn time, so a presenter that samples it at the step's time, drops it, or reads lead 0 for the height draws a different y. - var sunOrbit = cache.Upsert(new OrbitData { FixedPosition = new float2(-46, 9) }).Key; + var sunOrbit = cache.Upsert(new OrbitData { FixedPosition = new float2(-55, -.5f) }).Key; var planetOrbit = cache.Upsert(new OrbitData { Parent = new CultRecordRef(sunOrbit), Distance = 40f, Phase = 0f }).Key; var pack = new ZonePack { Radius = 5000f, Mass = 10000f }; pack.Orbits.Add(new CultRecordRef(sunOrbit)); pack.Orbits.Add(new CultRecordRef(planetOrbit)); pack.Planets.Add(new CultRecordRef(cache.Upsert(new PlanetData { Name = "Wiring Sun", Orbit = new CultRecordRef(sunOrbit), Mass = 400f }).Key)); - pack.Planets.Add(new CultRecordRef(cache.Upsert(new PlanetData { Name = "Wiring Planet", Orbit = new CultRecordRef(planetOrbit), Mass = 100f }).Key)); + pack.Planets.Add(new CultRecordRef(cache.Upsert(new PlanetData { Name = "Wiring Planet", Orbit = new CultRecordRef(planetOrbit), Mass = 400f }).Key)); var curves = new PlanetSettings { BodyRadius = new ExponentialCurve(), @@ -137,7 +137,7 @@ namespace Aetheria.EditorTools var rootObject = new GameObject("Wiring Zone Root"); var ore = new SimpleCommodity { Data = items.ItemData.RefOf(items.ItemData.GetByName("Wiring Ore")), Quantity = 7 }; - var floating = zone.Release(ore, new float2(3, 4), new float2(10, 0)); + var floating = zone.Release(ore, new float2(-17, 4), new float2(10, 0)); var mine = new Mine { Body = new KinematicBody { Position = new float2(-20, 8), Velocity = new float2(0, 14) }, @@ -173,7 +173,7 @@ namespace Aetheria.EditorTools const float LargestLead = .015f; foreach (var at in new[] { floating.Body.Position + pickupVelocity * LargestLead, mine.Body.Position + mineVelocity * LargestLead }) Require(Mathf.Abs(DrawAhead.Height(zone, at, LargestLead) - zone.GetHeight(at, zone.ExactTime)) > 5 * Tolerance, - "The fixture's field is flat under a floater: a drawn time would not move its height."); + $"The fixture's field is flat under a floater: height {DrawAhead.Height(zone, at, LargestLead)} at the drawn time, {zone.GetHeight(at, zone.ExactTime)} at the step, planet at {zone.OrbitPositionAt(planetOrbit, zone.ExactTime)}, floater at {at}."); Vector2 baseline = default; foreach (var leadSeconds in new[] { 0f, .008f, .015f })