Use CultMesh state refs for Eve surfaces

This commit is contained in:
Meta Vens 2026-06-29 03:09:13 +01:00
commit 5299dcb184
6 changed files with 44 additions and 45 deletions

View file

@ -5239,15 +5239,15 @@ static void RequireInventoryCargoItemDetailsUseEveSurface(string root)
!daemonItemStatQueries.Contains("public static bool TryReadItemStatRef(", StringComparison.Ordinal) ||
!daemonItemStatQueries.Contains("public string ValueRef =>", StringComparison.Ordinal) ||
!unityProject.Contains("AetheriaRuntimeDaemonItemStatQueries.cs", StringComparison.Ordinal) ||
!eveUnitySurfaceHost.Contains("Func<string, string> stateRefResolver", StringComparison.Ordinal) ||
!eveUnitySurfaceHost.Contains("CultMeshStateRefResolver stateRefResolver", StringComparison.Ordinal) ||
!eveUnitySurfaceHost.Contains("ContainsStateRefs(surface)", StringComparison.Ordinal) ||
!eveUnitySurfaceHost.Contains("prop.Key.EndsWith(\"Ref\", StringComparison.Ordinal)", StringComparison.Ordinal) ||
!eveUnitySurfaceHost.Contains("CreateDefaultStateRefResolver()", StringComparison.Ordinal) ||
!eveUnitySurfaceHost.Contains("AetheriaUnityRuntimeClientProvider", StringComparison.Ordinal) ||
!eveUnitySurfaceHost.Contains(".CreateEveSurfaceStateRefResolver()", StringComparison.Ordinal) ||
!eveUnitySurfaceHost.Contains(".CreateEveSurfaceCultMeshStateRefResolver()", 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("ResolvePropRefs(props, resolveStateRef)", StringComparison.Ordinal) ||
!runtimeEveSurfaceAdapter.Contains("ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, \"value\", resolveStateRef)", StringComparison.Ordinal) ||
!runtimeEveSurfaceAdapter.Contains("IsStatePointerProp(prop.Key)", StringComparison.Ordinal) ||
!runtimeEveSurfaceAdapter.Contains("ResolvePointerValueKey(refProp.Key)", StringComparison.Ordinal) ||
!cargoItemSurfaceBuilder.Contains("public string ValueRef { get; }", StringComparison.Ordinal) ||
@ -11954,7 +11954,6 @@ static void RequireAetheriaRuntimeVerseClientContract(string root)
var requiredClientStateSymbols = new[]
{
"public Func<string, string> CreateEveSurfaceStateRefResolver()",
"public CultMeshStateRefResolver CreateEveSurfaceCultMeshStateRefResolver()",
"public sealed class AetheriaClientState : IDisposable",
"CultMeshReactiveDocument<AetheriaRuntimeDaemonFrameDocument>? _eveStateRefFrame",
@ -15789,8 +15788,9 @@ 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)",
"CultMeshStateRefResolver? stateRefResolver",
"ResolvePropRefs(props, resolveStateRef)",
"ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, \"value\", resolveStateRef)",
"IsStatePointerProp(prop.Key)",
"ResolvePointerValueKey(refProp.Key)",
"public static EveSurfaceDocument EmptySurface(string surfaceId)",
@ -16356,7 +16356,6 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root)
"public async Task<global::Aetheria.State.Documents.EveSurfaceState?> DaemonGameTuiSurfaceAsync()",
"public async Task<global::Aetheria.State.Documents.EveSurfaceState?> DaemonEditorSurfaceAsync()",
"public async Task<global::Aetheria.State.Documents.EveSurfaceState?> DaemonEditorTuiSurfaceAsync()",
"public Func<string, string> CreateEveSurfaceStateRefResolver()",
"public CultMeshStateRefResolver CreateEveSurfaceCultMeshStateRefResolver()",
"public CultMeshDocumentHandle<TDocument> Document<TDocument>()",
"public Observable<TDocument> Watch<TDocument>()",
@ -16521,8 +16520,8 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root)
"Aetheria Eve surface presenter no longer routes daemon surface lookup through the shared AetheriaClient facade.");
}
if (!eveSurfacePresenter.Contains("client.State.CreateEveSurfaceStateRefResolver()", StringComparison.Ordinal) ||
!eveSurfacePresenter.Contains("ResolveClient(statePath).State.CreateEveSurfaceStateRefResolver()", StringComparison.Ordinal))
if (!eveSurfacePresenter.Contains("client.State.CreateEveSurfaceCultMeshStateRefResolver()", StringComparison.Ordinal) ||
!eveSurfacePresenter.Contains("ResolveClient(statePath).State.CreateEveSurfaceCultMeshStateRefResolver()", StringComparison.Ordinal))
{
throw new InvalidOperationException(
"Aetheria Eve surface presenter no longer resolves provider state refs through managed AetheriaClientState documents.");
@ -16547,10 +16546,11 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root)
}
if (aetheriaClientState.Contains("AetheriaRuntimeStateReader.CreateEveSurfaceCultMeshStateRefResolver", StringComparison.Ordinal) ||
aetheriaClientState.Contains("AetheriaRuntimeStateReader.CreateEveSurfaceStateRefResolver", StringComparison.Ordinal))
aetheriaClientState.Contains("AetheriaRuntimeStateReader.CreateEveSurfaceStateRefResolver", StringComparison.Ordinal) ||
aetheriaClientState.Contains("public Func<string, string> CreateEveSurfaceStateRefResolver()", StringComparison.Ordinal))
{
throw new InvalidOperationException(
"Managed client state still routes Eve state-ref resolution through the file-backed compatibility reader.");
"Managed client state still routes or exposes Eve state-ref resolution through file-backed/delegate compatibility.");
}
var forbiddenDirectStoreSymbols = new Dictionary<string, string[]>

