From 2c3f09377a51e4f911e618eed9225f01b188bb4c Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 12 Jul 2026 11:53:28 +0100 Subject: [PATCH] Specify reactive entity SoA world lowering --- docs/world-state-lowering.md | 19 ++++ ...amecult.eve.entity_soa_view.v1.schema.json | 87 +++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 schemas/gamecult.eve.entity_soa_view.v1.schema.json diff --git a/docs/world-state-lowering.md b/docs/world-state-lowering.md index 193dfbf..14b34c2 100644 --- a/docs/world-state-lowering.md +++ b/docs/world-state-lowering.md @@ -76,6 +76,25 @@ World surfaces should be able to describe: The renderer chooses the best native projection it can support. It must not invent provider semantics to compensate for missing contract information. +### Entity SoA Views + +`gamecult.eve.entity_soa_view.v1` is the portable descriptor for hot entity +presentation state. A `world.scene2d` or `world.scene3d` component points to it +with `entityViewPointerId`; `entityViewSchema` names the schema. The surface +does not duplicate entity transforms as retained child components. + +The descriptor carries buffer locations, semantic columns, dirty ranges, and +render groups. CultMesh selects the buffer route: shared memory for co-located +runtimes, a native stream for remote runtimes, or another advertised backend. +Replacing the reactive descriptor publishes a new generation and lowerers apply +only its dirty ranges. A backend location is transport data, not provider +authority. + +Stable composition, commands, and binding declarations may arrive in a +bootstrap snapshot. Live entity generations do not. UI values bind to reactive +typed documents named by state pointers. Versioned asset manifests are +bootstrap state and their content-addressed artifacts are cached. + Provider advertisements attach the reusable boundary to world surfaces through `surfaces[].worldInteraction`. That block names: diff --git a/schemas/gamecult.eve.entity_soa_view.v1.schema.json b/schemas/gamecult.eve.entity_soa_view.v1.schema.json new file mode 100644 index 0000000..91c1b4d --- /dev/null +++ b/schemas/gamecult.eve.entity_soa_view.v1.schema.json @@ -0,0 +1,87 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "gamecult.eve.entity_soa_view.v1", + "title": "Eve Entity SoA View", + "type": "object", + "required": ["schema", "providerId", "viewId", "frameId", "generation", "backend", "synchronizationMode", "buffers", "columns", "dirtyRanges", "renderGroups"], + "properties": { + "schema": { "const": "gamecult.eve.entity_soa_view.v1" }, + "providerId": { "type": "string", "minLength": 1 }, + "viewId": { "type": "string", "minLength": 1 }, + "frameId": { "type": "integer", "minimum": 0 }, + "generation": { "type": "integer", "minimum": 0 }, + "publishedAtUtc": { "type": "string" }, + "backend": { "type": "string", "minLength": 1 }, + "synchronizationMode": { "type": "string", "minLength": 1 }, + "buffers": { "type": "array", "items": { "$ref": "#/$defs/buffer" } }, + "columns": { "type": "array", "items": { "$ref": "#/$defs/column" } }, + "dirtyRanges": { "type": "array", "items": { "$ref": "#/$defs/dirtyRange" } }, + "renderGroups": { "type": "array", "items": { "$ref": "#/$defs/renderGroup" } } + }, + "$defs": { + "buffer": { + "type": "object", + "required": ["bufferId", "backend", "location", "byteOffset", "byteLength", "generation"], + "properties": { + "bufferId": { "type": "string", "minLength": 1 }, + "backend": { "type": "string", "minLength": 1 }, + "location": { "type": "string", "minLength": 1 }, + "byteOffset": { "type": "integer", "minimum": 0 }, + "byteLength": { "type": "integer", "minimum": 0 }, + "generation": { "type": "integer", "minimum": 0 } + }, + "additionalProperties": false + }, + "column": { + "type": "object", + "required": ["columnId", "semantic", "bufferId", "scalarType", "byteOffset", "elementStride", "elementCount"], + "properties": { + "columnId": { "type": "string", "minLength": 1 }, + "semantic": { "type": "string", "minLength": 1 }, + "bufferId": { "type": "string", "minLength": 1 }, + "scalarType": { "type": "string", "minLength": 1 }, + "byteOffset": { "type": "integer", "minimum": 0 }, + "elementStride": { "type": "integer", "minimum": 1 }, + "elementCount": { "type": "integer", "minimum": 0 }, + "unit": { "type": "string" }, + "coordinateSpace": { "type": "string" } + }, + "additionalProperties": false + }, + "dirtyRange": { + "type": "object", + "required": ["columnId", "startIndex", "count", "generation"], + "properties": { + "columnId": { "type": "string", "minLength": 1 }, + "startIndex": { "type": "integer", "minimum": 0 }, + "count": { "type": "integer", "minimum": 0 }, + "generation": { "type": "integer", "minimum": 0 } + }, + "additionalProperties": false + }, + "renderGroup": { + "type": "object", + "required": ["groupId", "meshAssetRef", "materialAssetRef", "instanceCount", "defaultScale"], + "properties": { + "groupId": { "type": "integer", "minimum": 0 }, + "meshAssetRef": { "type": "string" }, + "materialAssetRef": { "type": "string" }, + "subMeshIndex": { "type": "integer", "minimum": 0 }, + "layer": { "type": "integer" }, + "instanceCount": { "type": "integer", "minimum": 0 }, + "defaultScale": { "type": "number" }, + "boundsCenterX": { "type": "number" }, + "boundsCenterY": { "type": "number" }, + "boundsCenterZ": { "type": "number" }, + "boundsSizeX": { "type": "number", "minimum": 0 }, + "boundsSizeY": { "type": "number", "minimum": 0 }, + "boundsSizeZ": { "type": "number", "minimum": 0 }, + "shadowMode": { "type": "string" }, + "receiveShadows": { "type": "boolean" }, + "lod": { "type": "integer" } + }, + "additionalProperties": false + } + }, + "additionalProperties": false +}