Fetch Electron indexed documents from daemon
This commit is contained in:
parent
d91e87b6d6
commit
6f91e749cd
4 changed files with 169 additions and 136 deletions
|
|
@ -52,11 +52,11 @@ import {
|
|||
readAuthorityStatusDocument,
|
||||
readAssetManifestDocument,
|
||||
readDaemonHealthDocument,
|
||||
buildInventoryDocumentFromFrame,
|
||||
readGravityViewportDocument,
|
||||
readInventoryDocument,
|
||||
readObjectsViewportDocument,
|
||||
readRenderSplatsViewportDocument,
|
||||
buildSelectedObjectDocumentFromFrame,
|
||||
readSelectedObjectDocument,
|
||||
readStarbridgeSessionSummaryDocument,
|
||||
readViewportDocument,
|
||||
} from "./aetheria-rts-local-documents.js";
|
||||
|
|
@ -216,8 +216,10 @@ export class AetheriaCultMeshClient {
|
|||
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)),
|
||||
selectedObject: async (request: SelectedObjectRequest) => buildSelectedObjectDocumentFromFrame(await this.fetchLatestFrameDocument(), request),
|
||||
inventory: async (request: SelectedObjectRequest) => buildInventoryDocumentFromFrame(await this.fetchLatestFrameDocument(), request),
|
||||
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)),
|
||||
daemonHealth: async () => readDaemonHealthDocument(await this.fetchDaemonHealthDocument()),
|
||||
authorityStatus: async () => readAuthorityStatusDocument(await this.fetchAuthorityPolicyDocument()),
|
||||
starbridgeSession: async () => readStarbridgeSessionSummaryDocument(await this.fetchStarbridgeSessionSummaryDocument()),
|
||||
|
|
@ -512,6 +514,33 @@ export class AetheriaCultMeshClient {
|
|||
return retryTransientPublicationRead(() => document.latest(this.queryContext()));
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
private fetchPublicationDocument(schemaId: string): Promise<unknown> {
|
||||
return retryTransientPublicationRead(() => this.publications.latest({ schemaId }, this.queryContext()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,17 +4,12 @@ import {
|
|||
aetheriaRuntimeAssetManifestEntrySlots as assetManifestEntrySlots,
|
||||
aetheriaRuntimeAssetRefSlots as assetRefSlots,
|
||||
aetheriaRuntimeAuthorityRuleSlots as authorityRuleSlots,
|
||||
aetheriaRuntimeCargoBayLoadoutCommitSlots as cargoBaySlots,
|
||||
aetheriaRuntimeDaemonFrameDocumentSlots as frameSlots,
|
||||
aetheriaRuntimeDaemonHealthDocumentSlots as healthSlots,
|
||||
aetheriaRuntimeEntitySnapshotCommitSlots as entitySlots,
|
||||
aetheriaRuntimeEntityStatGridCommitSlots as statGridSlots,
|
||||
aetheriaRuntimeGameViewportBoundsSlots as viewportBoundsSlots,
|
||||
aetheriaRuntimeGameViewportDocumentSlots as gameViewportSlots,
|
||||
aetheriaRuntimeGameViewportObjectSlots as viewportObjectSlots,
|
||||
aetheriaRuntimeGravityViewportDocumentSlots as gravityViewportSlots,
|
||||
aetheriaRuntimeLoadoutItemCommitSlots as itemSlots,
|
||||
aetheriaRuntimeLoadoutItemSlotCommitSlots as itemSlotSlots,
|
||||
aetheriaRuntimeInventoryDocumentSlots as inventoryDocumentSlots,
|
||||
aetheriaRuntimeObjectsViewportDocumentSlots as objectsViewportSlots,
|
||||
aetheriaRuntimeRenderSplatLayerDefinitionSlots as renderSplatLayerSlots,
|
||||
aetheriaRuntimeRenderSplatsViewportDocumentSlots as renderSplatsViewportSlots,
|
||||
|
|
@ -23,14 +18,13 @@ import {
|
|||
aetheriaRuntimeRtsEntityStatusSlots as viewportStatusSlots,
|
||||
aetheriaRuntimeRtsGravityInfluenceSlots as gravityInfluenceSlots,
|
||||
aetheriaRuntimeRtsInventoryItemSlots as viewportInventoryItemSlots,
|
||||
aetheriaRuntimeRunCheckpointCommitSlots as runSlots,
|
||||
aetheriaRuntimeSelectedObjectDocumentSlots as selectedObjectDocumentSlots,
|
||||
aetheriaRuntimeStarbridgeBaseStatusSlots as starbridgeBaseSlots,
|
||||
aetheriaRuntimeStarbridgeRuntimeRoleSlots as starbridgeRoleSlots,
|
||||
aetheriaRuntimeStarbridgeSessionSummaryDocumentSlots as starbridgeSummarySlots,
|
||||
aetheriaRuntimeStarbridgeStationStockItemSlots as starbridgeStockSlots,
|
||||
aetheriaRuntimeStarbridgeWaveForecastSlots as starbridgeWaveForecastSlots,
|
||||
aetheriaRuntimeVerseAuthorityPolicyDocumentSlots as authorityPolicySlots,
|
||||
aetheriaRuntimeZoneSnapshotCommitSlots as zoneSlots,
|
||||
} from "./aetheria-rts-generated-bindings.js";
|
||||
import { cultMeshRectFromBounds, cultMeshViewportRequest } from "cultmesh-ts";
|
||||
import type {
|
||||
|
|
@ -47,7 +41,6 @@ import type {
|
|||
ObjectsViewportResponse,
|
||||
RenderSplatsViewportResponse,
|
||||
SelectedObjectDocument,
|
||||
SelectedObjectRequest,
|
||||
StarbridgeSessionDocument,
|
||||
ViewObject,
|
||||
ViewportRequest,
|
||||
|
|
@ -56,36 +49,30 @@ import type {
|
|||
|
||||
const missingDaemonRunId = "aetheria.run.unknown";
|
||||
|
||||
export function buildSelectedObjectDocumentFromFrame(
|
||||
frameDocument: unknown,
|
||||
request: SelectedObjectRequest,
|
||||
): SelectedObjectDocument {
|
||||
const context = frameContext(frameDocument);
|
||||
const entity = context.entities.find(candidate => num(candidate[entitySlots.entityIndex], -1) === request.entityIndex);
|
||||
export function readSelectedObjectDocument(selectedObjectDocument: unknown): SelectedObjectDocument {
|
||||
const document = arr(selectedObjectDocument);
|
||||
return {
|
||||
schema: AetheriaRtsSchemas.selectedObject,
|
||||
frameId: context.frameId,
|
||||
runId: context.runId,
|
||||
zoneIndex: context.zoneIndex,
|
||||
entityIndex: request.entityIndex,
|
||||
selected: entity ? toViewObject(entity, context.runId, context.zoneIndex) : null,
|
||||
schema: str(document[selectedObjectDocumentSlots.schema]) || AetheriaRtsSchemas.selectedObject,
|
||||
frameId: num(document[selectedObjectDocumentSlots.frameId]),
|
||||
runId: str(document[selectedObjectDocumentSlots.runId]) || missingDaemonRunId,
|
||||
zoneIndex: num(document[selectedObjectDocumentSlots.zoneIndex]),
|
||||
entityIndex: num(document[selectedObjectDocumentSlots.entityIndex], -1),
|
||||
selected: readNullableViewportObject(document[selectedObjectDocumentSlots.selected]),
|
||||
};
|
||||
}
|
||||
|
||||
export function buildInventoryDocumentFromFrame(frameDocument: unknown, request: SelectedObjectRequest): InventoryDocument {
|
||||
const context = frameContext(frameDocument);
|
||||
const entity = context.entities.find(candidate => num(candidate[entitySlots.entityIndex], -1) === request.entityIndex);
|
||||
const allItems = entity ? inventory(entity) : [];
|
||||
export function readInventoryDocument(inventoryDocument: unknown): InventoryDocument {
|
||||
const document = arr(inventoryDocument);
|
||||
return {
|
||||
schema: AetheriaRtsSchemas.inventory,
|
||||
frameId: context.frameId,
|
||||
runId: context.runId,
|
||||
zoneIndex: context.zoneIndex,
|
||||
entityIndex: request.entityIndex,
|
||||
entityKey: entity ? entityKey(context.runId, context.zoneIndex, request.entityIndex) : "",
|
||||
items: allItems,
|
||||
equipment: allItems.filter(item => item.source === "equipment"),
|
||||
cargo: allItems.filter(item => item.source === "cargo"),
|
||||
schema: str(document[inventoryDocumentSlots.schema]) || AetheriaRtsSchemas.inventory,
|
||||
frameId: num(document[inventoryDocumentSlots.frameId]),
|
||||
runId: str(document[inventoryDocumentSlots.runId]) || missingDaemonRunId,
|
||||
zoneIndex: num(document[inventoryDocumentSlots.zoneIndex]),
|
||||
entityIndex: num(document[inventoryDocumentSlots.entityIndex], -1),
|
||||
entityKey: str(document[inventoryDocumentSlots.entityKey]),
|
||||
items: list<unknown[]>(document[inventoryDocumentSlots.items]).map(readViewportInventoryItem),
|
||||
equipment: list<unknown[]>(document[inventoryDocumentSlots.equipment]).map(readViewportInventoryItem),
|
||||
cargo: list<unknown[]>(document[inventoryDocumentSlots.cargo]).map(readViewportInventoryItem),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -233,27 +220,6 @@ export function readAssetManifestDocument(assetManifestDocument: unknown): Asset
|
|||
};
|
||||
}
|
||||
|
||||
function frameContext(frameDocument: unknown): {
|
||||
frameId: number;
|
||||
runId: string;
|
||||
zoneIndex: number;
|
||||
entities: unknown[][];
|
||||
} {
|
||||
const frame = arr(frameDocument);
|
||||
const run = arr(frame[frameSlots.run]);
|
||||
const zones = list<unknown[]>(run[runSlots.zones]);
|
||||
const currentZoneIndex = num(run[runSlots.currentZoneIndex], -1);
|
||||
const zone = zones.find(candidate => num(candidate[zoneSlots.zoneIndex], -1) === currentZoneIndex) ??
|
||||
zones[0] ??
|
||||
[];
|
||||
return {
|
||||
frameId: num(frame[frameSlots.frameId]),
|
||||
runId: str(run[runSlots.runId]) || missingDaemonRunId,
|
||||
zoneIndex: num(zone[zoneSlots.zoneIndex]),
|
||||
entities: list<unknown[]>(zone[zoneSlots.entities]),
|
||||
};
|
||||
}
|
||||
|
||||
function readViewportBounds(value: unknown): ViewportRequest {
|
||||
const bounds = arr(value);
|
||||
return cultMeshViewportRequest(
|
||||
|
|
@ -271,6 +237,10 @@ function readViewportObjects(objects: unknown[][]): ViewObject[] {
|
|||
return objects.map(readViewportObject);
|
||||
}
|
||||
|
||||
function readNullableViewportObject(value: unknown): ViewObject | null {
|
||||
return Array.isArray(value) ? readViewportObject(value) : null;
|
||||
}
|
||||
|
||||
function readViewportObject(object: unknown[]): ViewObject {
|
||||
return {
|
||||
entityIndex: num(object[viewportObjectSlots.entityIndex], -1),
|
||||
|
|
@ -395,36 +365,6 @@ function readRenderSplatSoa(value: unknown): RenderSplatsViewportResponse["splat
|
|||
};
|
||||
}
|
||||
|
||||
function toViewObject(entity: unknown[], runId: string, zoneIndex: number): ViewObject {
|
||||
const kind = str(entity[entitySlots.kind]);
|
||||
const controlled = isPlayerControlled(entity);
|
||||
return {
|
||||
entityIndex: num(entity[entitySlots.entityIndex], -1),
|
||||
entityKey: entityKey(runId, zoneIndex, num(entity[entitySlots.entityIndex], -1)),
|
||||
displayName: str(entity[entitySlots.name]),
|
||||
kind,
|
||||
factionKey: str(entity[entitySlots.factionKey]),
|
||||
x: num(entity[entitySlots.positionX]),
|
||||
y: num(entity[entitySlots.positionZ]),
|
||||
z: num(entity[entitySlots.positionY]),
|
||||
directionX: num(entity[entitySlots.directionX]),
|
||||
directionY: num(entity[entitySlots.directionY]),
|
||||
velocityX: num(entity[entitySlots.velocityX]),
|
||||
velocityY: num(entity[entitySlots.velocityY]),
|
||||
controlled,
|
||||
targetEntityIndex: num(entity[entitySlots.targetEntityIndex], -1),
|
||||
isActive: bool(entity[entitySlots.isActive]),
|
||||
visibility: num(entity[entitySlots.visibility]),
|
||||
iconAsset: entityIconAsset(kind, controlled),
|
||||
status: {
|
||||
hull: stat(entity, "hull"),
|
||||
shield: stat(entity, "shield"),
|
||||
heat: stat(entity, "heat"),
|
||||
},
|
||||
inventory: inventory(entity),
|
||||
};
|
||||
}
|
||||
|
||||
function toStarbridgeBaseStatus(status: unknown[]): StarbridgeSessionDocument["baseStatus"] {
|
||||
return {
|
||||
entityKey: str(status[starbridgeBaseSlots.entityKey]),
|
||||
|
|
@ -466,46 +406,6 @@ function toStarbridgeRuntimeRole(role: unknown[]): StarbridgeSessionDocument["ru
|
|||
};
|
||||
}
|
||||
|
||||
function inventory(entity: unknown[]): InventoryItem[] {
|
||||
const items: InventoryItem[] = [];
|
||||
for (const slot of list<unknown[]>(entity[entitySlots.equipment]))
|
||||
addSlot(items, "equipment", slot);
|
||||
for (const bay of list<unknown[]>(entity[entitySlots.cargoContents])) {
|
||||
for (const slot of list<unknown[]>(bay[cargoBaySlots.items]))
|
||||
addSlot(items, "cargo", slot);
|
||||
}
|
||||
|
||||
return items.filter(item => item.itemKey.length > 0);
|
||||
}
|
||||
|
||||
function addSlot(items: InventoryItem[], source: string, slot: unknown[]): void {
|
||||
const item = arr(slot[itemSlotSlots.item]);
|
||||
const itemKey = str(item[itemSlots.itemKey]);
|
||||
items.push({
|
||||
source,
|
||||
itemKey,
|
||||
quantity: num(item[itemSlots.quantity]),
|
||||
quality: num(item[itemSlots.quality]),
|
||||
durability: num(item[itemSlots.durability]),
|
||||
enabled: bool(item[itemSlots.enabled]),
|
||||
iconAsset: itemIconAsset(itemKey),
|
||||
});
|
||||
}
|
||||
|
||||
function isPlayerControlled(entity: unknown[]): boolean {
|
||||
return str(entity[entitySlots.factionKey]).toLowerCase() === "player";
|
||||
}
|
||||
|
||||
function stat(entity: unknown[], name: string): number {
|
||||
const grid = list<unknown[]>(entity[entitySlots.statGrids])
|
||||
.find(candidate => str(candidate[statGridSlots.name]).toLowerCase() === name.toLowerCase());
|
||||
return grid ? numberList(grid[statGridSlots.values])[0] ?? 0 : 0;
|
||||
}
|
||||
|
||||
function entityKey(runId: string, zoneIndex: number, entityIndex: number): string {
|
||||
return `global:aetheria.run_state.${runId}.zone.${zoneIndex}.entity.${entityIndex}.v1`;
|
||||
}
|
||||
|
||||
function toAssetManifestEntry(entry: unknown[]): AssetManifestDocument["assets"][number] {
|
||||
return {
|
||||
ref: assetRef(arr(entry[assetManifestEntrySlots.ref])),
|
||||
|
|
|
|||
|
|
@ -619,6 +619,46 @@ static RudpCultNetSchemaServer StartClientCultMeshHost(
|
|||
}
|
||||
}
|
||||
|
||||
if (hasFrame && frame != null && TryGetIndexedGameDocumentRequest(request, out var indexedRecordKey, out var indexedSchemaId, out var indexedEntityIndex))
|
||||
{
|
||||
if (string.Equals(indexedSchemaId, AetheriaRuntimeDaemonSchemas.SelectedObject, StringComparison.Ordinal))
|
||||
{
|
||||
var selectedObjectPut = node.Database.Documents.CreateRawDocumentPutMessage(
|
||||
response.MessageId,
|
||||
new CultRecordHandle<AetheriaRuntimeSelectedObjectDocument>(
|
||||
new CultRecordKey(indexedRecordKey)),
|
||||
AetheriaRuntimeGameDocuments.SelectedObject(frame, indexedEntityIndex),
|
||||
new CultNetDocumentMessageOptions
|
||||
{
|
||||
SourceRuntimeId = options.DaemonId,
|
||||
SourceRole = "aetheria-daemon"
|
||||
});
|
||||
response.Documents = response.Documents
|
||||
.Where(document => !string.Equals(document.SchemaId, selectedObjectPut.Document.SchemaId, StringComparison.Ordinal) ||
|
||||
!string.Equals(document.RecordKey, selectedObjectPut.Document.RecordKey, StringComparison.Ordinal))
|
||||
.Concat(new[] { selectedObjectPut.Document })
|
||||
.ToArray();
|
||||
}
|
||||
else if (string.Equals(indexedSchemaId, AetheriaRuntimeDaemonSchemas.Inventory, StringComparison.Ordinal))
|
||||
{
|
||||
var inventoryPut = node.Database.Documents.CreateRawDocumentPutMessage(
|
||||
response.MessageId,
|
||||
new CultRecordHandle<AetheriaRuntimeInventoryDocument>(
|
||||
new CultRecordKey(indexedRecordKey)),
|
||||
AetheriaRuntimeGameDocuments.Inventory(frame, indexedEntityIndex),
|
||||
new CultNetDocumentMessageOptions
|
||||
{
|
||||
SourceRuntimeId = options.DaemonId,
|
||||
SourceRole = "aetheria-daemon"
|
||||
});
|
||||
response.Documents = response.Documents
|
||||
.Where(document => !string.Equals(document.SchemaId, inventoryPut.Document.SchemaId, StringComparison.Ordinal) ||
|
||||
!string.Equals(document.RecordKey, inventoryPut.Document.RecordKey, StringComparison.Ordinal))
|
||||
.Concat(new[] { inventoryPut.Document })
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
await InjectCultMeshCdnAssetSnapshotsAsync(options, request, response).ConfigureAwait(false);
|
||||
peer.SendCultNet(response);
|
||||
}
|
||||
|
|
@ -1042,6 +1082,57 @@ static bool TryGetManagedViewportRequest(
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool TryGetIndexedGameDocumentRequest(
|
||||
CultNetSnapshotRequestMessage request,
|
||||
out string recordKey,
|
||||
out string schemaId,
|
||||
out int entityIndex)
|
||||
{
|
||||
recordKey = "";
|
||||
schemaId = "";
|
||||
entityIndex = -1;
|
||||
var schemaIds = request.SchemaIds ?? Array.Empty<string>();
|
||||
var allowedSchemas = new[]
|
||||
{
|
||||
AetheriaRuntimeDaemonSchemas.SelectedObject,
|
||||
AetheriaRuntimeDaemonSchemas.Inventory
|
||||
};
|
||||
if (schemaIds.Length > 0 && !schemaIds.Any(candidate => allowedSchemas.Contains(candidate, StringComparer.Ordinal)))
|
||||
return false;
|
||||
|
||||
foreach (var candidate in request.RecordKeys ?? Array.Empty<string>())
|
||||
{
|
||||
var candidateSchemaId = "";
|
||||
var prefix = "";
|
||||
if (candidate.StartsWith("aetheria.object.selected.", StringComparison.Ordinal))
|
||||
{
|
||||
prefix = "aetheria.object.selected.";
|
||||
candidateSchemaId = AetheriaRuntimeDaemonSchemas.SelectedObject;
|
||||
}
|
||||
else if (candidate.StartsWith("aetheria.inventory.", StringComparison.Ordinal))
|
||||
{
|
||||
prefix = "aetheria.inventory.";
|
||||
candidateSchemaId = AetheriaRuntimeDaemonSchemas.Inventory;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (schemaIds.Length > 0 && !schemaIds.Contains(candidateSchemaId, StringComparer.Ordinal))
|
||||
continue;
|
||||
if (!int.TryParse(candidate.Substring(prefix.Length), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedEntityIndex))
|
||||
continue;
|
||||
|
||||
recordKey = candidate;
|
||||
schemaId = candidateSchemaId;
|
||||
entityIndex = parsedEntityIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool TryParseViewportToken(string token, out double value)
|
||||
{
|
||||
return double.TryParse(
|
||||
|
|
|
|||
|
|
@ -16592,35 +16592,48 @@ static void RequireUnityDoesNotCallSharedSimulationTicks(string root)
|
|||
if (rtsElectronCultMesh.Contains("buildViewportDocumentFromFrame(await this.fetchLatestFrameDocument()", StringComparison.Ordinal) ||
|
||||
rtsElectronCultMesh.Contains("buildObjectsViewportDocumentFromFrame(await this.fetchLatestFrameDocument()", StringComparison.Ordinal) ||
|
||||
rtsElectronCultMesh.Contains("buildGravityViewportDocumentFromFrame(await this.fetchLatestFrameDocument()", StringComparison.Ordinal) ||
|
||||
rtsElectronCultMesh.Contains("buildRenderSplatsViewportDocumentFromFrame(await this.fetchLatestFrameDocument()", StringComparison.Ordinal))
|
||||
rtsElectronCultMesh.Contains("buildRenderSplatsViewportDocumentFromFrame(await this.fetchLatestFrameDocument()", StringComparison.Ordinal) ||
|
||||
rtsElectronCultMesh.Contains("buildSelectedObjectDocumentFromFrame(await this.fetchLatestFrameDocument()", StringComparison.Ordinal) ||
|
||||
rtsElectronCultMesh.Contains("buildInventoryDocumentFromFrame(await this.fetchLatestFrameDocument()", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Electron viewport queries must fetch daemon-authored managed viewport documents, not rebuild field/view documents from daemonFrame.");
|
||||
"Electron queries must fetch daemon-authored managed documents, not rebuild field/view/selection/inventory documents from daemonFrame.");
|
||||
}
|
||||
if (rtsLocalDocuments.Contains("buildViewportDocumentFromFrame", StringComparison.Ordinal) ||
|
||||
rtsLocalDocuments.Contains("buildObjectsViewportDocumentFromFrame", StringComparison.Ordinal) ||
|
||||
rtsLocalDocuments.Contains("buildGravityViewportDocumentFromFrame", StringComparison.Ordinal) ||
|
||||
rtsLocalDocuments.Contains("buildRenderSplatsViewportDocumentFromFrame", StringComparison.Ordinal) ||
|
||||
rtsLocalDocuments.Contains("buildSelectedObjectDocumentFromFrame", StringComparison.Ordinal) ||
|
||||
rtsLocalDocuments.Contains("buildInventoryDocumentFromFrame", StringComparison.Ordinal) ||
|
||||
rtsLocalDocuments.Contains("frameContext(frameDocument", StringComparison.Ordinal) ||
|
||||
rtsLocalDocuments.Contains("RenderSplatBuilder", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Electron local document decoding must not keep dead viewport projection builders; daemon managed viewport documents own those fields.");
|
||||
"Electron local document decoding must not keep dead viewport, selection, or inventory projection builders; daemon managed documents own those fields.");
|
||||
}
|
||||
if (!rtsElectronCultMesh.Contains("fetchViewportDocument(AetheriaRtsSchemas.gameViewport, \"aetheria.viewport.map\"", StringComparison.Ordinal) ||
|
||||
!rtsElectronCultMesh.Contains("fetchViewportDocument(AetheriaRtsSchemas.objectsViewport, \"aetheria.viewport.objects\"", StringComparison.Ordinal) ||
|
||||
!rtsElectronCultMesh.Contains("fetchViewportDocument(AetheriaRtsSchemas.gravityViewport, \"aetheria.viewport.gravity\"", StringComparison.Ordinal) ||
|
||||
!rtsElectronCultMesh.Contains("fetchViewportDocument(AetheriaRtsSchemas.renderSplatsViewport, \"aetheria.viewport.render_splats\"", StringComparison.Ordinal) ||
|
||||
!rtsElectronCultMesh.Contains("managedViewportRecordKey(", StringComparison.Ordinal) ||
|
||||
!rtsElectronCultMesh.Contains("readRenderSplatsViewportDocument(await this.fetchViewportDocument", StringComparison.Ordinal))
|
||||
!rtsElectronCultMesh.Contains("readRenderSplatsViewportDocument(await this.fetchViewportDocument", StringComparison.Ordinal) ||
|
||||
!rtsElectronCultMesh.Contains("fetchIndexedDocument(AetheriaRtsSchemas.selectedObject, \"aetheria.object.selected\"", StringComparison.Ordinal) ||
|
||||
!rtsElectronCultMesh.Contains("fetchIndexedDocument(AetheriaRtsSchemas.inventory, \"aetheria.inventory\"", StringComparison.Ordinal) ||
|
||||
!rtsElectronCultMesh.Contains("readSelectedObjectDocument(await this.fetchIndexedDocument", StringComparison.Ordinal) ||
|
||||
!rtsElectronCultMesh.Contains("readInventoryDocument(await this.fetchIndexedDocument", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Electron viewport queries no longer use the daemon managed viewport document path.");
|
||||
"Electron viewport, selected-object, and inventory queries no longer use the daemon managed document path.");
|
||||
}
|
||||
if (!daemonProgram.Contains("recordKey.StartsWith(\"aetheria.viewport.map.\"", StringComparison.Ordinal) ||
|
||||
!daemonProgram.Contains("schemaId = AetheriaRuntimeDaemonSchemas.GameViewport", StringComparison.Ordinal))
|
||||
!daemonProgram.Contains("schemaId = AetheriaRuntimeDaemonSchemas.GameViewport", StringComparison.Ordinal) ||
|
||||
!daemonProgram.Contains("candidate.StartsWith(\"aetheria.object.selected.\"", StringComparison.Ordinal) ||
|
||||
!daemonProgram.Contains("candidate.StartsWith(\"aetheria.inventory.\"", StringComparison.Ordinal) ||
|
||||
!daemonProgram.Contains("AetheriaRuntimeGameDocuments.SelectedObject(frame, indexedEntityIndex)", StringComparison.Ordinal) ||
|
||||
!daemonProgram.Contains("AetheriaRuntimeGameDocuments.Inventory(frame, indexedEntityIndex)", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Daemon snapshot handling must expose the managed map viewport document key beside objects/gravity/render-splats.");
|
||||
"Daemon snapshot handling must expose managed viewport and indexed selected-object/inventory document keys.");
|
||||
}
|
||||
|
||||
if (daemonTickRunner.Contains("AetheriaRuntimeDaemonFrameStore.PublishFrame", StringComparison.Ordinal))
|
||||
|
|
|
|||
Loading…
Reference in a new issue