View file

@ -601,7 +601,7 @@ public class DaemonRuntimeDocumentTests
var unityGameTuiSurfaceState = ReadLatest(client.State.Document<global::Aetheria.State.Documents.EveSurfaceState>(AetheriaClientEveSurface.GameTui));
var unityEditorSurfaceState = ReadLatest(client.State.Document<global::Aetheria.State.Documents.EveSurfaceState>(AetheriaClientEveSurface.Editor));
var unityEditorTuiSurfaceState = ReadLatest(client.State.Document<global::Aetheria.State.Documents.EveSurfaceState>(AetheriaClientEveSurface.EditorTui));
var surfaceResolver = client.State.CreateEveSurfaceStateRefResolver();
var surfaceResolver = client.State.CreateEveSurfaceCultMeshStateRefResolver();
var unityGameSurface = AetheriaRuntimeEveSurfaceAdapter.ToEveSurfaceDocument(
unityGameSurfaceState,
surfaceResolver);
@ -690,9 +690,10 @@ public class DaemonRuntimeDocumentTests
Array.Empty<EveStyleToken>()),
Array.Empty<EveCommandTemplate>());
var resolved = AetheriaRuntimeEveSurfaceAdapter.ResolveStateRefs(
surface,
stateRef => stateRef == AetheriaRuntimeDaemonStateRefs.CurrentTargetName ? "Live Target" : "");
var resolver = CultMesh.StateRefResolver(
"aetheria.tests.refs",
(stateRef, _context) => stateRef == AetheriaRuntimeDaemonStateRefs.CurrentTargetName ? "Live Target" : "");
var resolved = AetheriaRuntimeEveSurfaceAdapter.ResolveStateRefs(surface, resolver);
Assert.IsTrue(ContainsEveSurfaceMetric(resolved.Surface.Root, "Target", "Live Target"));
Assert.IsTrue(ContainsEveSurfaceProp(
@ -728,9 +729,10 @@ public class DaemonRuntimeDocumentTests
Array.Empty<EveStyleToken>()),
Array.Empty<EveCommandTemplate>());
var resolved = AetheriaRuntimeEveSurfaceAdapter.ResolveStateRefs(
surface,
stateRef => stateRef == AetheriaRuntimeDaemonStateRefs.CurrentTargetName ? "Live Target" : "");
var resolver = CultMesh.StateRefResolver(
"aetheria.tests.refs",
(stateRef, _context) => stateRef == AetheriaRuntimeDaemonStateRefs.CurrentTargetName ? "Live Target" : "");
var resolved = AetheriaRuntimeEveSurfaceAdapter.ResolveStateRefs(surface, resolver);
Assert.IsTrue(ContainsEveSurfaceProp(resolved.Surface.Root, "description", "Live Target"));
Assert.IsTrue(ContainsEveSurfaceProp(resolved.Surface.Root, "descriptionRef", AetheriaRuntimeDaemonStateRefs.CurrentTargetName));

