Add Unity provider surface document source

This commit is contained in:
Meta Vens 2026-07-09 19:02:02 +01:00
commit da9bc3f4ff
11 changed files with 213 additions and 19 deletions

View file

@ -614,6 +614,12 @@ Recently cut:
movement/focus/target/action intents through the advertised command boundary,
while `EveUnitySceneProviderConnection` defines the generic surface source
and command sink ports that a CultMesh/CultNet adapter must implement.
`IEveUnitySceneProviderSurfaceDocumentSource`,
`EveUnitySceneProviderSurfaceDocument`, and
`EveUnitySceneProviderSurfaceDocumentSource` now add the typed provider
document boundary in front of those snapshots, so live CultMesh/CultCache
readers can publish daemon-owned surface documents without teaching EveUnity
Aetheria types.
`EveUnityPlayableWorldLiveClient` now composes the provider connection with
the playable-world presenter, so provider snapshots immediately drive scene
presentation and Unity input still exits through the provider command sink
@ -640,7 +646,7 @@ Recently cut:
Aetheria asset classes. The Unity client boundary is generic before it learns
live transport. The next blocker is the live generic Unity player loop:
implement the CultMesh/CultNet adapter, implement concrete CultMesh/CultCache
readers for provider snapshots and asset manifest documents, and prove
readers for provider surface and asset manifest documents, and prove
provider receipts plus daemon snapshots drive rendered Unity frames rather
than renderer-local simulation.
- EveElectron capture lifecycle now carries the same kind of structured pending

View file

@ -485,6 +485,12 @@ types. It also declares `providerSurfaceSource` through
`EveUnitySceneProviderConnection`, `IEveUnitySceneProviderSurfaceSource`, and
`IEveUnitySceneCommandSink`, so the live CultMesh/CultNet adapter has a narrow
runtime-owned port to implement. The runtime now also declares
`providerSurfaceDocumentSource`: `IEveUnitySceneProviderSurfaceDocumentSource`,
`EveUnitySceneProviderSurfaceDocument`, and
`EveUnitySceneProviderSurfaceDocumentSource` convert provider-authored surface
documents into snapshots before lowering, so the future CultMesh/CultCache
reader can own document delivery without importing Aetheria types. The runtime
now also declares
`livePlayableWorldClient`: `EveUnityPlayableWorldLiveClient` composes the
provider connection with `EveUnityPlayableWorldPresenter`, applies every live
snapshot to the scene sink, and delegates player intent back to the advertised
@ -514,8 +520,8 @@ declares `providerAssetManifestDocumentSource`:
`EveUnityPlayableWorldAssetManifestDocumentSource` convert provider-authored
manifest documents into the runtime cache without importing Aetheria asset
classes. The remaining blocker is the live CultMesh/CultNet adapter, concrete
CultMesh/CultCache readers for provider snapshots and asset manifests, and Unity
screenshot or frame-capture PNG production from EveUnity.
CultMesh/CultCache readers for provider surface and asset manifest documents,
and Unity screenshot or frame-capture PNG production from EveUnity.
Runtime capture probe coverage is exported as `runtimeCaptureProbeCoverage[]`.
Each record joins runtime status, capture owner, lifecycle capture contract,

View file

@ -164,6 +164,12 @@ radii, asset refs, controllability, and command affordances. The generic
`EveUnitySceneProviderConnection` adds the live-source port shape:
`IEveUnitySceneProviderSurfaceSource` supplies current and updated snapshots,
while `IEveUnitySceneCommandSink` receives command envelopes.
`IEveUnitySceneProviderSurfaceDocumentSource`,
`EveUnitySceneProviderSurfaceDocument`, and
`EveUnitySceneProviderSurfaceDocumentSource` now make that snapshot source a
typed document-consumer boundary: a CultMesh/CultCache adapter can own surface
delivery and publish provider-authored documents, while EveUnity only converts
them into snapshots for the generic lowerer.
`EveUnityPlayableWorldLiveClient` composes that connection with the playable
world presenter: every provider snapshot is lowered into a presentation pass,
Unity input still emits provider-owned command intents rather than mutating
@ -193,10 +199,10 @@ does not import Aetheria runtime types, prefab classes, or apply movement
locally.
This is not yet the final playable client. The remaining cut is a live
CultMesh/CultNet provider subscription adapter implementing those source/sink
ports, concrete CultMesh/CultCache readers for provider snapshots and asset
manifest documents, and proof that daemon receipts plus provider snapshots drive
the next rendered Unity frame rather than renderer-local state.
CultMesh/CultNet provider subscription adapter implementing those document and
command ports, concrete CultMesh/CultCache readers for provider snapshots and
asset manifest documents, and proof that daemon receipts plus provider
snapshots drive the next rendered Unity frame rather than renderer-local state.
## Non-Goals

