From 857e404f5a7db062b9368cfbb6a8186e08c8e306 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 21 Jun 2026 22:56:23 +0100 Subject: [PATCH] Resolve Eve surface pointer refs generically --- Aetheria.State.Verify/Program.cs | 9 +++-- .../Tests/DaemonRuntimeDocumentTests.cs | 37 +++++++++++++++++++ .../AetheriaRuntimeEveSurfaceAdapter.cs | 30 +++++++++++++-- 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index a41730713..f8075b9be 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -4329,8 +4329,10 @@ static void RequireInventoryCargoItemDetailsUseEveSurface(string root) !eveUnitySurfaceHost.Contains("CreateDefaultStateRefResolver()", StringComparison.Ordinal) || !eveUnitySurfaceHost.Contains("AetheriaRuntimeStateReader.CreateEveSurfaceStateRefResolver(stateBoot.StateFilePath)", StringComparison.Ordinal) || !runtimeEveSurfaceAdapter.Contains("public static EveSurfaceDocument ResolveStateRefs(", StringComparison.Ordinal) || + !runtimeEveSurfaceAdapter.Contains("ResolvePropRefs(props, stateRefResolver)", StringComparison.Ordinal) || !runtimeEveSurfaceAdapter.Contains("ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, \"value\", stateRefResolver)", StringComparison.Ordinal) || - !runtimeEveSurfaceAdapter.Contains("ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Value, \"value\", stateRefResolver)", StringComparison.Ordinal) || + !runtimeEveSurfaceAdapter.Contains("IsStatePointerProp(prop.Key)", StringComparison.Ordinal) || + !runtimeEveSurfaceAdapter.Contains("ResolvePointerValueKey(refProp.Key)", StringComparison.Ordinal) || !cargoItemSurfaceBuilder.Contains("public string ValueRef { get; }", StringComparison.Ordinal) || !cargoItemSurfaceBuilder.Contains("props.Add(AetheriaRuntimeSurfaceStateRefs.ValueRef(valueRef))", StringComparison.Ordinal) || !equippedItemSurfaceBuilder.Contains("public string ValueRef { get; }", StringComparison.Ordinal) || @@ -9771,9 +9773,10 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root) "public static class AetheriaRuntimeEveSurfaceAdapter", "public static EveSurfaceDocument ToEveSurfaceDocument(AetheriaRuntimeSurfaceDocument document)", "public static EveSurfaceDocument ResolveStateRefs(", + "ResolvePropRefs(props, stateRefResolver)", "ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, \"value\", stateRefResolver)", - "ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Value, \"value\", stateRefResolver)", - "ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Label, \"label\", stateRefResolver)", + "IsStatePointerProp(prop.Key)", + "ResolvePointerValueKey(refProp.Key)", "public static EveSurfaceDocument EmptySurface(string surfaceId)", "new EveSurfaceDocument(", "new EveSurfaceComponent(" diff --git a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs index d92af28cb..921ca5400 100644 --- a/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs +++ b/Assets/Scripts/Tests/DaemonRuntimeDocumentTests.cs @@ -406,6 +406,43 @@ public class DaemonRuntimeDocumentTests AetheriaRuntimeDaemonStateRefs.CurrentTargetName)); } + [Test] + public void EveSurfaceAdapterResolvesTypedPointerPropsBeforeLowering() + { + var surface = new EveSurfaceDocument( + "surface-state", + "gamecult.eve.surface.v1", + "aetheria.daemon", + "daemon", + "Daemon", + 1, + "", + new EveSurfaceTree( + "aetheria.test.surface", + new EveSurfaceComponent( + "aetheria.test.metric", + "metric", + new Dictionary(StringComparer.Ordinal) + { + ["label"] = "Heat", + ["description"] = "stale", + ["descriptionRef"] = AetheriaRuntimeDaemonStateRefs.CurrentTargetName, + [AetheriaRuntimeSurfaceStateRefs.Value] = AetheriaRuntimeDaemonStateRefs.CurrentTargetName + }, + Array.Empty()), + Array.Empty()), + Array.Empty()); + + var resolved = AetheriaRuntimeEveSurfaceAdapter.ResolveStateRefs( + surface, + stateRef => stateRef == AetheriaRuntimeDaemonStateRefs.CurrentTargetName ? "Live Target" : ""); + + Assert.IsTrue(ContainsEveSurfaceProp(resolved.Surface.Root, "description", "Live Target")); + Assert.IsTrue(ContainsEveSurfaceProp(resolved.Surface.Root, "descriptionRef", AetheriaRuntimeDaemonStateRefs.CurrentTargetName)); + Assert.IsTrue(ContainsEveSurfaceProp(resolved.Surface.Root, "value", "Live Target")); + Assert.IsTrue(ContainsEveSurfaceProp(resolved.Surface.Root, AetheriaRuntimeSurfaceStateRefs.Value, AetheriaRuntimeDaemonStateRefs.CurrentTargetName)); + } + [Test] public void RuntimeStateReaderResolvesItemStatRefsFromDaemonFrame() { diff --git a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveSurfaceAdapter.cs b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveSurfaceAdapter.cs index e29f01ff3..b05cf439b 100644 --- a/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveSurfaceAdapter.cs +++ b/Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveSurfaceAdapter.cs @@ -100,9 +100,7 @@ namespace GameCult.Aetheria.State.Verse Func stateRefResolver) { var props = new Dictionary(component.Props, StringComparer.Ordinal); - ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, "value", stateRefResolver); - ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Value, "value", stateRefResolver); - ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Label, "label", stateRefResolver); + ResolvePropRefs(props, stateRefResolver); return new EveSurfaceComponent( component.Id, @@ -124,6 +122,32 @@ namespace GameCult.Aetheria.State.Verse return resolved; } + private static void ResolvePropRefs( + Dictionary props, + Func stateRefResolver) + { + ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, "value", stateRefResolver); + + var refProps = props + .Where(prop => IsStatePointerProp(prop.Key) && + !string.Equals(prop.Key, AetheriaRuntimeSurfaceStateRefs.Source, StringComparison.Ordinal) && + !string.IsNullOrWhiteSpace(prop.Value)) + .ToArray(); + + foreach (var refProp in refProps) + ResolvePropRef(props, refProp.Key, ResolvePointerValueKey(refProp.Key), stateRefResolver); + } + + private static bool IsStatePointerProp(string key) + { + return key.EndsWith("Ref", StringComparison.Ordinal); + } + + private static string ResolvePointerValueKey(string refKey) + { + return refKey.Substring(0, refKey.Length - "Ref".Length); + } + private static void ResolvePropRef( Dictionary props, string refKey,