View file

@ -135,7 +135,7 @@ namespace GameCult.Aetheria.EveRuntime
? null
: AetheriaRuntimeEveSurfaceAdapter.ToEveSurfaceDocument(
surface,
client.State.CreateEveSurfaceStateRefResolver());
client.State.CreateEveSurfaceCultMeshStateRefResolver());
}
private global::Aetheria.State.Documents.EveSurfaceState? ReadDaemonSurfaceState(AetheriaClient client)
@ -231,7 +231,7 @@ namespace GameCult.Aetheria.EveRuntime
surface,
request => EmitCommand(statePath, request),
RootOnlyChrome,
ResolveClient(statePath).State.CreateEveSurfaceStateRefResolver());
ResolveClient(statePath).State.CreateEveSurfaceCultMeshStateRefResolver());
_mountedStatePath = statePath;
_mountedSurfaceId = surface.Surface.Id;
_mountedSurfaceVersion = surface.Version;

View file

@ -4,6 +4,7 @@ using System.Linq;
using GameCult.Aetheria.State.Verse;
using GameCult.Eve.Surface;
using GameCult.Eve.UnityUIToolkit;
using GameCult.Mesh;
using UnityEngine;
using UnityEngine.UIElements;
@ -47,7 +48,7 @@ namespace GameCult.Aetheria.EveRuntime
EveSurfaceDocument surface,
Action<EveSurfaceCommandRequest> commandHandler,
AetheriaEveUnitySurfaceChrome chrome,
Func<string, string> stateRefResolver = null,
CultMeshStateRefResolver stateRefResolver = null,
int sortingOrder = 1000)
{
if (owner == null)
@ -90,7 +91,7 @@ namespace GameCult.Aetheria.EveRuntime
AetheriaRuntimeSurfaceDocument surface,
Action<EveSurfaceCommandRequest> commandHandler,
AetheriaEveUnitySurfaceChrome chrome,
Func<string, string> stateRefResolver = null,
CultMeshStateRefResolver stateRefResolver = null,
int sortingOrder = 1000)
{
if (surface == null)
@ -219,16 +220,16 @@ namespace GameCult.Aetheria.EveRuntime
return false;
}
private static Func<string, string> CreateDefaultStateRefResolver()
private static CultMeshStateRefResolver CreateDefaultStateRefResolver()
{
var stateBoot = AetheriaRuntimeStateBoot.Inspect(AetheriaUnityRuntimePaths.GameDataDirectory, "");
if (!stateBoot.SupportsLocalStateFileRead || !stateBoot.StateFileExists)
return _ => "";
return null;
return AetheriaUnityRuntimeClientProvider
.ResolveClient(stateBoot, "unity-eve-surface-host")
.State
.CreateEveSurfaceStateRefResolver();
.CreateEveSurfaceCultMeshStateRefResolver();
}
}

View file