View file

@ -16,6 +16,10 @@ namespace GameCult.Eve.UnityScene
EveUnitySceneProviderSurfaceSnapshot CurrentSnapshot { get; }
event Action<EveUnitySceneProviderSurfaceSnapshot> SnapshotAvailable;
void Connect();
void Disconnect();
}
public interface IEveUnitySceneCommandSink
@ -25,6 +29,98 @@ namespace GameCult.Eve.UnityScene
void Submit(EveSurfaceCommandRequest request);
}
public interface IEveUnitySceneProviderSurfaceDocumentSource
{
EveUnitySceneProviderSurfaceDocument CurrentDocument { get; }
event Action<EveUnitySceneProviderSurfaceDocument> DocumentAvailable;
}
public sealed class EveUnitySceneProviderSurfaceDocument
{
public EveUnitySceneProviderSurfaceDocument(
EveSurfaceDocument surfaceDocument,
EveUnitySceneProviderSurfaceAdvertisement advertisedSurface,
string sourcePointer,
long version = 0)
{
SurfaceDocument = surfaceDocument ?? throw new ArgumentNullException(nameof(surfaceDocument));
AdvertisedSurface = advertisedSurface ?? throw new ArgumentNullException(nameof(advertisedSurface));
SourcePointer = sourcePointer ?? "";
Version = version == 0 ? surfaceDocument.Version : version;
}
public EveSurfaceDocument SurfaceDocument { get; }
public EveUnitySceneProviderSurfaceAdvertisement AdvertisedSurface { get; }
public string SourcePointer { get; }
public long Version { get; }
public EveUnitySceneProviderSurfaceSnapshot ToSnapshot()
{
return new EveUnitySceneProviderSurfaceSnapshot(
SurfaceDocument,
AdvertisedSurface,
SourcePointer,
Version);
}
}
public sealed class EveUnitySceneProviderSurfaceDocumentSource : IEveUnitySceneProviderSurfaceSource, IDisposable
{
private readonly IEveUnitySceneProviderSurfaceDocumentSource _documentSource;
private bool _connected;
public EveUnitySceneProviderSurfaceDocumentSource(
IEveUnitySceneProviderSurfaceDocumentSource documentSource)
{
_documentSource = documentSource ?? throw new ArgumentNullException(nameof(documentSource));
CurrentSnapshot = _documentSource.CurrentDocument.ToSnapshot();
}
public string ProviderId => CurrentSnapshot.Document.ProviderId;
public string SurfaceId => CurrentSnapshot.AdvertisedSurface.SurfaceId;
public string SourcePointer => CurrentSnapshot.SourcePointer;
public EveUnitySceneProviderSurfaceSnapshot CurrentSnapshot { get; private set; }
public event Action<EveUnitySceneProviderSurfaceSnapshot>? SnapshotAvailable;
public void Connect()
{
if (_connected)
return;
_documentSource.DocumentAvailable += OnDocumentAvailable;
_connected = true;
}
public void Disconnect()
{
if (!_connected)
return;
_documentSource.DocumentAvailable -= OnDocumentAvailable;
_connected = false;
}
public void Dispose()
{
Disconnect();
}
private void OnDocumentAvailable(EveUnitySceneProviderSurfaceDocument document)
{
if (document == null) throw new ArgumentNullException(nameof(document));
CurrentSnapshot = document.ToSnapshot();
SnapshotAvailable?.Invoke(CurrentSnapshot);
}
}
public sealed class EveUnitySceneProviderConnection : IDisposable
{
private readonly IEveUnitySceneProviderSurfaceSource _surfaceSource;
@ -66,6 +162,7 @@ namespace GameCult.Eve.UnityScene
if (!_connected)
{
_surfaceSource.SnapshotAvailable += OnSnapshotAvailable;
_surfaceSource.Connect();
_connected = true;
}
@ -116,6 +213,7 @@ namespace GameCult.Eve.UnityScene
return;
_surfaceSource.SnapshotAvailable -= OnSnapshotAvailable;
_surfaceSource.Disconnect();
_connected = false;
}

