2026-06-25 18:09:33 +01:00
import { encode } from "@msgpack/msgpack" ;
import { performance } from "node:perf_hooks" ;
import { CultMesh } from "cultmesh-ts" ;
import type {
2026-06-27 20:14:13 +01:00
CultMeshDocumentCatalog ,
CultMeshDocumentPublicationSource ,
CultMeshPublicationDocumentBinding ,
2026-06-25 18:09:33 +01:00
CultMeshOperationContext ,
CultMeshQueryContext ,
CultMeshSurfaceCatalogIndexDiagnostic ,
CultMeshVerse ,
} from "cultmesh-ts" ;
import type {
CultNetDocumentPutRawMessage ,
CultNetPeer ,
} from "cultnet-ts" ;
import {
AetheriaRtsSchemas ,
2026-07-05 19:56:18 +01:00
createAetheriaRuntimeGameDocuments ,
2026-07-06 03:41:32 +01:00
createAetheriaRuntimeGameOperationHandles ,
createAetheriaRuntimeGameVerseHandles ,
createAetheriaRuntimeGameQueryHandles ,
describeAetheriaRuntimeGameLiveFeedSurface ,
describeAetheriaRuntimeGameQueryHandles ,
describeAetheriaRuntimeGameSurfaceCatalog ,
2026-06-25 18:09:33 +01:00
type AetheriaRuntimeDaemonCommandReceipt ,
2026-06-30 19:14:49 +01:00
type AssetManifestDocument ,
type AuthorityStatusDocument ,
type DaemonHealthDocument ,
2026-06-25 18:09:33 +01:00
type GravityViewportResponse ,
2026-06-30 19:14:49 +01:00
type InventoryDocument ,
2026-06-25 18:09:33 +01:00
type ObjectsViewportResponse ,
2026-07-05 01:17:27 +01:00
type RenderSplatsViewportResponse ,
2026-07-06 03:41:32 +01:00
type AetheriaRuntimeGameLiveFeedDiagnostic ,
type AetheriaRuntimeGameQueryDiagnostic ,
type AetheriaRuntimeGameSurfaceCatalogDiagnostic ,
type AetheriaRuntimeGameOperationHandles ,
type AetheriaRuntimeGameVerseHandles ,
2026-07-05 19:56:18 +01:00
type AetheriaRuntimeGameDocuments ,
2026-06-25 18:09:33 +01:00
type AetheriaRuntimeViewportFeedRequest ,
type AetheriaRuntimeViewportFeedSnapshot ,
type RtsSetMoveVectorRequest ,
type RtsSetTargetRequest ,
2026-06-30 19:14:49 +01:00
type SelectedObjectDocument ,
2026-06-25 18:09:33 +01:00
type SelectedObjectRequest ,
2026-06-30 19:14:49 +01:00
type StarbridgeSessionDocument ,
2026-06-25 18:09:33 +01:00
type ViewportRequest ,
type ViewportResponse ,
} from "./aetheria-rts-bindings.js" ;
import {
2026-06-30 19:14:49 +01:00
readAuthorityStatusDocument ,
readAssetManifestDocument ,
readDaemonHealthDocument ,
2026-07-06 03:21:20 +01:00
readGravityViewportDocument ,
2026-07-06 03:32:45 +01:00
readInventoryDocument ,
2026-07-06 03:21:20 +01:00
readObjectsViewportDocument ,
readRenderSplatsViewportDocument ,
2026-07-06 03:32:45 +01:00
readSelectedObjectDocument ,
2026-06-30 19:14:49 +01:00
readStarbridgeSessionSummaryDocument ,
2026-07-06 03:21:20 +01:00
readViewportDocument ,
2026-06-30 19:14:49 +01:00
} from "./aetheria-rts-local-documents.js" ;
2026-06-25 18:09:33 +01:00
const connectionId = 0x43554c54 ;
2026-07-06 02:56:48 +01:00
const cultMeshCdnAssetBlobSchemaId = "gamecult.cultmesh.cdn.asset_blob.v1" ;
2026-06-25 18:09:33 +01:00
2026-06-27 20:14:13 +01:00
type AetheriaPublicationDocumentSpec = CultMeshPublicationDocumentBinding & {
readonly localPath : string ;
readonly remoteRecordKey? : string ;
2026-06-25 18:09:33 +01:00
} ;
2026-07-06 03:41:32 +01:00
type AetheriaRuntimeGameQueryExecutors = {
2026-07-05 15:12:29 +01:00
mapViewport : ( request : ViewportRequest ) = > Promise < ViewportResponse > ;
objectsViewport : ( request : ViewportRequest ) = > Promise < ObjectsViewportResponse > ;
gravityViewport : ( request : ViewportRequest ) = > Promise < GravityViewportResponse > ;
renderSplatsViewport : ( request : ViewportRequest ) = > Promise < RenderSplatsViewportResponse > ;
selectedObject : ( request : SelectedObjectRequest ) = > Promise < SelectedObjectDocument > ;
inventory : ( request : SelectedObjectRequest ) = > Promise < InventoryDocument > ;
daemonHealth : ( ) = > Promise < DaemonHealthDocument > ;
authorityStatus : ( ) = > Promise < AuthorityStatusDocument > ;
starbridgeSession : ( ) = > Promise < StarbridgeSessionDocument > ;
assetManifest : ( ) = > Promise < AssetManifestDocument > ;
} ;
2026-06-25 18:09:33 +01:00
export type AetheriaCultMeshClientOptions = {
publicationMode ? : "local" | "remote" ;
snapshotTimeoutMs? : number ;
} ;
2026-07-04 22:46:04 +01:00
export type AetheriaCultMeshDaemonTarget = {
readonly uri : string ;
readonly peerId? : string ;
readonly verseId? : string ;
readonly role? : string ;
readonly endpoints? : readonly string [ ] ;
} ;
2026-06-25 18:09:33 +01:00
export type {
BodyView ,
EntityStatus ,
GravityViewportResponse ,
GravityInfluence ,
InventoryItem ,
ObjectsViewportResponse ,
AetheriaRuntimeViewportFeedRequest ,
AetheriaRuntimeViewportFeedSnapshot ,
RtsSetMoveVectorRequest ,
RtsSetTargetRequest ,
2026-06-30 19:14:49 +01:00
SelectedObjectDocument ,
2026-06-25 18:09:33 +01:00
SelectedObjectRequest ,
2026-06-30 19:14:49 +01:00
StarbridgeSessionDocument ,
2026-06-25 18:09:33 +01:00
ViewObject ,
ViewportRequest ,
ViewportResponse ,
} from "./aetheria-rts-bindings.js" ;
export class AetheriaCultMeshClient {
# peer : CultNetPeer | null = null ;
private readonly verse : CultMeshVerse ;
private readonly queryVerse : CultMeshVerse ;
private readonly commandVerse : CultMeshVerse ;
2026-07-04 22:46:04 +01:00
private readonly daemonTarget : Required < AetheriaCultMeshDaemonTarget > ;
2026-06-25 18:09:33 +01:00
public constructor (
2026-07-04 22:46:04 +01:00
daemonTarget : string | AetheriaCultMeshDaemonTarget ,
2026-06-25 18:09:33 +01:00
statePath : string ,
2026-07-05 21:43:00 +01:00
private readonly runtimeId = "aetheria-electron-client" ,
2026-06-25 18:09:33 +01:00
options : AetheriaCultMeshClientOptions = { } ,
) {
2026-07-04 22:46:04 +01:00
this . daemonTarget = normalizeDaemonTarget ( daemonTarget ) ;
2026-06-25 18:09:33 +01:00
const publicationMode = options . publicationMode ? ? "local" ;
2026-07-04 22:46:04 +01:00
this . publicationDescription = publicationMode === "remote" ? this . daemonTarget.uri : statePath ;
2026-06-25 18:09:33 +01:00
this . verse = CultMesh . verse ( "aetheria.local" , this . runtimeId ) ;
this . queryVerse = publicationMode === "remote"
2026-06-27 20:14:13 +01:00
? this . verse . withRoute ( "network" , this . publicationDescription )
: this . verse . withRoute ( "shared-memory" , this . publicationDescription ) ;
2026-06-25 18:09:33 +01:00
this . commandVerse = this . verse
2026-07-04 22:46:04 +01:00
. withRoute ( "network" , this . daemonTarget . uri )
2026-06-25 18:09:33 +01:00
. withClaim ( "commander-control" , { shardId : "aetheria.local" } ) ;
2026-06-27 20:14:13 +01:00
this . publications = CultMesh . documentsFromPublication (
this . createPublicationSource ( publicationMode ) ,
createAetheriaPublicationDocuments ( statePath , publicationMode ) ,
{
routeHint : this.queryVerse.context.routeHint ,
timeoutMs : options.snapshotTimeoutMs ,
pollMs : 50 ,
messageIdPrefix : ` ${ this . runtimeId } :snapshot ` ,
} ,
) ;
2026-06-25 18:09:33 +01:00
const executors = {
2026-07-06 03:21:20 +01:00
mapViewport : async ( request : ViewportRequest ) = >
readViewportDocument ( await this . fetchViewportDocument ( AetheriaRtsSchemas . gameViewport , "aetheria.viewport.map" , request ) ) ,
objectsViewport : async ( request : ViewportRequest ) = >
readObjectsViewportDocument ( await this . fetchViewportDocument ( AetheriaRtsSchemas . objectsViewport , "aetheria.viewport.objects" , request ) ) ,
gravityViewport : async ( request : ViewportRequest ) = >
readGravityViewportDocument ( await this . fetchViewportDocument ( AetheriaRtsSchemas . gravityViewport , "aetheria.viewport.gravity" , request ) ) ,
renderSplatsViewport : async ( request : ViewportRequest ) = >
readRenderSplatsViewportDocument ( await this . fetchViewportDocument ( AetheriaRtsSchemas . renderSplatsViewport , "aetheria.viewport.render_splats" , request ) ) ,
2026-07-06 03:32:45 +01:00
selectedObject : async ( request : SelectedObjectRequest ) = >
readSelectedObjectDocument ( await this . fetchIndexedDocument ( AetheriaRtsSchemas . selectedObject , "aetheria.object.selected" , request . entityIndex ) ) ,
inventory : async ( request : SelectedObjectRequest ) = >
readInventoryDocument ( await this . fetchIndexedDocument ( AetheriaRtsSchemas . inventory , "aetheria.inventory" , request . entityIndex ) ) ,
2026-06-30 19:14:49 +01:00
daemonHealth : async ( ) = > readDaemonHealthDocument ( await this . fetchDaemonHealthDocument ( ) ) ,
authorityStatus : async ( ) = > readAuthorityStatusDocument ( await this . fetchAuthorityPolicyDocument ( ) ) ,
starbridgeSession : async ( ) = > readStarbridgeSessionSummaryDocument ( await this . fetchStarbridgeSessionSummaryDocument ( ) ) ,
assetManifest : async ( ) = > readAssetManifestDocument ( await this . fetchAssetManifestDocument ( ) ) ,
2026-06-25 18:09:33 +01:00
} ;
2026-07-05 15:12:29 +01:00
this . queryExecutors = executors ;
2026-07-06 03:41:32 +01:00
this . queries = createAetheriaRuntimeGameQueryHandles (
2026-06-25 18:09:33 +01:00
executors ,
this . queryVerse . context . routeHint ,
{
objectsViewport : CultMesh.pollingQueryWatcher ( executors . objectsViewport , { intervalMs : 50 } ) ,
gravityViewport : CultMesh.pollingQueryWatcher ( executors . gravityViewport , { intervalMs : 50 } ) ,
2026-07-05 01:17:27 +01:00
renderSplatsViewport : CultMesh.pollingQueryWatcher ( executors . renderSplatsViewport , { intervalMs : 50 } ) ,
2026-06-25 18:09:33 +01:00
selectedObject : CultMesh.pollingQueryWatcher ( executors . selectedObject , { intervalMs : 50 } ) ,
inventory : CultMesh.pollingQueryWatcher ( executors . inventory , { intervalMs : 50 } ) ,
daemonHealth : CultMesh.pollingQueryWatcher ( executors . daemonHealth , { intervalMs : 250 } ) ,
authorityStatus : CultMesh.pollingQueryWatcher ( executors . authorityStatus , { intervalMs : 250 } ) ,
starbridgeSession : CultMesh.pollingQueryWatcher ( executors . starbridgeSession , { intervalMs : 250 } ) ,
2026-06-28 01:18:21 +01:00
assetManifest : CultMesh.pollingQueryWatcher ( executors . assetManifest , { intervalMs : 1000 } ) ,
2026-06-25 18:09:33 +01:00
} ,
) ;
2026-07-05 19:56:18 +01:00
this . documents = createAetheriaRuntimeGameDocuments (
2026-06-25 18:09:33 +01:00
this . queryVerse . context . routeHint ,
{
daemonFrame : async ( ) = > this . fetchLatestFrameDocument ( ) ,
daemonHealth : async ( ) = > this . fetchDaemonHealthDocument ( ) ,
authorityPolicy : async ( ) = > this . fetchAuthorityPolicyDocument ( ) ,
starbridgeSession : async ( ) = > this . fetchStarbridgeSessionSummaryDocument ( ) ,
2026-06-28 01:18:21 +01:00
assetManifest : async ( ) = > this . fetchAssetManifestDocument ( ) ,
2026-06-25 18:09:33 +01:00
} ,
) ;
2026-07-06 03:41:32 +01:00
this . operations = createAetheriaRuntimeGameOperationHandles (
2026-06-25 18:09:33 +01:00
( commandId , issuedAtUtc , command , context ) = >
this . sendCommandDocument ( commandId , issuedAtUtc , command , context ) ,
) ;
2026-07-06 03:41:32 +01:00
this . aetheria = createAetheriaRuntimeGameVerseHandles (
2026-06-25 18:09:33 +01:00
this . queryVerse . context ,
this . commandVerse . context ,
this . queries ,
this . operations ,
2026-06-27 15:26:20 +01:00
this . documents ,
2026-06-25 18:09:33 +01:00
) ;
}
2026-06-27 20:14:13 +01:00
private readonly publicationDescription : string ;
private readonly publications : CultMeshDocumentCatalog ;
2026-07-06 03:41:32 +01:00
private readonly queryExecutors : AetheriaRuntimeGameQueryExecutors ;
private readonly queries : ReturnType < typeof createAetheriaRuntimeGameQueryHandles > ;
2026-07-05 19:56:18 +01:00
private readonly documents : AetheriaRuntimeGameDocuments ;
2026-07-06 03:41:32 +01:00
private readonly operations : AetheriaRuntimeGameOperationHandles ;
private readonly aetheria : AetheriaRuntimeGameVerseHandles ;
2026-06-25 18:09:33 +01:00
public async close ( ) : Promise < void > {
this . # peer ? . close ( ) ;
this . # peer = null ;
}
public async waitForFrame ( timeoutMs : number ) : Promise < void > {
const started = Date . now ( ) ;
let lastError = "" ;
while ( Date . now ( ) - started < timeoutMs ) {
try {
await this . mapViewport ( CultMesh . viewportRequest ( CultMesh . rectFromBounds ( - 1000 , - 1000 , 1000 , 1000 ) ) ) ;
return ;
} catch ( error ) {
lastError = error instanceof Error ? error.message : String ( error ) ;
await delay ( 250 ) ;
}
}
2026-07-04 22:46:04 +01:00
throw new Error ( ` Timed out waiting for Aetheria CultMesh frame at ${ this . daemonTarget . uri } . ${ lastError } ` ) ;
2026-06-25 18:09:33 +01:00
}
public async mapViewport ( request : ViewportRequest ) : Promise < ViewportResponse > {
2026-07-05 16:59:06 +01:00
return this . aetheria . zone ( ) . viewport . within ( request ) ;
2026-06-25 18:09:33 +01:00
}
public async objectsViewport ( request : ViewportRequest ) : Promise < ObjectsViewportResponse > {
2026-07-05 16:59:06 +01:00
return this . aetheria . zone ( ) . objects . visibleWithin ( request ) ;
2026-06-25 18:09:33 +01:00
}
public async gravityViewport ( request : ViewportRequest ) : Promise < GravityViewportResponse > {
2026-07-05 16:59:06 +01:00
return this . aetheria . zone ( ) . gravity . within ( request ) ;
2026-06-25 18:09:33 +01:00
}
2026-07-05 01:17:27 +01:00
public async renderSplatsViewport ( request : ViewportRequest ) : Promise < RenderSplatsViewportResponse > {
2026-07-05 16:59:06 +01:00
return this . aetheria . zone ( ) . renderSplats . within ( request ) ;
2026-07-05 01:17:27 +01:00
}
2026-06-30 19:14:49 +01:00
public async selectedObject ( request : SelectedObjectRequest ) : Promise < SelectedObjectDocument > {
2026-07-05 16:59:06 +01:00
return this . aetheria . selectedObject ( request . entityIndex ) ;
2026-06-25 18:09:33 +01:00
}
2026-06-30 19:14:49 +01:00
public async inventory ( request : SelectedObjectRequest ) : Promise < InventoryDocument > {
2026-07-05 16:59:06 +01:00
return this . aetheria . inventory ( request . entityIndex ) ;
2026-06-25 18:09:33 +01:00
}
2026-06-30 19:14:49 +01:00
public async daemonHealth ( ) : Promise < DaemonHealthDocument > {
2026-06-25 18:09:33 +01:00
return this . aetheria . daemon . health ( ) ;
}
2026-06-30 19:14:49 +01:00
public async authorityStatus ( ) : Promise < AuthorityStatusDocument > {
2026-06-25 18:09:33 +01:00
return this . aetheria . daemon . authorityStatus ( ) ;
}
2026-06-30 19:14:49 +01:00
public async starbridgeSession ( ) : Promise < StarbridgeSessionDocument > {
2026-06-25 18:09:33 +01:00
return this . aetheria . daemon . starbridgeSession ( ) ;
}
2026-06-30 19:14:49 +01:00
public async assetManifest ( ) : Promise < AssetManifestDocument > {
2026-06-28 01:18:21 +01:00
return this . aetheria . daemon . assetManifest ( ) ;
}
2026-06-27 20:14:13 +01:00
2026-07-06 02:56:48 +01:00
public async assetBlob ( uri : string ) : Promise < { bytes : Uint8Array ; mimeType : string } > {
const recordKey = normalizeCultMeshAssetUri ( uri ) ;
const document = CultMesh . documentFromPublication (
{
kind : "peer-snapshot" ,
peer : ( ) = > this . peer ( ) ,
endpoint : this.resolvedRudpEndpoint ( ) ,
} ,
cultMeshCdnAssetBlobSchemaId ,
recordKey ,
{
documentId : recordKey ,
routeHint : this.queryVerse.context.routeHint ,
sourceId : recordKey ,
timeoutMs : 1500 ,
pollMs : 50 ,
messageIdPrefix : ` ${ this . runtimeId } :asset ` ,
} ,
) ;
const bytes = normalizeAssetBlob ( await document . latest ( this . queryContext ( ) ) ) ;
const manifest = await this . assetManifest ( ) . catch ( ( ) = > null ) ;
return {
bytes ,
mimeType : resolveAssetMimeType ( recordKey , manifest ) ,
} ;
}
2026-07-06 03:41:32 +01:00
public queryDiagnostics ( ) : Readonly < Record < string , AetheriaRuntimeGameQueryDiagnostic > > {
return describeAetheriaRuntimeGameQueryHandles ( this . queries ) ;
2026-06-25 18:09:33 +01:00
}
2026-07-06 03:41:32 +01:00
public liveFeedDiagnostics ( ) : Readonly < Record < string , AetheriaRuntimeGameLiveFeedDiagnostic > > {
2026-06-25 18:09:33 +01:00
return {
2026-07-06 03:41:32 +01:00
viewportFeed : describeAetheriaRuntimeGameLiveFeedSurface ( this . createViewportFeed ( ) ) ,
2026-06-25 18:09:33 +01:00
} ;
}
2026-07-06 03:41:32 +01:00
public surfaceCatalogDiagnostics ( ) : AetheriaRuntimeGameSurfaceCatalogDiagnostic {
const catalog = describeAetheriaRuntimeGameSurfaceCatalog ( this . queries , this . operations , this . documents ) ;
2026-06-25 18:09:33 +01:00
return CultMesh . describeSurfaceCatalog ( catalog . catalogId , [
. . . catalog . surfaces ,
CultMesh . describeSurface ( this . createViewportFeed ( ) ) ,
] ) ;
}
public surfaceCatalogIndexDiagnostics ( ) : CultMeshSurfaceCatalogIndexDiagnostic {
return CultMesh . surfaceCatalogIndex ( this . surfaceCatalogDiagnostics ( ) ) ;
}
public watchViewportFeed (
request : AetheriaRuntimeViewportFeedRequest ,
callback : ( snapshot : AetheriaRuntimeViewportFeedSnapshot ) = > void ,
) : ( ) = > void {
return this . createViewportFeed ( ) . watch ( request , this . queryContext ( ) , callback ) ;
}
public async setMoveVector ( request : RtsSetMoveVectorRequest ) : Promise < AetheriaRuntimeDaemonCommandReceipt > {
return this . aetheria . entity ( request . actorEntityKey ) . pilot . move (
CultMesh . vec2 ( request . directionX , request . directionY ) ,
{
scalar : request.scalar ,
observedFrameId : request.observedFrameId ,
} ,
) ;
}
public async setTarget ( request : RtsSetTargetRequest ) : Promise < AetheriaRuntimeDaemonCommandReceipt > {
return this . aetheria . entity ( request . actorEntityKey ) . pilot . target ( request . targetEntityKey , {
observedFrameId : request.observedFrameId ,
} ) ;
}
private async fetchLatestFrameDocument ( ) : Promise < unknown > {
2026-06-27 20:14:13 +01:00
return this . fetchPublicationDocument ( AetheriaRtsSchemas . daemonFrame ) ;
2026-06-25 18:09:33 +01:00
}
private async fetchDaemonHealthDocument ( ) : Promise < unknown > {
2026-06-27 20:14:13 +01:00
return this . fetchPublicationDocument ( AetheriaRtsSchemas . daemonHealth ) ;
2026-06-25 18:09:33 +01:00
}
private async fetchAuthorityPolicyDocument ( ) : Promise < unknown > {
2026-06-27 20:14:13 +01:00
return this . fetchPublicationDocument ( AetheriaRtsSchemas . verseAuthorityPolicy ) ;
2026-06-25 18:09:33 +01:00
}
private async fetchStarbridgeSessionSummaryDocument ( ) : Promise < unknown > {
2026-06-27 20:14:13 +01:00
return this . fetchPublicationDocument ( AetheriaRtsSchemas . starbridgeSessionSummary ) ;
}
2026-06-28 01:18:21 +01:00
private async fetchAssetManifestDocument ( ) : Promise < unknown > {
return this . fetchPublicationDocument ( AetheriaRtsSchemas . assetManifest ) ;
}
2026-06-27 20:14:13 +01:00
2026-07-06 03:21:20 +01:00
private async fetchViewportDocument (
schemaId : string ,
recordPrefix : string ,
request : ViewportRequest ,
) : Promise < unknown > {
const recordKey = managedViewportRecordKey ( recordPrefix , request ) ;
const document = CultMesh . documentFromPublication (
{
kind : "peer-snapshot" ,
peer : ( ) = > this . peer ( ) ,
endpoint : this.resolvedRudpEndpoint ( ) ,
} ,
schemaId ,
recordKey ,
{
documentId : recordKey ,
routeHint : this.queryVerse.context.routeHint ,
sourceId : recordKey ,
timeoutMs : 1500 ,
pollMs : 50 ,
messageIdPrefix : ` ${ this . runtimeId } :viewport ` ,
} ,
) ;
return retryTransientPublicationRead ( ( ) = > document . latest ( this . queryContext ( ) ) ) ;
}
2026-07-06 03:32:45 +01:00
private async fetchIndexedDocument (
schemaId : string ,
recordPrefix : string ,
entityIndex : number ,
) : Promise < unknown > {
const recordKey = ` ${ recordPrefix } . ${ Math . trunc ( entityIndex ) } ` ;
const document = CultMesh . documentFromPublication (
{
kind : "peer-snapshot" ,
peer : ( ) = > this . peer ( ) ,
endpoint : this.resolvedRudpEndpoint ( ) ,
} ,
schemaId ,
recordKey ,
{
documentId : recordKey ,
routeHint : this.queryVerse.context.routeHint ,
sourceId : recordKey ,
timeoutMs : 1500 ,
pollMs : 50 ,
messageIdPrefix : ` ${ this . runtimeId } :indexed-document ` ,
} ,
) ;
return retryTransientPublicationRead ( ( ) = > document . latest ( this . queryContext ( ) ) ) ;
}
2026-06-27 20:14:13 +01:00
private fetchPublicationDocument ( schemaId : string ) : Promise < unknown > {
2026-07-05 13:48:28 +01:00
return retryTransientPublicationRead ( ( ) = > this . publications . latest ( { schemaId } , this . queryContext ( ) ) ) ;
2026-06-27 20:14:13 +01:00
}
private createPublicationSource (
mode : "local" | "remote" ,
) : ( binding : CultMeshPublicationDocumentBinding ) = > CultMeshDocumentPublicationSource {
if ( mode === "remote" ) {
return ( ) = > ( {
kind : "peer-snapshot" ,
peer : ( ) = > this . peer ( ) ,
2026-07-04 22:46:04 +01:00
endpoint : this.resolvedRudpEndpoint ( ) ,
2026-06-27 20:14:13 +01:00
} ) ;
}
return binding = > ( {
kind : "single-file" ,
path : ( binding as AetheriaPublicationDocumentSpec ) . localPath ,
} ) ;
2026-06-25 18:09:33 +01:00
}
private createViewportFeed() {
return CultMesh . liveFeed < AetheriaRuntimeViewportFeedRequest , AetheriaRuntimeViewportFeedSnapshot > (
2026-07-05 22:14:58 +01:00
"gamecult.aetheria.viewport_feed.v1" ,
2026-06-25 18:09:33 +01:00
async ( request , context ) = > {
const objects = await this . queries . objectsViewport . execute ( request . viewport , context ) ;
return this . createViewportFeedSnapshot ( request , objects ) ;
} ,
{
sources : [
. . . this . queries . objectsViewport . sources ,
. . . this . queries . gravityViewport . sources ,
. . . this . queries . daemonHealth . sources ,
. . . this . queries . authorityStatus . sources ,
. . . this . queries . starbridgeSession . sources ,
2026-06-28 01:18:21 +01:00
. . . this . queries . assetManifest . sources ,
2026-06-25 18:09:33 +01:00
] ,
routeHint : this.queryVerse.context.routeHint ,
watchFeed : ( request , context , callback ) = > {
let disposed = false ;
let sampling = false ;
const unsubscribe = this . queries . objectsViewport . watch ( request . viewport , context , objects = > {
if ( disposed || sampling ) {
return ;
}
sampling = true ;
void this . createViewportFeedSnapshot ( request , objects )
. then ( snapshot = > {
if ( ! disposed ) {
callback ( snapshot ) ;
}
} )
. finally ( ( ) = > {
sampling = false ;
} ) ;
} ) ;
return ( ) = > {
disposed = true ;
unsubscribe ( ) ;
} ;
} ,
} ,
) ;
}
private async createViewportFeedSnapshot (
request : AetheriaRuntimeViewportFeedRequest ,
objects : ObjectsViewportResponse ,
) : Promise < AetheriaRuntimeViewportFeedSnapshot > {
const startedAt = performance . now ( ) ;
const selectedEntityIndex = request . selectedEntityIndex ? ? - 1 ;
const [
gravity ,
daemonHealth ,
authorityStatus ,
starbridgeSession ,
2026-06-28 01:18:21 +01:00
assetManifest ,
2026-06-25 18:09:33 +01:00
selectedObject ,
inventory ,
] = await Promise . all ( [
2026-07-05 15:12:29 +01:00
this . queryExecutors . gravityViewport ( request . viewport ) ,
this . queryExecutors . daemonHealth ( ) ,
this . queryExecutors . authorityStatus ( ) ,
this . queryExecutors . starbridgeSession ( ) ,
this . queryExecutors . assetManifest ( ) ,
2026-06-25 18:09:33 +01:00
selectedEntityIndex >= 0
2026-07-05 15:12:29 +01:00
? this . queryExecutors . selectedObject ( { entityIndex : selectedEntityIndex } )
2026-06-25 18:09:33 +01:00
: Promise . resolve ( null ) ,
selectedEntityIndex >= 0
2026-07-05 15:12:29 +01:00
? this . queryExecutors . inventory ( { entityIndex : selectedEntityIndex } )
2026-06-25 18:09:33 +01:00
: Promise . resolve ( null ) ,
] ) ;
return {
viewport : composeViewport ( objects , gravity ) ,
selectedObject ,
inventory ,
daemonHealth ,
authorityStatus ,
starbridgeSession ,
2026-06-28 01:18:21 +01:00
assetManifest ,
2026-06-25 18:09:33 +01:00
receivedAtUtc : new Date ( ) . toISOString ( ) ,
sampleMs : performance.now ( ) - startedAt ,
} ;
}
private queryContext ( ) : CultMeshQueryContext {
return this . queryVerse . queryContext ( ) ;
}
private async sendCommandDocument (
commandId : string ,
issuedAtUtc : string ,
command : unknown [ ] ,
context : CultMeshOperationContext ,
) : Promise < void > {
const message : CultNetDocumentPutRawMessage = {
schemaVersion : "cultnet.document_put_raw.v0" ,
messageId : commandId ,
document : {
schemaId : AetheriaRtsSchemas.daemonCommand ,
recordKey : ` daemon:commands: ${ stableToken ( commandId ) } : ${ AetheriaRtsSchemas . daemonCommand } ` ,
storedAt : issuedAtUtc ,
payloadEncoding : "messagepack" ,
payload : encode ( command ) ,
sourceRuntimeId : context.runtimeId ,
2026-07-05 21:43:00 +01:00
sourceRole : "aetheria-client" ,
tags : [ "aetheria" ] ,
2026-06-25 18:09:33 +01:00
} ,
} ;
const peer = await this . peer ( ) ;
peer . send ( message ) ;
await delay ( 80 ) ;
}
private async peer ( ) : Promise < CultNetPeer > {
if ( this . # peer )
return this . # peer ;
2026-07-04 22:46:04 +01:00
const peers = CultMesh . createPeerCatalog ( ) ;
const leases = CultMesh . createAuthorityLeaseCatalog ( ) ;
const leaseId = ` ${ this . daemonTarget . peerId } :authority ` ;
peers . upsert ( {
peerId : this.daemonTarget.peerId ,
verseId : this.daemonTarget.verseId ,
endpoints : this.daemonTarget.endpoints ,
roles : [ this . daemonTarget . role ] ,
authorityLeaseId : leaseId ,
} ) ;
leases . upsert ( {
leaseId ,
verseId : this.daemonTarget.verseId ,
peerId : this.daemonTarget.peerId ,
roles : [ this . daemonTarget . role ] ,
validFrom : new Date ( Date . now ( ) - 60 _000 ) ,
expiresAt : new Date ( Date . now ( ) + 60 _000 ) ,
} ) ;
this . # peer = await CultMesh . createRudpPeerForAuthorizedPeer (
this . runtimeId ,
connectionId ,
peers ,
leases ,
this . daemonTarget . verseId ,
this . daemonTarget . role ,
{
2026-06-25 18:09:33 +01:00
connectTimeoutMs : 2000 ,
maxFragmentBytes : 1200 ,
maxPendingReliablePackets : 512 ,
2026-07-04 22:46:04 +01:00
} ,
) ;
2026-06-25 18:09:33 +01:00
this . # peer . on ( "close" , ( ) = > {
this . # peer = null ;
} ) ;
return this . # peer ;
}
2026-07-04 22:46:04 +01:00
private resolvedRudpEndpoint ( ) : string {
const endpoint = this . daemonTarget . endpoints . find ( value = > value . toLowerCase ( ) . startsWith ( "rudp://" ) ) ;
if ( ! endpoint ) {
throw new Error ( ` Daemon ${ this . daemonTarget . uri } has no resolved RUDP transport endpoint. Resolve it through Odin/CultMesh before opening a transport peer. ` ) ;
}
return endpoint ;
}
}
function normalizeDaemonTarget ( target : string | AetheriaCultMeshDaemonTarget ) : Required < AetheriaCultMeshDaemonTarget > {
const value = typeof target === "string"
? { uri : target }
: target ;
if ( ! value . uri . trim ( ) ) {
throw new Error ( "Aetheria CultMesh daemon target URI is required." ) ;
}
if ( value . uri . toLowerCase ( ) . startsWith ( "rudp://" ) ) {
throw new Error ( "Aetheria daemon targets must be CultMesh URIs; raw RUDP endpoints belong in resolved peer-card endpoints." ) ;
}
return {
uri : value.uri ,
2026-07-05 21:43:00 +01:00
peerId : value.peerId?.trim ( ) || "aetheria-daemon" ,
2026-07-04 22:46:04 +01:00
verseId : value.verseId?.trim ( ) || "aetheria.local" ,
2026-07-05 21:43:00 +01:00
role : value.role?.trim ( ) || "aetheria-daemon" ,
2026-07-04 22:46:04 +01:00
endpoints : value.endpoints ? ? [ ] ,
} ;
2026-06-25 18:09:33 +01:00
}
2026-07-06 02:56:48 +01:00
function normalizeCultMeshAssetUri ( uri : string ) : string {
const value = ( uri ? ? "" ) . trim ( ) ;
if ( ! value . toLowerCase ( ) . startsWith ( "cultmesh://" ) ) {
throw new Error ( ` Aetheria asset URI must be CultMesh-native: ${ value } ` ) ;
}
return value ;
}
2026-07-06 03:21:20 +01:00
function managedViewportRecordKey ( prefix : string , request : ViewportRequest ) : string {
const minX = Math . min ( finiteNumber ( request . minX ) , finiteNumber ( request . maxX ) ) ;
const minY = Math . min ( finiteNumber ( request . minY ) , finiteNumber ( request . maxY ) ) ;
const maxX = Math . max ( finiteNumber ( request . minX ) , finiteNumber ( request . maxX ) ) ;
const maxY = Math . max ( finiteNumber ( request . minY ) , finiteNumber ( request . maxY ) ) ;
return ` ${ prefix } . ${ viewportToken ( minX ) } . ${ viewportToken ( minY ) } . ${ viewportToken ( maxX ) } . ${ viewportToken ( maxY ) } ` ;
}
function viewportToken ( value : number ) : string {
const rounded = Math . round ( value * 1000 ) / 1000 ;
return rounded
. toString ( )
. replace ( "-" , "n" )
. replace ( "." , "p" ) ;
}
function finiteNumber ( value : unknown ) : number {
return typeof value === "number" && Number . isFinite ( value ) ? value : 0 ;
}
2026-07-06 02:56:48 +01:00
function normalizeAssetBlob ( value : unknown ) : Uint8Array {
if ( value instanceof Uint8Array )
return value ;
if ( Array . isArray ( value ) )
return Uint8Array . from ( value . map ( entry = > typeof entry === "number" ? entry : 0 ) ) ;
throw new Error ( "Aetheria CultMesh CDN asset blob did not decode to bytes." ) ;
}
function resolveAssetMimeType ( recordKey : string , manifest : AssetManifestDocument | null ) : string {
const entry = manifest ? . assets . find ( candidate = > candidate . ref . uri === recordKey ) ;
return entry ? . ref . mimeType ? . trim ( ) || mimeTypeFromUri ( recordKey ) ;
}
function mimeTypeFromUri ( uri : string ) : string {
const normalized = uri . toLowerCase ( ) ;
if ( normalized . endsWith ( ".jpg" ) || normalized . endsWith ( ".jpeg" ) )
return "image/jpeg" ;
if ( normalized . endsWith ( ".svg" ) )
return "image/svg+xml" ;
if ( normalized . endsWith ( ".png" ) || normalized . startsWith ( "cultmesh://" ) )
return "image/png" ;
return "application/octet-stream" ;
}
2026-07-05 13:48:28 +01:00
async function retryTransientPublicationRead < T > ( read : ( ) = > Promise < T > ) : Promise < T > {
let lastError : unknown ;
2026-07-05 15:12:29 +01:00
for ( let attempt = 0 ; attempt < 40 ; attempt += 1 ) {
2026-07-05 13:48:28 +01:00
try {
return await read ( ) ;
} catch ( error ) {
lastError = error ;
if ( ! isTransientPublicationReadError ( error ) )
throw error ;
2026-07-05 15:12:29 +01:00
await delay ( 25 + attempt * 8 ) ;
2026-07-05 13:48:28 +01:00
}
}
throw lastError ;
}
function isTransientPublicationReadError ( error : unknown ) : boolean {
const message = error instanceof Error ? error.message : String ( error ) ;
2026-07-05 15:12:29 +01:00
return message . includes ( "EBUSY" ) ||
message . includes ( "EPERM" ) ||
message . includes ( "ENOENT" ) ||
message . includes ( "did not contain schema" ) ;
2026-07-05 13:48:28 +01:00
}
2026-06-25 18:09:33 +01:00
function stableToken ( value : string ) : string {
return value
. replace ( / [ ^ a - z A - Z 0 - 9 ] + / g u , " - " )
. replace ( / ^ - + | - + $ / g u , " " )
. replace ( / - - + / g u , " - " )
. toLowerCase ( ) || "empty" ;
}
function composeViewport (
objects : ObjectsViewportResponse ,
gravity : GravityViewportResponse ,
) : ViewportResponse {
return {
2026-07-05 19:56:18 +01:00
schema : "gamecult.aetheria.game_viewport.v1" ,
2026-06-25 18:09:33 +01:00
frameId : objects.frameId ,
publishedAtUtc : objects.publishedAtUtc ,
simulationTimeSeconds : objects.simulationTimeSeconds ,
runId : objects.runId ,
zoneIndex : objects.zoneIndex ,
zoneName : objects.zoneName ,
currentEntityKey : objects.currentEntityKey ,
viewport : objects.viewport ,
controlledEntityIndices : objects.controlledEntityIndices ,
objects : objects.objects ,
gravityInfluences : gravity.gravityInfluences ,
bodies : gravity.bodies ,
} ;
}
2026-06-27 20:14:13 +01:00
function createAetheriaPublicationDocuments (
statePath : string ,
mode : "local" | "remote" ,
) : readonly AetheriaPublicationDocumentSpec [ ] {
const documents : readonly AetheriaPublicationDocumentSpec [ ] = [
{
. . . CultMesh . publicationDocument (
AetheriaRtsSchemas . daemonFrame ,
"daemon:aetheria.frame.latest.v1" ,
{
documentId : "daemon:aetheria.frame.latest.v1" ,
sourceId : "daemon:aetheria.frame.latest.v1" ,
} ,
) ,
2026-06-30 19:14:49 +01:00
localPath : statePath ,
2026-06-27 20:14:13 +01:00
} ,
{
. . . CultMesh . publicationDocument (
AetheriaRtsSchemas . daemonHealth ,
"daemon:aetheria.health.latest.v1" ,
{
documentId : "daemon:aetheria.health.latest.v1" ,
sourceId : "daemon:aetheria.health.latest.v1" ,
} ,
) ,
2026-06-30 19:14:49 +01:00
localPath : statePath ,
2026-06-27 20:14:13 +01:00
remoteRecordKey : "daemon:aetheria.health.v1" ,
} ,
{
. . . CultMesh . publicationDocument (
AetheriaRtsSchemas . verseAuthorityPolicy ,
"daemon:aetheria.authority.policy.latest.v1" ,
{
documentId : "daemon:aetheria.authority.policy.latest.v1" ,
sourceId : "daemon:aetheria.authority.policy.latest.v1" ,
} ,
) ,
2026-06-30 19:14:49 +01:00
localPath : statePath ,
2026-06-27 20:14:13 +01:00
remoteRecordKey : "global:aetheria.verse_authority_policy.v1" ,
} ,
{
. . . CultMesh . publicationDocument (
AetheriaRtsSchemas . starbridgeSessionSummary ,
"daemon:aetheria.starbridge.session.latest.v1" ,
{
documentId : "daemon:aetheria.starbridge.session.latest.v1" ,
sourceId : "daemon:aetheria.starbridge.session.latest.v1" ,
} ,
) ,
2026-06-30 19:14:49 +01:00
localPath : statePath ,
2026-06-27 20:14:13 +01:00
} ,
2026-06-28 01:18:21 +01:00
{
. . . CultMesh . publicationDocument (
AetheriaRtsSchemas . assetManifest ,
"daemon:aetheria.asset_manifest.latest.v1" ,
{
documentId : "daemon:aetheria.asset_manifest.latest.v1" ,
sourceId : "daemon:aetheria.asset_manifest.latest.v1" ,
} ,
) ,
2026-06-30 19:14:49 +01:00
localPath : statePath ,
2026-06-28 01:18:21 +01:00
} ,
2026-06-27 20:14:13 +01:00
] ;
return documents . map ( document = > mode === "remote" && document . remoteRecordKey
? {
. . . document ,
recordKey : document.remoteRecordKey ,
}
: document ) ;
}
2026-07-05 00:32:49 +01:00
function readField ( value : unknown , property : string , index : number ) : unknown {
if ( Array . isArray ( value ) )
return value [ index ] ;
if ( value && typeof value === "object" ) {
const record = value as Record < string , unknown > ;
if ( property in record )
return record [ property ] ;
const pascal = property . charAt ( 0 ) . toUpperCase ( ) + property . slice ( 1 ) ;
if ( pascal in record )
return record [ pascal ] ;
}
return undefined ;
}
function arrayValue ( value : unknown ) : unknown [ ] {
return Array . isArray ( value ) ? value : [ ] ;
}
function normalizeCommandPayload ( payload : Record < string , unknown > | undefined ) : Record < string , string > {
const result : Record < string , string > = { } ;
for ( const [ key , value ] of Object . entries ( payload ? ? { } ) ) {
if ( value == null )
continue ;
result [ key ] = typeof value === "string" ? value : String ( value ) ;
}
return result ;
}
function objectValue ( value : unknown ) : Record < string , unknown > {
return value && typeof value === "object" && ! Array . isArray ( value )
? value as Record < string , unknown >
: { } ;
}
function stringOr ( value : unknown , fallback : string ) : string {
return typeof value === "string" ? value : fallback ;
}
function numberOr ( value : unknown , fallback : number ) : number {
return typeof value === "number" && Number . isFinite ( value ) ? value : fallback ;
}
function stringRecord ( value : unknown ) : Record < string , string > {
const source = objectValue ( value ) ;
const result : Record < string , string > = { } ;
for ( const [ key , entry ] of Object . entries ( source ) ) {
if ( entry == null )
continue ;
result [ key ] = typeof entry === "string" ? entry : String ( entry ) ;
}
return result ;
}
2026-06-25 18:09:33 +01:00
function delay ( milliseconds : number ) : Promise < void > {
return new Promise ( resolve = > setTimeout ( resolve , milliseconds ) ) ;
}