@ -249,11 +249,6 @@ namespace GameCult.Aetheria.State.Verse
return (CultMeshDocumentHandle<TDocument>)(object)_starbridgePlayerSeat(seatId);
}
public Func<string, string> CreateEveSurfaceStateRefResolver()
{
return CreateEveSurfaceCultMeshStateRefResolver().AsFunc();
}
public CultMeshStateRefResolver CreateEveSurfaceCultMeshStateRefResolver()
{
_eveStateRefFrame ??= Document<AetheriaRuntimeDaemonFrameDocument>().Reactive();

View file

@ -23,7 +23,7 @@ namespace GameCult.Aetheria.State.Verse
public static EveSurfaceDocument ToEveSurfaceDocument(
EveSurfaceState state,
Func<string, string>? stateRefResolver)
CultMeshStateRefResolver? stateRefResolver)
{
if (state == null) throw new ArgumentNullException(nameof(state));
@ -51,7 +51,7 @@ namespace GameCult.Aetheria.State.Verse
public static EveSurfaceDocument ToEveSurfaceDocument(
AetheriaRuntimeSurfaceDocument document,
Func<string, string>? stateRefResolver)
CultMeshStateRefResolver? stateRefResolver)
{
if (document == null) throw new ArgumentNullException(nameof(document));
@ -78,12 +78,13 @@ namespace GameCult.Aetheria.State.Verse
public static EveSurfaceDocument ResolveStateRefs(
EveSurfaceDocument surface,
Func<string, string>? stateRefResolver)
CultMeshStateRefResolver? stateRefResolver)
{
if (surface == null) throw new ArgumentNullException(nameof(surface));
if (stateRefResolver == null)
return surface;
var resolveStateRef = stateRefResolver.AsFunc();
return new EveSurfaceDocument(
surface.Type,
surface.Schema,
@ -94,7 +95,7 @@ namespace GameCult.Aetheria.State.Verse
surface.UpdatedAtUtc,
new EveSurfaceTree(
surface.Surface.Id,
ResolveStateRefs(surface.Surface.Root, stateRefResolver),
ResolveStateRefs(surface.Surface.Root, resolveStateRef),
surface.Surface.Styles),
surface.Commands);
}
@ -187,37 +188,37 @@ namespace GameCult.Aetheria.State.Verse
private static EveSurfaceComponent ResolveStateRefs(
EveSurfaceComponent component,
Func<string, string> stateRefResolver)
Func<string, string> resolveStateRef)
{
var props = new Dictionary<string, string>(component.Props, StringComparer.Ordinal);
ResolvePropRefs(props, stateRefResolver);
ResolvePropRefs(props, resolveStateRef);
return new EveSurfaceComponent(
component.Id,
component.Kind,
props,
ResolveStateRefs(component.Children, stateRefResolver),
ResolveStateRefs(component.Children, resolveStateRef),
component.StateBindings);
}
private static IReadOnlyList<EveSurfaceComponent> ResolveStateRefs(
IReadOnlyList<EveSurfaceComponent> children,
Func<string, string> stateRefResolver)
Func<string, string> resolveStateRef)
{
if (children == null || children.Count == 0)
return Array.Empty<EveSurfaceComponent>();
var resolved = new EveSurfaceComponent[children.Count];
for (var index = 0; index < children.Count; index++)
resolved[index] = ResolveStateRefs(children[index], stateRefResolver);
resolved[index] = ResolveStateRefs(children[index], resolveStateRef);
return resolved;
}
private static void ResolvePropRefs(
Dictionary<string, string> props,
Func<string, string> stateRefResolver)
Func<string, string> resolveStateRef)
{
ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, "value", stateRefResolver);
ResolvePropRef(props, AetheriaRuntimeSurfaceStateRefs.Source, "value", resolveStateRef);
var refProps = props
.Where(prop => IsStatePointerProp(prop.Key) &&
@ -226,7 +227,7 @@ namespace GameCult.Aetheria.State.Verse
.ToArray();
foreach (var refProp in refProps)
ResolvePropRef(props, refProp.Key, ResolvePointerValueKey(refProp.Key), stateRefResolver);
ResolvePropRef(props, refProp.Key, ResolvePointerValueKey(refProp.Key), resolveStateRef);
}
private static bool IsStatePointerProp(string key)
@ -243,12 +244,12 @@ namespace GameCult.Aetheria.State.Verse
Dictionary<string, string> props,
string refKey,
string valueKey,
Func<string, string> stateRefResolver)
Func<string, string> resolveStateRef)
{
if (!props.TryGetValue(refKey, out var stateRef) || string.IsNullOrWhiteSpace(stateRef))
return;
var resolved = stateRefResolver(stateRef);
var resolved = resolveStateRef(stateRef);
if (!string.IsNullOrWhiteSpace(resolved))
props[valueKey] = resolved;
}