View file

@ -198,6 +198,56 @@ namespace GameCult.Eve.UnityScene.Tests
Assert.That(projectionUpdates, Is.EqualTo(2));
}
[Test]
public void ProviderSurfaceDocumentSourceFeedsPlayableClientWithoutAetheriaTypes()
{
var documentSource = new FakeProviderSurfaceDocumentSource(new EveUnitySceneProviderSurfaceDocument(
PlayableArpgDocument(),
Advertisement("aetheria.daemon.game"),
"cultmesh://aetheria/eve/surfaces/aetheria.daemon.game",
1));
using var surfaceSource = new EveUnitySceneProviderSurfaceDocumentSource(documentSource);
var commandSink = new FakeCommandSink("cultmesh-command-sink");
var sceneSink = new FakePlayableWorldSceneSink();
using var connection = new EveUnitySceneProviderConnection(surfaceSource, commandSink);
using var client = new EveUnityPlayableWorldLiveClient(
connection,
new EveUnityPlayableWorldPresenter(sceneSink, new EveUnityAssetRefResolver()));
var initialPresentation = client.Connect();
Assert.That(surfaceSource.ProviderId, Is.EqualTo("aetheria"));
Assert.That(surfaceSource.SurfaceId, Is.EqualTo("aetheria.daemon.game"));
Assert.That(surfaceSource.SourcePointer, Is.EqualTo("cultmesh://aetheria/eve/surfaces/aetheria.daemon.game"));
Assert.That(initialPresentation.ActiveEntities, Is.EqualTo(3));
Assert.That(client.ActiveWorld, Is.Not.Null);
Assert.That(client.ActiveWorld!.StatePointerId, Is.EqualTo("cultmesh://aetheria/run/current"));
Assert.That(client.ActiveWorld.AssetManifest, Is.EqualTo("cultmesh://aetheria/assets/manifest"));
documentSource.Publish(new EveUnitySceneProviderSurfaceDocument(
PlayableArpgDocument(includeRaider: false, playerPosition: "11,0,5"),
Advertisement("aetheria.daemon.game"),
"cultmesh://aetheria/eve/surfaces/aetheria.daemon.game",
2));
Assert.That(client.ActiveVersion, Is.EqualTo(2));
Assert.That(client.LastPresentation, Is.Not.Null);
Assert.That(client.LastPresentation!.ActiveEntities, Is.EqualTo(2));
Assert.That(sceneSink.RemovedEntityIds, Does.Contain("raider-scout"));
Assert.That(sceneSink.Upserts[3].entity.EntityId, Is.EqualTo("player-vanguard"));
Assert.That(sceneSink.Upserts[3].entity.PositionX, Is.EqualTo(11f));
Assert.That(sceneSink.Upserts[3].entity.PositionZ, Is.EqualTo(5f));
var moveIntent = client.SubmitMoveIntent("player-vanguard", 12f, 0f, 8f);
Assert.That(commandSink.Submitted.Count, Is.EqualTo(1));
Assert.That(commandSink.Submitted[0], Is.SameAs(moveIntent));
Assert.That(moveIntent.ProviderId, Is.EqualTo("aetheria"));
Assert.That(moveIntent.SurfaceId, Is.EqualTo("aetheria.daemon.game"));
Assert.That(moveIntent.CommandBoundary, Is.EqualTo("aetheria.daemon.commands"));
Assert.That(moveIntent.ReceiptSchema, Is.EqualTo("aetheria.eve_command_acceptance_status.v1"));
}
[Test]
public void PlayableWorldPresenterInstantiatesUpdatesAndDespawnsProviderEntities()
{
@ -934,6 +984,14 @@ namespace GameCult.Eve.UnityScene.Tests
public event Action<EveUnitySceneProviderSurfaceSnapshot>? SnapshotAvailable;
public void Connect()
{
}
public void Disconnect()
{
}
public void Stage(EveUnitySceneProviderSurfaceSnapshot snapshot)
{
CurrentSnapshot = snapshot;
@ -946,6 +1004,24 @@ namespace GameCult.Eve.UnityScene.Tests
}
}
private sealed class FakeProviderSurfaceDocumentSource : IEveUnitySceneProviderSurfaceDocumentSource
{
public FakeProviderSurfaceDocumentSource(EveUnitySceneProviderSurfaceDocument currentDocument)
{
CurrentDocument = currentDocument;
}
public EveUnitySceneProviderSurfaceDocument CurrentDocument { get; private set; }
public event Action<EveUnitySceneProviderSurfaceDocument>? DocumentAvailable;
public void Publish(EveUnitySceneProviderSurfaceDocument document)
{
CurrentDocument = document;
DocumentAvailable?.Invoke(document);
}
}
private sealed class FakeCommandReceiptSource : IEveUnitySceneCommandReceiptSource
{
public event Action<EveUnitySceneCommandReceipt>? ReceiptAvailable;

View file

@ -18,6 +18,7 @@
"commandTransport",
"providerSurfaceSession",
"providerSurfaceSource",
"providerSurfaceDocumentSource",
"livePlayableWorldClient",
"providerCommandReceipts",
"providerAssetManifestDocumentSource",
@ -178,7 +179,7 @@
],
"pendingProofs": [
"Unity scene provider-advertisement smoke runs from EveUnity with real Unity scene/frame objects and no Aetheria imports.",
"Live CultMesh/CultNet provider subscription adapter implements IEveUnitySceneProviderSurfaceSource and feeds EveUnitySceneClientSession snapshots instead of Eve-local fixture documents."
"Live CultMesh/CultNet provider subscription adapter implements IEveUnitySceneProviderSurfaceDocumentSource/IEveUnitySceneProviderSurfaceSource and feeds EveUnitySceneClientSession snapshots from provider-owned documents instead of Eve-local fixture documents."
]
},
"capture": {

View file

@ -73,7 +73,7 @@
"runtimes/incubating/eve-unity-scene/eve-runtime-capability.json"
],
"destinationOwner": "EveUnity",
"replacementProof": "EveUnity claims the provider-advertised unity-scene lowering target with provider-agnostic playable-world projection, scene graph projection, provider snapshot session, live playable-world client composition, provider command receipt observation, playable-world scene presentation, Unity GameObject scene sink, typed provider asset manifest document loading, provider asset manifest resolution, provider asset manifest source/cache, and command boundary evidence; live transport and capture remain separate lifecycle proofs."
"replacementProof": "EveUnity claims the provider-advertised unity-scene lowering target with provider-agnostic playable-world projection, scene graph projection, typed provider surface document loading, provider snapshot session, live playable-world client composition, provider command receipt observation, playable-world scene presentation, Unity GameObject scene sink, typed provider asset manifest document loading, provider asset manifest resolution, provider asset manifest source/cache, and command boundary evidence; live transport and capture remain separate lifecycle proofs."
},
{
"id": "unity-scene-sai-plugin-projection",
@ -122,7 +122,7 @@
"runtimes/incubating/eve-unity-scene/eve-runtime-capability.json"
],
"destinationOwner": "EveUnity",
"replacementProof": "Unity scene input emits gamecult.eve.command.v1 intents through a provider-snapshot client session, IEveUnitySceneProviderSurfaceSource, IEveUnitySceneCommandSink, IEveUnitySceneCommandReceiptSource, and advertised command boundaries, then observes provider receipts and refreshes from provider snapshots instead of mutating local world truth."
"replacementProof": "Unity scene input emits gamecult.eve.command.v1 intents through typed provider surface documents, a provider-snapshot client session, IEveUnitySceneProviderSurfaceSource, IEveUnitySceneCommandSink, IEveUnitySceneCommandReceiptSource, and advertised command boundaries, then observes provider receipts and refreshes from provider documents/snapshots instead of mutating local world truth."
},
{
"id": "unity-scene-capture-lifecycle",
@ -161,7 +161,7 @@
"EveUnity builds the provider-agnostic Unity scene UPM package artifact.",
"EveUnity owns a provider-agnostic scene graph lowerer that consumes advertised worldInteraction boundaries without importing Aetheria internals.",
"EveUnity owns a provider-snapshot Unity scene client session that lowers Aetheria's surface and emits command intents without importing Aetheria project code.",
"EveUnity owns provider surface source and command sink ports that a live CultMesh/CultNet adapter can implement without changing scene lowering.",
"EveUnity owns typed provider surface document, provider surface source, and command sink ports that a live CultMesh/CultNet adapter can implement without changing scene lowering.",
"EveUnity owns a live playable-world client coordinator that applies provider snapshots through the presenter, observes provider command receipts, and emits command intents through the advertised provider command sink without local simulation.",
"EveUnity owns a playable-world presenter that maps provider-authored entity rows and asset refs into Unity scene operations without importing Aetheria entity or prefab classes.",
"EveUnity owns a generic Unity GameObject scene sink and asset-provider hook for playable-world rows without importing Aetheria entity or prefab classes.",
@ -175,7 +175,7 @@
"EveUnity lowers at least one non-Aetheria provider-authored world surface into Unity scene objects.",
"EveUnity lowers Aetheria's game world surface into generic playableWorld projection data through provider advertisements without importing Aetheria internals.",
"A generic EveUnity scene client subscribes to the live Aetheria daemon surface over CultMesh/CultNet without Aetheria project code.",
"Unity scene input emits gamecult.eve.command.v1 intents, observes provider receipts, and refreshes rendered state from provider snapshots.",
"Unity scene input emits gamecult.eve.command.v1 intents, observes provider receipts, and refreshes rendered state from provider surface documents/snapshots.",
"Unity scene screenshot or frame-capture PNG artifacts are attached to conformance output."
]
}

