From 1218dbf655cc95fcdb7e83effae24224dda503ea Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 10 Jul 2026 07:17:55 +0100 Subject: [PATCH] Resolve Eve documents behind provider transport --- .../Client/aetheria-rts-contract.ts | 16 +++++++ Aetheria.Rts.Web/Client/app.ts | 44 +++--------------- .../Electron/aetheria-cultmesh.ts | 46 +++++++++++++++++++ .../aetheria-rts-generated-bindings.ts | 19 ++++++++ Aetheria.Rts.Web/Electron/main.ts | 1 + Aetheria.Rts.Web/Electron/preload.cjs | 2 + .../scripts/generate-rts-bindings.mjs | 35 ++++++++++++++ .../scripts/verify-stage7c-electron-rts.ps1 | 4 ++ 8 files changed, 129 insertions(+), 38 deletions(-) diff --git a/Aetheria.Rts.Web/Client/aetheria-rts-contract.ts b/Aetheria.Rts.Web/Client/aetheria-rts-contract.ts index 51a714aa5..01fe33291 100644 --- a/Aetheria.Rts.Web/Client/aetheria-rts-contract.ts +++ b/Aetheria.Rts.Web/Client/aetheria-rts-contract.ts @@ -348,6 +348,21 @@ export type AetheriaEveSurfaceRequest = { recordKey?: string; }; +export type EveEmbeddedDocumentRequest = { + documentId: string; + schemaId?: string; + slotId?: string; + presentationKind?: string; + context?: Record; +}; + +export type EveResolvedDocument = { + documentId: string; + schemaId: string; + document?: unknown; + surface?: AetheriaMenuSurfaceTree; +}; + export type EveProviderAdvertisement = { providerId: string; title: string; @@ -429,6 +444,7 @@ export type AetheriaRtsApi = { surfaceCatalogIndex(): Promise; eveSurface(request: AetheriaEveSurfaceRequest): Promise; eveProviderAdvertisement(): Promise; + eveDocument(request: EveEmbeddedDocumentRequest): Promise; submitEveCommand(request: AetheriaEveCommandRequest): Promise; windowControl(action: "minimize" | "maximize" | "close"): Promise; health(): Promise; diff --git a/Aetheria.Rts.Web/Client/app.ts b/Aetheria.Rts.Web/Client/app.ts index c4f23adc4..30e9997d9 100644 --- a/Aetheria.Rts.Web/Client/app.ts +++ b/Aetheria.Rts.Web/Client/app.ts @@ -6,9 +6,7 @@ import { type EveSurfaceComponent, } from "../node_modules/@gamecult/eve-browser-lowering/dist/index.js"; import type { - AetheriaMenuSurfaceDocument, AetheriaRtsApi, - Viewport, } from "./aetheria-rts-contract.js"; export {}; @@ -65,44 +63,14 @@ function surfaceRequest(surface: EveProviderSurfaceAdvertisement): { surfaceId?: async function resolveEveDocument( request: EveEmbeddedDocumentRequest, component: EveSurfaceComponent, -): Promise<{ document?: unknown; documentId: string; schemaId: string; surface?: AetheriaMenuSurfaceDocument["surface"] } | undefined> { - if (request.schemaId === "gamecult.eve.surface.v1" || request.slotId === "mainMenuPanel") { - const surface = await window.aetheriaRts.eveSurface({ - surfaceId: request.documentId, - }); - return { - documentId: request.documentId, - schemaId: "gamecult.eve.surface.v1", - surface: surface.surface, - }; - } - - const viewport = viewportFromComponent(component); - if (request.schemaId === "gamecult.aetheria.render_splats_viewport.v1" || request.slotId === "renderSplats") { - return { - document: await window.aetheriaRts.renderSplatsViewport(viewport), - documentId: request.documentId, - schemaId: "gamecult.aetheria.render_splats_viewport.v1", - }; - } - if (request.schemaId === "gamecult.aetheria.gravity_viewport.v1" || request.slotId === "gravity") { - return { - document: await window.aetheriaRts.gravityViewport(viewport), - documentId: request.documentId, - schemaId: "gamecult.aetheria.gravity_viewport.v1", - }; - } - if (request.schemaId === "gamecult.aetheria.objects_viewport.v1" || request.slotId === "objects") { - return { - document: await window.aetheriaRts.objectsViewport(viewport), - documentId: request.documentId, - schemaId: "gamecult.aetheria.objects_viewport.v1", - }; - } - return undefined; +): ReturnType { + return window.aetheriaRts.eveDocument({ + ...request, + context: { viewport: viewportFromComponent(component) }, + }); } -function viewportFromComponent(component: EveSurfaceComponent): Viewport { +function viewportFromComponent(component: EveSurfaceComponent): Record { const props = component.props ?? {}; return { minX: numberProp(props.minX, -1500), diff --git a/Aetheria.Rts.Web/Electron/aetheria-cultmesh.ts b/Aetheria.Rts.Web/Electron/aetheria-cultmesh.ts index ee1b4a26a..809ea33f1 100644 --- a/Aetheria.Rts.Web/Electron/aetheria-cultmesh.ts +++ b/Aetheria.Rts.Web/Electron/aetheria-cultmesh.ts @@ -104,6 +104,21 @@ export type AetheriaEveSurfaceRequest = { recordKey?: string; }; +export type EveEmbeddedDocumentRequest = { + documentId: string; + schemaId?: string; + slotId?: string; + presentationKind?: string; + context?: Record; +}; + +export type EveResolvedDocument = { + documentId: string; + schemaId: string; + document?: unknown; + surface?: AetheriaMenuSurfaceDocument["surface"]; +}; + export type AetheriaEveCommandRequest = { providerId?: string; surfaceId?: string; @@ -406,6 +421,27 @@ export class AetheriaCultMeshClient { return normalizeEveProviderAdvertisement(await document.latest(this.queryContext())); } + public async eveDocument(request: EveEmbeddedDocumentRequest): Promise { + const schemaId = request?.schemaId?.trim() || ""; + if (!request?.documentId?.trim()) throw new Error("Eve embedded document request is missing documentId."); + if (schemaId === eveSurfaceSchemaId || request.slotId === "mainMenuPanel") { + const surface = await this.eveSurface({ surfaceId: request.documentId }); + return { documentId: request.documentId, schemaId: eveSurfaceSchemaId, surface: surface.surface }; + } + + const viewport = viewportFromEmbeddedDocumentContext(request.context); + if (schemaId === AetheriaRtsSchemas.renderSplatsViewport || request.slotId === "renderSplats") { + return { documentId: request.documentId, schemaId: AetheriaRtsSchemas.renderSplatsViewport, document: await this.renderSplatsViewport(viewport) }; + } + if (schemaId === AetheriaRtsSchemas.gravityViewport || request.slotId === "gravity") { + return { documentId: request.documentId, schemaId: AetheriaRtsSchemas.gravityViewport, document: await this.gravityViewport(viewport) }; + } + if (schemaId === AetheriaRtsSchemas.objectsViewport || request.slotId === "objects") { + return { documentId: request.documentId, schemaId: AetheriaRtsSchemas.objectsViewport, document: await this.objectsViewport(viewport) }; + } + return undefined; + } + public async submitEveCommand(request: AetheriaEveCommandRequest): Promise { const issuedAtUtc = request?.issuedAtUtc || new Date().toISOString(); const commandId = `${this.runtimeId}:eve:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`; @@ -967,6 +1003,16 @@ function normalizeEveProviderAdvertisement(document: unknown): import("./aetheri }; } +function viewportFromEmbeddedDocumentContext(context: Record | undefined): ViewportRequest { + const source = objectValue(context?.viewport); + return { + minX: numberOr(source.minX, -1500), + minY: numberOr(source.minY, -1000), + maxX: numberOr(source.maxX, 1500), + maxY: numberOr(source.maxY, 1000), + }; +} + function normalizeEveSurfaceDocument(document: unknown): AetheriaMenuSurfaceDocument { const portableSlots = Array.isArray(document) && typeof document[1] === "string" && diff --git a/Aetheria.Rts.Web/Electron/aetheria-rts-generated-bindings.ts b/Aetheria.Rts.Web/Electron/aetheria-rts-generated-bindings.ts index f1bf472f5..832d0a295 100644 --- a/Aetheria.Rts.Web/Electron/aetheria-rts-generated-bindings.ts +++ b/Aetheria.Rts.Web/Electron/aetheria-rts-generated-bindings.ts @@ -130,6 +130,7 @@ export const AetheriaRtsIpcChannels = { surfaceCatalogIndex: "aetheria-rts:surface-catalog-index", eveSurface: "aetheria-rts:eve-surface", eveProviderAdvertisement: "eve:provider-advertisement", + eveDocument: "eve:embedded-document", submitEveCommand: "aetheria-rts:submit-eve-command", windowControl: "aetheria-rts:window-control", health: "aetheria-rts:health", @@ -1960,6 +1961,21 @@ export type AetheriaEveSurfaceRequest = { recordKey?: string; }; +export type EveEmbeddedDocumentRequest = { + documentId: string; + schemaId?: string; + slotId?: string; + presentationKind?: string; + context?: Record; +}; + +export type EveResolvedDocument = { + documentId: string; + schemaId: string; + document?: unknown; + surface?: AetheriaMenuSurfaceTree; +}; + export type EveProviderAdvertisement = { providerId: string; title: string; @@ -2041,6 +2057,7 @@ export type AetheriaRtsMainClient = { setTarget(request: AetheriaRuntimeSetTargetRequest): Promise; eveSurface(request: AetheriaEveSurfaceRequest): Promise; eveProviderAdvertisement(): Promise; + eveDocument(request: EveEmbeddedDocumentRequest): Promise; submitEveCommand(request: AetheriaEveCommandRequest): Promise; surfaceCatalogDiagnostics(): CultMeshSurfaceCatalogDiagnostic; surfaceCatalogIndexDiagnostics(): CultMeshSurfaceCatalogIndexDiagnostic; @@ -2092,6 +2109,8 @@ export function registerAetheriaRtsIpcHandlers( getClient().eveSurface(request)); ipcMain.handle(AetheriaRtsIpcChannels.eveProviderAdvertisement, async () => getClient().eveProviderAdvertisement()); + ipcMain.handle(AetheriaRtsIpcChannels.eveDocument, async (_event, request: EveEmbeddedDocumentRequest) => + getClient().eveDocument(request)); ipcMain.handle(AetheriaRtsIpcChannels.submitEveCommand, async (_event, request: AetheriaEveCommandRequest) => getClient().submitEveCommand(request)); ipcMain.handle(AetheriaRtsIpcChannels.surfaceCatalog, () => getClient().surfaceCatalogDiagnostics()); diff --git a/Aetheria.Rts.Web/Electron/main.ts b/Aetheria.Rts.Web/Electron/main.ts index 7950371d8..07e236381 100644 --- a/Aetheria.Rts.Web/Electron/main.ts +++ b/Aetheria.Rts.Web/Electron/main.ts @@ -199,6 +199,7 @@ async function runElectronSmoke(window: BrowserWindow): Promise ipcRenderer.invoke(channels.surfaceCatalogIndex), eveSurface: request => ipcRenderer.invoke(channels.eveSurface, request), eveProviderAdvertisement: request => ipcRenderer.invoke(channels.eveProviderAdvertisement, request), + eveDocument: request => ipcRenderer.invoke(channels.eveDocument, request), submitEveCommand: request => ipcRenderer.invoke(channels.submitEveCommand, request), windowControl: request => ipcRenderer.invoke(channels.windowControl, request), health: () => ipcRenderer.invoke(channels.health), diff --git a/Aetheria.Rts.Web/scripts/generate-rts-bindings.mjs b/Aetheria.Rts.Web/scripts/generate-rts-bindings.mjs index 9a93bcff9..d0591fbab 100644 --- a/Aetheria.Rts.Web/scripts/generate-rts-bindings.mjs +++ b/Aetheria.Rts.Web/scripts/generate-rts-bindings.mjs @@ -43,6 +43,7 @@ const ipcChannels = [ ["surfaceCatalogIndex", "aetheria-rts:surface-catalog-index"], ["eveSurface", "aetheria-rts:eve-surface"], ["eveProviderAdvertisement", "eve:provider-advertisement"], + ["eveDocument", "eve:embedded-document"], ["submitEveCommand", "aetheria-rts:submit-eve-command"], ["windowControl", "aetheria-rts:window-control"], ["health", "aetheria-rts:health"], @@ -486,6 +487,21 @@ export type AetheriaEveSurfaceRequest = { recordKey?: string; }; +export type EveEmbeddedDocumentRequest = { + documentId: string; + schemaId?: string; + slotId?: string; + presentationKind?: string; + context?: Record; +}; + +export type EveResolvedDocument = { + documentId: string; + schemaId: string; + document?: unknown; + surface?: AetheriaMenuSurfaceTree; +}; + export type EveProviderAdvertisement = { providerId: string; title: string; @@ -567,6 +583,7 @@ export type AetheriaRtsMainClient = { setTarget(request: AetheriaRuntimeSetTargetRequest): Promise; eveSurface(request: AetheriaEveSurfaceRequest): Promise; eveProviderAdvertisement(): Promise; + eveDocument(request: EveEmbeddedDocumentRequest): Promise; submitEveCommand(request: AetheriaEveCommandRequest): Promise; surfaceCatalogDiagnostics(): CultMeshSurfaceCatalogDiagnostic; surfaceCatalogIndexDiagnostics(): CultMeshSurfaceCatalogIndexDiagnostic; @@ -618,6 +635,8 @@ export function registerAetheriaRtsIpcHandlers( getClient().eveSurface(request)); ipcMain.handle(AetheriaRtsIpcChannels.eveProviderAdvertisement, async () => getClient().eveProviderAdvertisement()); + ipcMain.handle(AetheriaRtsIpcChannels.eveDocument, async (_event, request: EveEmbeddedDocumentRequest) => + getClient().eveDocument(request)); ipcMain.handle(AetheriaRtsIpcChannels.submitEveCommand, async (_event, request: AetheriaEveCommandRequest) => getClient().submitEveCommand(request)); ipcMain.handle(AetheriaRtsIpcChannels.surfaceCatalog, () => getClient().surfaceCatalogDiagnostics()); @@ -1164,6 +1183,21 @@ export type AetheriaEveSurfaceRequest = { recordKey?: string; }; +export type EveEmbeddedDocumentRequest = { + documentId: string; + schemaId?: string; + slotId?: string; + presentationKind?: string; + context?: Record; +}; + +export type EveResolvedDocument = { + documentId: string; + schemaId: string; + document?: unknown; + surface?: AetheriaMenuSurfaceTree; +}; + export type EveProviderAdvertisement = { providerId: string; title: string; @@ -1245,6 +1279,7 @@ export type AetheriaRtsApi = { surfaceCatalogIndex(): Promise; eveSurface(request: AetheriaEveSurfaceRequest): Promise; eveProviderAdvertisement(): Promise; + eveDocument(request: EveEmbeddedDocumentRequest): Promise; submitEveCommand(request: AetheriaEveCommandRequest): Promise; windowControl(action: "minimize" | "maximize" | "close"): Promise; health(): Promise; diff --git a/Aetheria.Rts.Web/scripts/verify-stage7c-electron-rts.ps1 b/Aetheria.Rts.Web/scripts/verify-stage7c-electron-rts.ps1 index 0aa07c9a3..df670c133 100644 --- a/Aetheria.Rts.Web/scripts/verify-stage7c-electron-rts.ps1 +++ b/Aetheria.Rts.Web/scripts/verify-stage7c-electron-rts.ps1 @@ -15,7 +15,11 @@ if (-not (Get-Content wwwroot\index.html -Raw).Contains('eve-surface-host')) { $appText = Get-Content wwwroot\app.js -Raw if (-not $appText.Contains('window.aetheriaRts.eveProviderAdvertisement') -or -not $appText.Contains('EveBrowserProviderHost') -or + -not $appText.Contains('window.aetheriaRts.eveDocument') -or $appText.Contains('eve:surface:aetheria.daemon.game') -or + $appText.Contains('gamecult.aetheria.gravity_viewport.v1') -or + $appText.Contains('gamecult.aetheria.render_splats_viewport.v1') -or + $appText.Contains('gamecult.aetheria.objects_viewport.v1') -or $appText.Contains('legacyViewportMode') -or $appText.Contains('mainMenuSurface') -or $appText.Contains('main-menu-mode')) {