Lower zone body views from daemon render queries

This commit is contained in:
Meta Vens 2026-06-21 23:01:34 +01:00
commit 2a8414aa10
4 changed files with 146 additions and 12 deletions

View file

@ -1504,8 +1504,10 @@ static void RequireTypedOrbitConsumerKeys(string root)
{
[Path.Combine(root, "Assets", "Scripts", "Zone Display", "ZoneRenderer.cs")] = new[]
{
"private readonly List<AetheriaRuntimeDaemonBodyView> _daemonBodyViews",
"AetheriaRuntimeDaemonRenderQueries.QueryBodyViews(_daemonZoneSnapshot, _daemonBodyViews);",
"foreach (var bodyView in _daemonBodyViews)",
"foreach (var pose in _daemonBodyPoses)",
"foreach (var body in daemonZone?.Bodies ?? Array.Empty<AetheriaRuntimeBodySnapshotCommit>())",
"beltPosesByBodyKey.TryGetValue(body.BodyKey ?? \"\", out var beltPose)",
"_daemonBodyPosesByBodyKey.TryGetValue(planet.Key, out var pose)",
"var p = new float2((float)pose.CenterX, (float)pose.CenterZ);",
@ -1835,6 +1837,9 @@ static void RequireDaemonRenderQueryAuthority(string root)
"public static AetheriaRuntimeDaemonBodyPose[] QueryBodyPoses(",
"public static int QueryBodyPoses(",
"new AetheriaRuntimeDaemonBodyPose(",
"AetheriaRuntimeDaemonBodyView",
"public static AetheriaRuntimeDaemonBodyView[] QueryBodyViews(",
"public static int QueryBodyViews(",
"AetheriaRuntimeDaemonAsteroidBeltPose",
"public static AetheriaRuntimeDaemonAsteroidBeltPose[] QueryAsteroidBeltPoses(",
"public static int QueryAsteroidBeltPoses(",
@ -1948,6 +1953,13 @@ static void RequireDaemonRenderQueryAuthority(string root)
"ZoneRenderer must query daemon gravity terrain bands instead of calling mirrored Unity Zone gravity math.");
}
if (zoneRenderer.Contains("Settings.PlanetSettings.GravityRadius.Evaluate(", StringComparison.Ordinal) ||
zoneRenderer.Contains("Settings.PlanetSettings.GravityDepth.Evaluate(", StringComparison.Ordinal))
{
throw new InvalidOperationException(
"ZoneRenderer must lower daemon-authored gravity influence radius/depth instead of reconstructing gravity brushes from Unity settings.");
}
if (zoneRenderer.Contains("Zone.GetOrbitPosition(", StringComparison.Ordinal))
{
throw new InvalidOperationException(
@ -2036,6 +2048,7 @@ static void RequireDaemonRenderQueryAuthority(string root)
"public AetheriaRuntimeDaemonRenderSettings RenderSettings { get; set; }",
"private AetheriaRuntimeRunCheckpointCommit _daemonRunSnapshot;",
"private AetheriaRuntimeZoneSnapshotCommit _daemonZoneSnapshot;",
"private readonly List<AetheriaRuntimeDaemonBodyView> _daemonBodyViews",
"private readonly List<AetheriaRuntimeDaemonBodyPose> _daemonBodyPoses",
"private readonly Dictionary<string, AetheriaRuntimeDaemonBodyPose> _daemonBodyPosesByBodyKey",
"private readonly Dictionary<string, PlanetObject> _bodyViewsByBodyKey",
@ -2061,8 +2074,10 @@ static void RequireDaemonRenderQueryAuthority(string root)
" 2000);",
"AetheriaRuntimeDaemonRenderQueries.QueryGravityTerrainBand(",
"private readonly List<AetheriaRuntimeDaemonAsteroidInstancePose> _visibleAsteroidInstancePoses",
"foreach (var bodyView in _daemonBodyViews)",
"if (bodyView.IsAsteroidBelt)",
"AetheriaRuntimeDaemonRenderQueries.QueryBodyViews(_daemonZoneSnapshot, _daemonBodyViews);",
"foreach (var pose in _daemonBodyPoses)",
"foreach (var body in daemonZone?.Bodies ?? Array.Empty<AetheriaRuntimeBodySnapshotCommit>())",
"LoadPlanet(body)",
"void LoadPlanet(AetheriaRuntimeBodySnapshotCommit body)",
"beltPosesByBodyKey.TryGetValue(body.BodyKey ?? \"\", out var beltPose)",

View file

@ -985,6 +985,58 @@ public class DaemonRuntimeDocumentTests
Assert.AreEqual(3.5, poses[1].GravityWaveSpeed, 0.0001);
}
[Test]
public void DaemonRenderQueriesPublishBodyViewsFromZoneSnapshot()
{
var zone = new AetheriaRuntimeZoneSnapshotCommit
{
Orbits = new[]
{
new AetheriaRuntimeOrbitSnapshotCommit
{
OrbitKey = "orbit:planet",
FixedPositionX = 12,
FixedPositionY = -8
},
new AetheriaRuntimeOrbitSnapshotCommit
{
OrbitKey = "orbit:belt",
Distance = 30
}
},
Bodies = new[]
{
new AetheriaRuntimeBodySnapshotCommit
{
BodyKey = "body:planet",
OrbitKey = "orbit:planet",
Kind = "planet",
GravityInfluenceRadius = 40,
GravityWellDepth = 7
},
new AetheriaRuntimeBodySnapshotCommit
{
BodyKey = "body:belt",
OrbitKey = "orbit:belt",
Kind = "asteroid_belt"
}
}
};
var views = new List<AetheriaRuntimeDaemonBodyView>();
var count = AetheriaRuntimeDaemonRenderQueries.QueryBodyViews(zone, views);
Assert.AreEqual(2, count);
Assert.AreEqual("body:planet", views[0].Body.BodyKey);
Assert.IsFalse(views[0].IsAsteroidBelt);
Assert.AreEqual(12, views[0].Pose.CenterX, 0.0001);
Assert.AreEqual(-8, views[0].Pose.CenterZ, 0.0001);
Assert.AreEqual(40, views[0].Body.GravityInfluenceRadius, 0.0001);
Assert.AreEqual(7, views[0].Body.GravityWellDepth, 0.0001);
Assert.AreEqual("body:belt", views[1].Body.BodyKey);
Assert.IsTrue(views[1].IsAsteroidBelt);
}
[Test]
public void DaemonRenderQueriesPublishAsteroidBeltPosesFromZoneSnapshot()
{

View file

@ -85,6 +85,7 @@ public class ZoneRenderer : MonoBehaviour
private bool _showAsteroidUI;
private AetheriaRuntimeRunCheckpointCommit _daemonRunSnapshot;
private AetheriaRuntimeZoneSnapshotCommit _daemonZoneSnapshot;
private readonly List<AetheriaRuntimeDaemonBodyView> _daemonBodyViews = new List<AetheriaRuntimeDaemonBodyView>();
private readonly List<AetheriaRuntimeDaemonBodyPose> _daemonBodyPoses = new List<AetheriaRuntimeDaemonBodyPose>();
private readonly Dictionary<string, AetheriaRuntimeDaemonBodyPose> _daemonBodyPosesByBodyKey =
new Dictionary<string, AetheriaRuntimeDaemonBodyPose>(StringComparer.Ordinal);
@ -220,17 +221,17 @@ public class ZoneRenderer : MonoBehaviour
{
ClearZone();
ApplyDaemonFrame(daemonZone, daemonRun);
RefreshDaemonBodyViews();
RefreshDaemonBodyPoses();
RefreshDaemonAsteroidBeltPoses();
var beltPosesByBodyKey = _daemonAsteroidBeltPoses
.Where(pose => !string.IsNullOrWhiteSpace(pose.BodyKey))
.ToDictionary(pose => pose.BodyKey, StringComparer.Ordinal);
foreach (var body in daemonZone?.Bodies ?? Array.Empty<AetheriaRuntimeBodySnapshotCommit>())
foreach (var bodyView in _daemonBodyViews)
{
if (body == null)
continue;
var body = bodyView.Body;
if (string.Equals(body.Kind ?? "", "asteroid_belt", StringComparison.OrdinalIgnoreCase))
if (bodyView.IsAsteroidBelt)
{
if (beltPosesByBodyKey.TryGetValue(body.BodyKey ?? "", out var beltPose))
LoadAsteroidBelt(beltPose);
@ -467,12 +468,8 @@ public class ZoneRenderer : MonoBehaviour
}
var bodyRadius = Settings.PlanetSettings.BodyRadius.Evaluate(mass) * (float)body.BodyRadiusMultiplier;
var gravityWellRadius = body.GravityInfluenceRadius > 0
? (float)body.GravityInfluenceRadius
: Settings.PlanetSettings.GravityRadius.Evaluate(mass) * (float)body.GravityRadiusMultiplier;
var gravityWellDepth = body.GravityWellDepth != 0
? (float)body.GravityWellDepth
: Settings.PlanetSettings.GravityDepth.Evaluate(mass) * (float)body.GravityDepthMultiplier;
var gravityWellRadius = Mathf.Max(0f, (float)body.GravityInfluenceRadius);
var gravityWellDepth = (float)body.GravityWellDepth;
planet.Body.transform.localScale = bodyRadius * Vector3.one;
planet.GravityWell.transform.localScale = gravityWellRadius * Vector3.one;
// var depth = planetInstance.GravityWellDepth;
@ -675,6 +672,11 @@ public class ZoneRenderer : MonoBehaviour
// MinimapTintQuad.transform.position = gravPos - Vector3.up*10;
}
private void RefreshDaemonBodyViews()
{
AetheriaRuntimeDaemonRenderQueries.QueryBodyViews(_daemonZoneSnapshot, _daemonBodyViews);
}
private void RefreshDaemonBodyPoses()
{
AetheriaRuntimeDaemonRenderQueries.QueryBodyPoses(_daemonZoneSnapshot, _daemonBodyPoses);

View file

@ -137,6 +137,23 @@ namespace GameCult.Aetheria.State.Verse
public double GravityWaveSpeed { get; }
}
public readonly struct AetheriaRuntimeDaemonBodyView
{
public AetheriaRuntimeDaemonBodyView(
AetheriaRuntimeBodySnapshotCommit body,
AetheriaRuntimeDaemonBodyPose pose,
bool isAsteroidBelt)
{
Body = body ?? throw new ArgumentNullException(nameof(body));
Pose = pose;
IsAsteroidBelt = isAsteroidBelt;
}
public AetheriaRuntimeBodySnapshotCommit Body { get; }
public AetheriaRuntimeDaemonBodyPose Pose { get; }
public bool IsAsteroidBelt { get; }
}
public readonly struct AetheriaRuntimeDaemonAsteroidBeltPose
{
public AetheriaRuntimeDaemonAsteroidBeltPose(
@ -427,6 +444,54 @@ namespace GameCult.Aetheria.State.Verse
return poses.Count;
}
public static AetheriaRuntimeDaemonBodyView[] QueryBodyViews(
AetheriaRuntimeZoneSnapshotCommit? zone)
{
var views = new List<AetheriaRuntimeDaemonBodyView>();
QueryBodyViews(zone, views);
return views.Count == 0 ? Array.Empty<AetheriaRuntimeDaemonBodyView>() : views.ToArray();
}
public static int QueryBodyViews(
AetheriaRuntimeZoneSnapshotCommit? zone,
List<AetheriaRuntimeDaemonBodyView> views)
{
if (views == null) throw new ArgumentNullException(nameof(views));
views.Clear();
if (zone == null)
return 0;
var orbitPositions = BuildOrbitPositions(zone);
var orbits = BuildOrbitMap(zone);
foreach (var body in zone.Bodies ?? Array.Empty<AetheriaRuntimeBodySnapshotCommit>())
{
if (body == null || !TryResolveBodyCenter(body, orbitPositions, out var center))
continue;
var orbitKey = body.OrbitKey ?? "";
var parentOrbitKey = orbits.TryGetValue(orbitKey, out var orbit) ? orbit.ParentOrbitKey ?? "" : "";
var parentCenter = orbitPositions.TryGetValue(parentOrbitKey, out var parent)
? parent
: new AetheriaRuntimeXzPoint(0, 0);
var pose = new AetheriaRuntimeDaemonBodyPose(
body.BodyKey,
orbitKey,
parentOrbitKey,
body.Kind,
center.x,
center.z,
parentCenter.x,
parentCenter.z,
ResolveWaveSpeed(body));
views.Add(new AetheriaRuntimeDaemonBodyView(
body,
pose,
string.Equals(body.Kind, "asteroid_belt", StringComparison.OrdinalIgnoreCase)));
}
return views.Count;
}
public static AetheriaRuntimeDaemonAsteroidBeltPose[] QueryAsteroidBeltPoses(
AetheriaRuntimeZoneSnapshotCommit? zone)
{