View file

@ -39,7 +39,7 @@ if ($manifest.incubation.splitHandoff.manifestPath -ne "runtimes/incubating/eve-
throw "EveUnity scene manifest missing split handoff path"
}
foreach ($feature in @("providerAdvertisements", "commandTransport", "providerSurfaceSession", "providerSurfaceSource", "livePlayableWorldClient", "providerCommandReceipts", "providerAssetManifestDocumentSource", "sceneGraphProjection", "playableWorldProjection", "playableWorldScenePresentation", "unityGameObjectSceneSink", "providerAssetManifestResolution", "providerAssetManifestSource", "embeddedDocuments")) {
foreach ($feature in @("providerAdvertisements", "commandTransport", "providerSurfaceSession", "providerSurfaceSource", "providerSurfaceDocumentSource", "livePlayableWorldClient", "providerCommandReceipts", "providerAssetManifestDocumentSource", "sceneGraphProjection", "playableWorldProjection", "playableWorldScenePresentation", "unityGameObjectSceneSink", "providerAssetManifestResolution", "providerAssetManifestSource", "embeddedDocuments")) {
if (-not (@($manifest.supportedFeatures) -contains $feature)) {
throw "EveUnity scene manifest missing provider-shell feature: $feature"
}

View file

@ -54,7 +54,7 @@ foreach ($evidencePath in @($worldSurfaceLoweringClaim.evidencePaths)) {
}
}
foreach ($feature in @("providerAdvertisements", "commandTransport", "providerSurfaceSession", "providerSurfaceSource", "livePlayableWorldClient", "providerCommandReceipts", "providerAssetManifestDocumentSource", "sceneGraphProjection", "playableWorldProjection", "playableWorldScenePresentation", "unityGameObjectSceneSink", "providerAssetManifestResolution", "providerAssetManifestSource")) {
foreach ($feature in @("providerAdvertisements", "commandTransport", "providerSurfaceSession", "providerSurfaceSource", "providerSurfaceDocumentSource", "livePlayableWorldClient", "providerCommandReceipts", "providerAssetManifestDocumentSource", "sceneGraphProjection", "playableWorldProjection", "playableWorldScenePresentation", "unityGameObjectSceneSink", "providerAssetManifestResolution", "providerAssetManifestSource")) {
if (-not (@($manifest.supportedFeatures) -contains $feature)) {
throw "EveUnity scene provider shell missing supported feature: $feature"
}
@ -99,7 +99,7 @@ foreach ($symbol in @("EveUnitySceneClientSession", "EveUnitySceneProviderSurfac
}
$providerConnectionSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-unity-scene\Runtime\EveUnitySceneProviderConnection.cs") -Raw
foreach ($symbol in @("IEveUnitySceneProviderSurfaceSource", "IEveUnitySceneCommandSink", "EveUnitySceneProviderConnection", "SnapshotAvailable", "CurrentSnapshot", "Connect", "Refresh", "SubmitMoveIntent", "SubmitFocusIntent", "SubmitTargetIntent", "SubmitActionIntent", "Disconnect")) {
foreach ($symbol in @("IEveUnitySceneProviderSurfaceSource", "IEveUnitySceneCommandSink", "IEveUnitySceneProviderSurfaceDocumentSource", "EveUnitySceneProviderSurfaceDocument", "EveUnitySceneProviderSurfaceDocumentSource", "ToSnapshot", "DocumentAvailable", "EveUnitySceneProviderConnection", "SnapshotAvailable", "CurrentSnapshot", "Connect", "Refresh", "SubmitMoveIntent", "SubmitFocusIntent", "SubmitTargetIntent", "SubmitActionIntent", "Disconnect")) {
if (-not $providerConnectionSource.Contains($symbol)) {
throw "EveUnity scene provider connection missing symbol: $symbol"
}
@ -155,7 +155,7 @@ foreach ($symbol in @("TeXMathUnitySceneProjectionAdapter", "tex.math", "embed.t
}
$testSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-unity-scene\Tests\Editor\EveUnitySceneSurfaceLowererTests.cs") -Raw
foreach ($symbol in @("LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "LowerExtractsPlayableArpgWorldFromGenericScene3dSurface", "GenericClientSessionConsumesAetheriaPlayableWorldSnapshotWithoutAetheriaTypes", "GenericProviderConnectionAppliesLiveSnapshotsAndSubmitsCommandsThroughSink", "PlayableWorldPresenterInstantiatesUpdatesAndDespawnsProviderEntities", "LivePlayableWorldClientPresentsProviderSnapshotsAndKeepsCommandsProviderOwned", "LivePlayableWorldClientRefreshesFromProviderSnapshotAfterReceiptWithoutOwningMovement", "AssetManifestMapsProviderAssetRefsToUnityLoadKeysWithoutAetheriaTypes", "AssetManifestCacheTracksPlayableWorldManifestPointerAndLiveUpdates", "AssetManifestDocumentSourceFeedsCacheWithoutChangingSceneLowering", "FakeProviderSurfaceSource", "FakeCommandReceiptSource", "FakeAssetManifestSource", "FakeAssetManifestDocumentSource", "FakeCommandSink", "FakePlayableWorldSceneSink", "SaiVisualNovelLowersThroughRuntimeProjectionAdapterWithoutOwningStoryState", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "pending", "reconciled", "world-projection-node", "playable-world-root", "playable-world-entity", "world-field-3d", "arpg-third-person", "cultmesh://aetheria/assets/manifest", "cultmesh://aetheria/eve/surfaces/aetheria.daemon.game", "aetheria.daemon.move_intent", "sai-vn-scene-stage", "norn-graph-scene-projection", "tex-math-scene-projection", "sai.vn", "norn.graph", "tex.math", "sidecar-advertised-plugin-abi", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1")) {
foreach ($symbol in @("LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "LowerExtractsPlayableArpgWorldFromGenericScene3dSurface", "GenericClientSessionConsumesAetheriaPlayableWorldSnapshotWithoutAetheriaTypes", "GenericProviderConnectionAppliesLiveSnapshotsAndSubmitsCommandsThroughSink", "ProviderSurfaceDocumentSourceFeedsPlayableClientWithoutAetheriaTypes", "PlayableWorldPresenterInstantiatesUpdatesAndDespawnsProviderEntities", "LivePlayableWorldClientPresentsProviderSnapshotsAndKeepsCommandsProviderOwned", "LivePlayableWorldClientRefreshesFromProviderSnapshotAfterReceiptWithoutOwningMovement", "AssetManifestMapsProviderAssetRefsToUnityLoadKeysWithoutAetheriaTypes", "AssetManifestCacheTracksPlayableWorldManifestPointerAndLiveUpdates", "AssetManifestDocumentSourceFeedsCacheWithoutChangingSceneLowering", "FakeProviderSurfaceSource", "FakeProviderSurfaceDocumentSource", "FakeCommandReceiptSource", "FakeAssetManifestSource", "FakeAssetManifestDocumentSource", "FakeCommandSink", "FakePlayableWorldSceneSink", "SaiVisualNovelLowersThroughRuntimeProjectionAdapterWithoutOwningStoryState", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "pending", "reconciled", "world-projection-node", "playable-world-root", "playable-world-entity", "world-field-3d", "arpg-third-person", "cultmesh://aetheria/assets/manifest", "cultmesh://aetheria/eve/surfaces/aetheria.daemon.game", "aetheria.daemon.move_intent", "sai-vn-scene-stage", "norn-graph-scene-projection", "tex-math-scene-projection", "sai.vn", "norn.graph", "tex.math", "sidecar-advertised-plugin-abi", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1")) {
if (-not $testSource.Contains($symbol)) {
throw "EveUnity scene provider shell tests missing symbol: $symbol"
}

View file

@ -67,6 +67,7 @@ node $consumerScript $consumerExport `
--expect-runtime-feature unity-scene:commandTransport `
--expect-runtime-feature unity-scene:providerSurfaceSession `
--expect-runtime-feature unity-scene:providerSurfaceSource `
--expect-runtime-feature unity-scene:providerSurfaceDocumentSource `
--expect-runtime-feature unity-scene:livePlayableWorldClient `
--expect-runtime-feature unity-scene:providerCommandReceipts `
--expect-runtime-feature unity-scene:providerAssetManifestDocumentSource `

View file

@ -1041,7 +1041,7 @@
"splitHandoffPath": "runtimes/incubating/eve-unity-scene/eveunity-scene-split-handoff.json",
"requiredFixtures": ["aetheria-world", "eve-world-smoke"],
"pluginFixtures": ["sai-vn"],
"supportedFeatures": ["providerAdvertisements", "commandTransport", "providerSurfaceSession", "providerSurfaceSource", "livePlayableWorldClient", "providerCommandReceipts", "providerAssetManifestDocumentSource", "providerAssetManifestSource", "sceneGraphProjection", "playableWorldProjection", "playableWorldScenePresentation", "unityGameObjectSceneSink", "providerAssetManifestResolution", "embeddedDocuments"],
"supportedFeatures": ["providerAdvertisements", "commandTransport", "providerSurfaceSession", "providerSurfaceSource", "providerSurfaceDocumentSource", "livePlayableWorldClient", "providerCommandReceipts", "providerAssetManifestDocumentSource", "providerAssetManifestSource", "sceneGraphProjection", "playableWorldProjection", "playableWorldScenePresentation", "unityGameObjectSceneSink", "providerAssetManifestResolution", "embeddedDocuments"],
"supportedPlugins": [
{
"pluginId": "sai.vn",
@ -1127,7 +1127,7 @@
},
{
"path": "runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneProviderConnection.cs",
"contains": ["IEveUnitySceneProviderSurfaceSource", "IEveUnitySceneCommandSink", "EveUnitySceneProviderConnection", "SnapshotAvailable", "CurrentSnapshot", "Connect", "Refresh", "SubmitMoveIntent", "SubmitFocusIntent", "SubmitTargetIntent", "SubmitActionIntent", "Disconnect"]
"contains": ["IEveUnitySceneProviderSurfaceSource", "IEveUnitySceneCommandSink", "IEveUnitySceneProviderSurfaceDocumentSource", "EveUnitySceneProviderSurfaceDocument", "EveUnitySceneProviderSurfaceDocumentSource", "ToSnapshot", "DocumentAvailable", "EveUnitySceneProviderConnection", "SnapshotAvailable", "CurrentSnapshot", "Connect", "Refresh", "SubmitMoveIntent", "SubmitFocusIntent", "SubmitTargetIntent", "SubmitActionIntent", "Disconnect"]
},
{
"path": "runtimes/incubating/eve-unity-scene/Runtime/EveUnityPlayableWorldLiveClient.cs",
@ -1159,7 +1159,7 @@
},
{
"path": "runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"contains": ["LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "LowerExtractsPlayableArpgWorldFromGenericScene3dSurface", "GenericClientSessionConsumesAetheriaPlayableWorldSnapshotWithoutAetheriaTypes", "GenericProviderConnectionAppliesLiveSnapshotsAndSubmitsCommandsThroughSink", "PlayableWorldPresenterInstantiatesUpdatesAndDespawnsProviderEntities", "LivePlayableWorldClientPresentsProviderSnapshotsAndKeepsCommandsProviderOwned", "LivePlayableWorldClientRefreshesFromProviderSnapshotAfterReceiptWithoutOwningMovement", "AssetManifestMapsProviderAssetRefsToUnityLoadKeysWithoutAetheriaTypes", "AssetManifestCacheTracksPlayableWorldManifestPointerAndLiveUpdates", "AssetManifestDocumentSourceFeedsCacheWithoutChangingSceneLowering", "FakeProviderSurfaceSource", "FakeCommandReceiptSource", "FakeAssetManifestSource", "FakeAssetManifestDocumentSource", "FakeCommandSink", "FakePlayableWorldSceneSink", "SaiVisualNovelLowersThroughRuntimeProjectionAdapterWithoutOwningStoryState", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "pending", "reconciled", "world-projection-node", "playable-world-root", "playable-world-entity", "world-field-3d", "arpg-third-person", "cultmesh://aetheria/assets/manifest", "cultmesh://aetheria/eve/surfaces/aetheria.daemon.game", "aetheria.daemon.move_intent", "sai-vn-scene-stage", "norn-graph-scene-projection", "tex-math-scene-projection", "norn.map", "cultmesh://aetheria/norn/map", "sai.vn", "norn.graph", "tex.math", "sidecar-advertised-plugin-abi", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
"contains": ["LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "LowerExtractsPlayableArpgWorldFromGenericScene3dSurface", "GenericClientSessionConsumesAetheriaPlayableWorldSnapshotWithoutAetheriaTypes", "GenericProviderConnectionAppliesLiveSnapshotsAndSubmitsCommandsThroughSink", "ProviderSurfaceDocumentSourceFeedsPlayableClientWithoutAetheriaTypes", "PlayableWorldPresenterInstantiatesUpdatesAndDespawnsProviderEntities", "LivePlayableWorldClientPresentsProviderSnapshotsAndKeepsCommandsProviderOwned", "LivePlayableWorldClientRefreshesFromProviderSnapshotAfterReceiptWithoutOwningMovement", "AssetManifestMapsProviderAssetRefsToUnityLoadKeysWithoutAetheriaTypes", "AssetManifestCacheTracksPlayableWorldManifestPointerAndLiveUpdates", "AssetManifestDocumentSourceFeedsCacheWithoutChangingSceneLowering", "FakeProviderSurfaceSource", "FakeProviderSurfaceDocumentSource", "FakeCommandReceiptSource", "FakeAssetManifestSource", "FakeAssetManifestDocumentSource", "FakeCommandSink", "FakePlayableWorldSceneSink", "SaiVisualNovelLowersThroughRuntimeProjectionAdapterWithoutOwningStoryState", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "pending", "reconciled", "world-projection-node", "playable-world-root", "playable-world-entity", "world-field-3d", "arpg-third-person", "cultmesh://aetheria/assets/manifest", "cultmesh://aetheria/eve/surfaces/aetheria.daemon.game", "aetheria.daemon.move_intent", "sai-vn-scene-stage", "norn-graph-scene-projection", "tex-math-scene-projection", "norn.map", "cultmesh://aetheria/norn/map", "sai.vn", "norn.graph", "tex.math", "sidecar-advertised-plugin-abi", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
},
{
"path": "tools/eveunity/eveunity-capture-contract.test.mjs",