@underpostnet/cyberia 3.3.73 → 3.3.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +17 -5
- package/.github/workflows/coverall.cyberia.ci.yml +10 -0
- package/.github/workflows/docker-image.cyberia-client.ci.yml +1 -1
- package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +1 -1
- package/.github/workflows/docker-image.cyberia-server.ci.yml +1 -1
- package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +1 -1
- package/.github/workflows/docker-image.engine-cyberia.ci.yml +1 -1
- package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +1 -1
- package/.github/workflows/engine-cyberia.ci.yml +1 -1
- package/.github/workflows/publish.cyberia.ci.yml +44 -0
- package/AGENTS.md +61 -12
- package/CHANGELOG.md +159 -161
- package/CLI-HELP.md +20 -13
- package/Dockerfile +1 -1
- package/Dockerfile.dev +1 -1
- package/Dockerfile.test +2 -2
- package/README.md +28 -28
- package/bin/build.js +96 -21
- package/bin/cyberia.js +1247 -1373
- package/bin/index.js +1247 -1373
- package/compose.env +17 -5
- package/conf.js +7 -4
- package/deploy/cyberia-client/deploy.sh +10 -11
- package/deploy/cyberia-client/package.sh +0 -1
- package/deploy/cyberia-client/state.sh +3 -2
- package/deploy/cyberia-server/deploy.sh +10 -11
- package/deploy/cyberia-server/package.sh +0 -1
- package/deploy/cyberia-server/state.sh +3 -2
- package/deploy/dd-cyberia/deploy.sh +5 -5
- package/deploy/dd-cyberia/init.sh +15 -14
- package/deploy/dd-cyberia/package.sh +0 -1
- package/deploy/dd-cyberia/state.sh +2 -2
- package/deploy/dd-cyberia/sync-deploy.sh +139 -75
- package/deploy/lib/config.sh +29 -0
- package/deploy/lib/github-actions-logging.sh +92 -76
- package/deploy/lib/host.sh +28 -19
- package/deploy/lib/state.sh +4 -1
- package/deploy/pwa-microservices-template/deploy.sh +10 -8
- package/deploy/release/deploy.sh +0 -2
- package/deployment.yaml +1 -1
- package/docker-compose.yml +23 -17
- package/docs/coverage/cyberia/api/cyberia-instance/cyberia-fallback-capture.js.html +1591 -0
- package/docs/coverage/cyberia/api/cyberia-instance/index.html +116 -0
- package/docs/coverage/cyberia/api/cyberia-server-defaults/cyberia-server-defaults.js.html +4138 -0
- package/docs/coverage/cyberia/api/cyberia-server-defaults/index.html +116 -0
- package/docs/coverage/cyberia/api/object-layer/index.html +116 -0
- package/docs/coverage/cyberia/api/object-layer/object-layer.model.js.html +1393 -0
- package/docs/coverage/cyberia/base.css +362 -0
- package/docs/coverage/cyberia/block-navigation.js +82 -0
- package/docs/coverage/cyberia/favicon.png +0 -0
- package/docs/coverage/cyberia/index.html +161 -0
- package/docs/coverage/cyberia/prettify.css +101 -0
- package/docs/coverage/cyberia/prettify.js +937 -0
- package/docs/coverage/cyberia/projects/cyberia/atlas-sprite-sheet-generator.js.html +1315 -0
- package/docs/coverage/cyberia/projects/cyberia/index.html +176 -0
- package/docs/coverage/cyberia/projects/cyberia/instance-backup.js.html +715 -0
- package/docs/coverage/cyberia/projects/cyberia/instance-data.js.html +2182 -0
- package/docs/coverage/cyberia/projects/cyberia/shape-generator.js.html +3265 -0
- package/docs/coverage/cyberia/projects/cyberia/stat-balance.js.html +328 -0
- package/docs/coverage/cyberia/sort-arrow-sprite.png +0 -0
- package/docs/coverage/cyberia/sorter.js +205 -0
- package/hardhat/package-lock.json +2 -2
- package/hardhat/package.json +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +1 -1
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +1 -1
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/mongo-express/deployment.yaml +46 -27
- package/manifests/deployment/mongo-express/kustomization.yaml +9 -0
- package/manifests/deployment/mongo-express/mongo-express-nodeport.yaml +18 -0
- package/manifests/deployment/mongo-express/service.yaml +16 -0
- package/manifests/deployment/mongo-express-no-auth/disable-mongodb-auth.yaml +16 -0
- package/manifests/deployment/mongo-express-no-auth/kustomization.yaml +16 -0
- package/package.json +19 -17
- package/scripts/test-monitor.sh +3 -3
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +14 -9
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +36 -5
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +88 -184
- package/src/api/cyberia-action/cyberia-action.router.js +2 -2
- package/src/api/cyberia-action/cyberia-action.service.js +3 -4
- package/src/api/cyberia-audio/cyberia-audio.controller.js +6 -0
- package/src/api/cyberia-audio/cyberia-audio.model.js +61 -0
- package/src/api/cyberia-audio/cyberia-audio.router.js +21 -0
- package/src/api/cyberia-audio/cyberia-audio.service.js +220 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -3
- package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +10 -19
- package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +12 -34
- package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +15 -32
- package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
- package/src/api/cyberia-entity/cyberia-entity.model.js +2 -0
- package/src/api/cyberia-entity/cyberia-entity.service.js +1 -1
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +8 -2
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +31 -20
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +16 -1
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +466 -3
- package/src/api/cyberia-instance/cyberia-fallback-capture.js +87 -51
- package/src/api/cyberia-instance/cyberia-fallback-world.js +21 -40
- package/src/api/cyberia-instance/cyberia-instance-boot.service.js +5 -5
- package/src/api/cyberia-instance/cyberia-instance-items.js +98 -0
- package/src/api/cyberia-instance/cyberia-instance-map.service.js +34 -141
- package/src/api/cyberia-instance/cyberia-instance.controller.js +1 -4
- package/src/api/cyberia-instance/cyberia-instance.model.js +0 -14
- package/src/api/cyberia-instance/cyberia-instance.router.js +3 -16
- package/src/api/cyberia-instance/cyberia-instance.service.js +3 -43
- package/src/api/cyberia-instance/cyberia-world-generator.js +8 -13
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +49 -75
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +74 -1
- package/src/api/cyberia-map/cyberia-map.service.js +6 -2
- package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.controller.js +31 -0
- package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.model.js +56 -0
- package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.router.js +33 -0
- package/src/api/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +189 -0
- package/src/api/cyberia-quest/cyberia-quest.router.js +3 -3
- package/src/api/cyberia-quest/cyberia-quest.service.js +3 -3
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +1 -1
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +403 -188
- package/src/api/cyberia-skill/cyberia-skill.model.js +6 -6
- package/src/api/file/file.ref.js +153 -0
- package/src/api/file/file.ref.json +11 -2
- package/src/api/object-layer/object-layer.model.js +47 -12
- package/src/api/object-layer/object-layer.router.js +10 -3
- package/src/api/object-layer/object-layer.service.js +113 -120
- package/src/cli/app.js +12 -1
- package/src/cli/client.js +2 -2
- package/src/cli/cluster.js +80 -18
- package/src/cli/deploy.js +215 -34
- package/src/cli/docker-compose.js +1 -1
- package/src/cli/fs-selection.js +115 -0
- package/src/cli/fs.js +158 -342
- package/src/cli/index.js +22 -10
- package/src/cli/release.js +3 -1
- package/src/cli/repository.js +35 -9
- package/src/cli/run.js +80 -199
- package/src/cli/test.js +4 -0
- package/src/cli/wireguard.js +32 -31
- package/src/client/components/core/Badge.js +0 -1
- package/src/client/components/core/CssCore.js +8 -1
- package/src/client/components/core/Docs.js +77 -100
- package/src/client/components/core/Modal.js +77 -23
- package/src/client/components/core/ToolTip.js +15 -0
- package/src/client/components/cryptokoyn/AppShellCryptokoyn.js +0 -2
- package/src/client/components/cyberia/ActionEngineCyberia.js +12 -36
- package/src/client/components/cyberia/EntityEngineCyberia.js +492 -121
- package/src/client/components/cyberia/InstanceEngineCyberia.js +129 -160
- package/src/client/components/cyberia/InstanceSelectionView.js +7 -1
- package/src/client/components/cyberia/MapEngineCyberia.js +175 -69
- package/src/client/components/cyberia/ObjectLayerEngine.js +1011 -97
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +81 -155
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +113 -98
- package/src/client/components/cyberia/SharedDefaultsCyberia.js +215 -56
- package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +0 -34
- package/src/client/components/cyberia-portal/CssCyberiaPortal.js +1 -1
- package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +712 -76
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +0 -4
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +0 -4
- package/src/client/components/default/AppShellDefault.js +1 -4
- package/src/client/components/itemledger/AppShellItemledger.js +0 -2
- package/src/client/components/underpost/AppShellUnderpost.js +1 -1
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +15 -15
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +280 -24
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +51 -29
- package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +52 -53
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +16 -11
- package/src/client/public/cyberia-docs/CYBERIA.md +28 -28
- package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +11 -5
- package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
- package/src/client/public/cyberia-docs/STATS-PROGRESSION.md +217 -0
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +20 -12
- package/src/client/services/cyberia-audio/cyberia-audio.service.js +99 -0
- package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +38 -0
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +5 -4
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +0 -40
- package/src/client/services/cyberia-map/cyberia-map.management.js +5 -4
- package/src/client/services/cyberia-map-audio-conf/cyberia-map-audio-conf.service.js +138 -0
- package/src/client/services/object-layer/object-layer.management.js +6 -10
- package/src/client/services/object-layer/object-layer.service.js +3 -1
- package/src/client/ssr/views/Cyberia404.js +3 -3
- package/src/client-builder/client-build-docs.js +52 -52
- package/src/client-builder/client-build.js +67 -44
- package/src/client-builder/client-bundle.js +347 -0
- package/src/db/mongo/MongoExpress.js +187 -0
- package/src/grpc/cyberia/grpc-server.js +5 -7
- package/src/index.js +1 -1
- package/src/projects/cyberia/atlas-sprite-sheet-generator.js +143 -146
- package/src/projects/cyberia/atlas-sprite-sheet-store.js +391 -0
- package/src/projects/cyberia/besu-genesis-generator.js +5 -14
- package/src/projects/cyberia/boot-contract-fixtures.js +32 -0
- package/src/projects/cyberia/catalog-cyberia.js +3 -2
- package/src/projects/cyberia/gemini-client.js +3 -3
- package/src/projects/cyberia/generate-saga.js +4 -11
- package/src/projects/cyberia/hot-reload-trigger.js +17 -28
- package/src/projects/cyberia/instance-backup.js +210 -0
- package/src/projects/cyberia/instance-data.js +177 -257
- package/src/projects/cyberia/map-preview-generator.js +32 -68
- package/src/projects/cyberia/object-layer.js +152 -319
- package/src/projects/cyberia/seed-audio.js +139 -0
- package/src/projects/cyberia/semantic-layer-generator-skin.js +2 -8
- package/src/projects/cyberia/semantic-layer-generator.js +2 -18
- package/src/projects/cyberia/stat-balance.js +81 -0
- package/src/projects/cyberia/stat-commands.js +23 -0
- package/src/projects/cyberia/stat-contract-generator.js +101 -0
- package/src/runtime/cyberia-client/Dockerfile +8 -4
- package/src/runtime/cyberia-client/Dockerfile.dev +5 -2
- package/src/runtime/cyberia-server/Dockerfile +9 -2
- package/src/runtime/cyberia-server/Dockerfile.dev +8 -1
- package/src/runtime/engine-cyberia/Dockerfile +1 -1
- package/src/runtime/engine-cyberia/Dockerfile.dev +1 -1
- package/src/runtime/engine-cyberia/Dockerfile.test +2 -2
- package/src/runtime/engine-cyberia/compose.env +17 -5
- package/src/runtime/engine-cyberia/docker-compose.yml +23 -17
- package/src/server/build/coverage.js +113 -42
- package/src/server/build/package.js +55 -12
- package/src/server/build/testing.js +59 -9
- package/src/server/network/middlewares.js +8 -2
- package/src/server/network/underpost-gateway.js +113 -14
- package/src/server/ops/logger.js +70 -35
- package/src/server/runtime/conf.js +40 -9
- package/src/server/runtime/start.js +11 -2
- package/src/server/storage/data-query.js +16 -0
- package/src/server/storage/downloader.js +62 -14
- package/src/server/storage/zip.js +153 -0
- package/test/integration/app/cyberia/atlas-sprite-sheet-store.test.js +402 -0
- package/test/integration/app/cyberia/atlas-sprite-sheet.test.js +86 -0
- package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +34 -0
- package/test/integration/app/cyberia/cyberia-entity-type-default.test.js +842 -0
- package/test/integration/app/cyberia/cyberia-instance-conf-coerce.test.js +53 -0
- package/test/integration/app/cyberia/cyberia-instance-conf-defaults.test.js +16 -22
- package/test/integration/app/cyberia/cyberia-instance-items.test.js +90 -0
- package/test/integration/app/cyberia/cyberia-load.test.js +6 -7
- package/test/integration/app/cyberia/cyberia-map-audio-conf.test.js +256 -0
- package/test/integration/app/cyberia/cyberia-stats.test.js +150 -0
- package/test/integration/app/cyberia/fallback-world-capture.test.js +87 -2
- package/test/integration/app/cyberia/object-layer-item-selection.test.js +56 -0
- package/test/integration/app/cyberia/object-layer-natural-key.test.js +32 -0
- package/test/integration/app/cyberia/seed-audio.test.js +275 -0
- package/test/integration/infra/2-network/wireguard-cli.test.js +33 -9
- package/test/integration/infra/2-network/wireguard-edge.test.js +58 -18
- package/test/integration/infra/3-cluster/mongo-express-deploy.test.js +156 -0
- package/test/integration/infra/4-ingress/api-cross-origin.test.js +79 -0
- package/test/integration/infra/4-ingress/underpost-ingress.test.js +1 -1
- package/test/unit/catalog.test.js +13 -2
- package/test/unit/client-build-docs.test.js +97 -70
- package/test/unit/client-bundle.test.js +313 -0
- package/test/unit/conf-resolution.test.js +58 -7
- package/test/unit/coverage-artifact.test.js +120 -29
- package/test/unit/cyberia/instance-backup.test.js +183 -0
- package/test/unit/cyberia/instance-data.test.js +314 -0
- package/test/unit/cyberia/instance-object-layer-items.test.js +46 -0
- package/test/unit/cyberia/publish-workflow.test.js +22 -0
- package/test/unit/cyberia/stat-balance.test.js +69 -0
- package/test/unit/deploy-legacy-gateway-sweep.test.js +63 -0
- package/test/unit/deploy-log-table.test.js +76 -5
- package/test/unit/downloader-integrity.test.js +98 -0
- package/test/unit/file-reference-registry.test.js +141 -0
- package/test/unit/fs-storage-paths.test.js +596 -0
- package/test/unit/gateway-pod-fetch.test.js +95 -0
- package/test/unit/letsencrypt-issuer.test.js +101 -0
- package/test/unit/logger-redaction.test.js +29 -0
- package/test/unit/package.test.js +70 -16
- package/test/unit/prepare-host.test.js +84 -1
- package/test/unit/release-bump.test.js +3 -1
- package/test/unit/start-options.test.js +12 -0
- package/test/unit/test-tiers.test.js +27 -0
- package/test/unit/zip-archive.test.js +142 -0
- package/vitest.config.js +11 -3
- package/src/api/cyberia-instance/cyberia-fallback-default-items.js +0 -63
- package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +0 -368
|
@@ -56,10 +56,6 @@ class RouterCyberiaPortal {
|
|
|
56
56
|
title: 'cyberia-entity-engine',
|
|
57
57
|
render: () => s(`.main-btn-cyberia-entity-engine`).click(),
|
|
58
58
|
},
|
|
59
|
-
'/fallback-world-engine': {
|
|
60
|
-
title: 'fallback-world-engine',
|
|
61
|
-
render: () => s(`.main-btn-fallback-world-engine`).click(),
|
|
62
|
-
},
|
|
63
59
|
'/instance-selection': {
|
|
64
60
|
title: 'instance-selection',
|
|
65
61
|
render: () => s(`.main-btn-instance-selection`).click(),
|
|
@@ -30,10 +30,6 @@ class TranslateCyberiaPortal {
|
|
|
30
30
|
en: 'Cyberia Entity Engine',
|
|
31
31
|
es: 'Cyberia Entity Engine',
|
|
32
32
|
};
|
|
33
|
-
Translate.Data['fallback-world-engine'] = {
|
|
34
|
-
en: 'Fallback World Engine',
|
|
35
|
-
es: 'Fallback World Engine',
|
|
36
|
-
};
|
|
37
33
|
Translate.Data['instance-selection'] = {
|
|
38
34
|
en: 'Select World',
|
|
39
35
|
es: 'Seleccionar Mundo',
|
|
@@ -31,8 +31,6 @@ class AppShellDefault {
|
|
|
31
31
|
const RouterInstance = RouterDefault.instance();
|
|
32
32
|
|
|
33
33
|
const { barConfig } = await Themes[Css.currentTheme]();
|
|
34
|
-
|
|
35
|
-
const badgeNotificationMenuStyle = { top: '-33px', left: '24px' };
|
|
36
34
|
const barMode = undefined; // 'top-bottom-bar';
|
|
37
35
|
await Modal.instance({
|
|
38
36
|
id: 'modal-menu',
|
|
@@ -197,8 +195,7 @@ class AppShellDefault {
|
|
|
197
195
|
${await Badge.instance({
|
|
198
196
|
id: 'main-btn-chat',
|
|
199
197
|
type: 'circle-red',
|
|
200
|
-
|
|
201
|
-
classList: 'hide',
|
|
198
|
+
classList: 'hide badge-notification-menu',
|
|
202
199
|
})}`,
|
|
203
200
|
attrs: `data-id="chat"`,
|
|
204
201
|
tabHref: `${getProxyPath()}chat`,
|
|
@@ -27,8 +27,6 @@ class AppShellItemledger {
|
|
|
27
27
|
const RouterInstance = RouterItemledger.instance();
|
|
28
28
|
|
|
29
29
|
const { barConfig } = await Themes[Css.currentTheme]();
|
|
30
|
-
|
|
31
|
-
const badgeNotificationMenuStyle = { top: '-33px', left: '24px' };
|
|
32
30
|
const barMode = undefined; // 'top-bottom-bar';
|
|
33
31
|
await Modal.instance({
|
|
34
32
|
id: 'modal-menu',
|
|
@@ -9,8 +9,8 @@ Underpost Platform provides the toolchain, deployment surface, PWA delivery, and
|
|
|
9
9
|
## Process model
|
|
10
10
|
|
|
11
11
|
```
|
|
12
|
-
|
|
13
|
-
│ UNDERPOST PLATFORM (infra · toolchain · deploy · PWA/Workbox)
|
|
12
|
+
┌──────────────────────────────────────────────────────────────────────────┐
|
|
13
|
+
│ UNDERPOST PLATFORM (infra · toolchain · deploy · PWA/Workbox) │
|
|
14
14
|
│ │
|
|
15
15
|
│ ┌─────────────────────┐ │
|
|
16
16
|
│ │ Persistent backend │ ← Cyberia content authority + asset backend │
|
|
@@ -38,9 +38,9 @@ Underpost Platform provides the toolchain, deployment surface, PWA delivery, and
|
|
|
38
38
|
│ └─────────────────────┘ │
|
|
39
39
|
│ │ │
|
|
40
40
|
│ │ REST (atlas frames, asset metadata, client hints, │
|
|
41
|
-
│ │ instance-map static presence + capability activity)
|
|
41
|
+
│ │ instance-map static presence + capability activity) │
|
|
42
42
|
│ └──→ engine-cyberia │
|
|
43
|
-
|
|
43
|
+
└──────────────────────────────────────────────────────────────────────────┘
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
Three processes, strict role separation. The ecosystem is fully operational only when all three are running and healthy at the same time.
|
|
@@ -62,7 +62,7 @@ What it owns:
|
|
|
62
62
|
- gRPC `CyberiaDataService` for world load and content streaming.
|
|
63
63
|
- REST boot fallback (`/api/cyberia-instance/boot/*`): the same world-load / hot-reload payloads as the gRPC service, served over REST for deploys where the engine gRPC server is not enabled.
|
|
64
64
|
- REST APIs for assets and the optional client-hints overrides.
|
|
65
|
-
- Instance Map REST (`/api/cyberia-instance/instance-map/:code/{static,dynamic}`): static map topology plus authored presence POIs,
|
|
65
|
+
- Instance Map REST (`/api/cyberia-instance/instance-map/:code/{static,dynamic}`): static map topology plus authored presence POIs, and capability membership; the dynamic response supplies only per-player capability activity. Never live positions or simulation stats — those stay client-side.
|
|
66
66
|
- Static content distribution + Cloudinary-backed asset flow.
|
|
67
67
|
- Editor and CLI integration for content workflows.
|
|
68
68
|
|
|
@@ -125,7 +125,7 @@ The three processes are supervised independently. Each service owns its own moni
|
|
|
125
125
|
|
|
126
126
|
Dependency between services is handled by supervision and reconnect loops:
|
|
127
127
|
|
|
128
|
-
- `cyberia-server` dials `engine-cyberia` gRPC at boot; on dial or load failure it retries over the REST boot fallback (
|
|
128
|
+
- `cyberia-server` dials `engine-cyberia` gRPC at boot; on dial or load failure it retries over the REST boot fallback (`--data-server-url`, `/api/cyberia-instance/boot/*`) and exits only when both transports fail rather than fabricate a world. On reconnect, it reloads world configuration.
|
|
129
129
|
- `cyberia-client` reconnects to `cyberia-server` over WebSocket and re-fetches content from `engine-cyberia` over REST independently.
|
|
130
130
|
- If any one of the three services goes unhealthy, the game moves to standby until all three recover.
|
|
131
131
|
|
|
@@ -238,18 +238,18 @@ WS frame (binary) → decode → typed InputCommand{kind, clientTick, sequen
|
|
|
238
238
|
|
|
239
239
|
`InputCommand.Sequence` is monotonic per client. Every snapshot carries two acknowledgements of it, and they are not interchangeable:
|
|
240
240
|
|
|
241
|
-
| Field | Meaning | Client use
|
|
242
|
-
| --------- | ------------------------------------------------------------- |
|
|
243
|
-
| `ack` | Highest sequence **received** for this player.
|
|
244
|
-
| `moveAck` | Highest `PlayerAction` sequence that **re-planned movement**.
|
|
241
|
+
| Field | Meaning | Client use |
|
|
242
|
+
| --------- | ------------------------------------------------------------- | --------------------------------------------------------- |
|
|
243
|
+
| `ack` | Highest sequence **received** for this player. | Retires commands from the prediction buffer. |
|
|
244
|
+
| `moveAck` | Highest `PlayerAction` sequence that **re-planned movement**. | Gates adoption of the authoritative `targetPos` / `path`. |
|
|
245
245
|
|
|
246
|
-
**Movement re-plans once per player per tick, and nothing else throttles it.** Handlers record the tap's destination; `phaseInput` runs one A
|
|
246
|
+
**Movement re-plans once per player per tick, and nothing else throttles it.** Handlers record the tap's destination; `phaseInput` runs one A\* per player after the queue is drained. Taps that land in the same tick describe the same instant, so only the newest is planned — the rest were superseded before they could mean anything. That coalescing is the only bound on pathfinder cost.
|
|
247
247
|
|
|
248
248
|
This is why the two acknowledgements diverge: a superseded tap is acked on arrival and never planned, so `self.path` and `self.targetPos` can still describe an earlier command. A client that adopted the route on `ack` alone would turn back toward the abandoned target — worst during rapid changes of direction, where it reads as input lag and as a walk that sets off the wrong way.
|
|
249
249
|
|
|
250
250
|
Skills are not coalesced: they fire on every accepted tap, so the uplink carries every tap and the inbound rate limiter (`DefaultMessageRate`, 30/s) is what bounds the stream.
|
|
251
251
|
|
|
252
|
-
The client predicts every tap immediately and never waits on a cadence. `self.actionCooldownMs` is the skill-trigger period only; keyboard steering paces its
|
|
252
|
+
The client predicts every tap immediately and never waits on a cadence. `self.actionCooldownMs` is the skill-trigger period only; keyboard steering paces its _refresh_ by it, while a change of heading emits at once.
|
|
253
253
|
|
|
254
254
|
---
|
|
255
255
|
|
|
@@ -284,8 +284,8 @@ Every Cyberia document uses the same terms. Aliases are not permitted.
|
|
|
284
284
|
| **tick rate** | Simulation Hz on `cyberia-server`. |
|
|
285
285
|
| **snapshot** | AOI-filtered world view at one tick for one player. |
|
|
286
286
|
| **prediction** | Optimistic local apply of input commands to the predicted self entity. |
|
|
287
|
-
| **reconciliation** | Correct prediction by the error measured at one tick: authoritative position minus the position predicted for that tick. Input is a destination, not a per-tick impulse, so the client keeps walking toward the `targetPos` that `moveAck` confirms, rather than replaying a command log.
|
|
288
|
-
| **move coalescing** | One movement re-plan per player per tick, from the newest tap of that tick. The only bound on pathfinder cost, and the reason `moveAck` trails `ack`.
|
|
287
|
+
| **reconciliation** | Correct prediction by the error measured at one tick: authoritative position minus the position predicted for that tick. Input is a destination, not a per-tick impulse, so the client keeps walking toward the `targetPos` that `moveAck` confirms, rather than replaying a command log. |
|
|
288
|
+
| **move coalescing** | One movement re-plan per player per tick, from the newest tap of that tick. The only bound on pathfinder cost, and the reason `moveAck` trails `ack`. |
|
|
289
289
|
| **display smoothing** | Per-render-frame exponential lerp from the discrete predicted self position to a continuous on-screen position. Decouples the visible main player from sim-tick boundaries. |
|
|
290
290
|
| **interpolation** | Render-time smoothing of remote entities, sampled from snapshot history. |
|
|
291
291
|
| **authoritative server** | `cyberia-server`. Sole authority on world state. |
|
|
@@ -295,7 +295,7 @@ Every Cyberia document uses the same terms. Aliases are not permitted.
|
|
|
295
295
|
| **presentation metadata** | Render-only data. Client-owned. |
|
|
296
296
|
| **input command** | Typed client→server frame with kind, clientTick, sequence, payload. |
|
|
297
297
|
| **AOI** | Area of interest — the spatial filter that defines which entities a given player receives. |
|
|
298
|
-
| **Instance Map** | Client strategic overlay of packed map tiles and authored presence POIs. The static REST response supplies topology, presence,
|
|
298
|
+
| **Instance Map** | Client strategic overlay of packed map tiles and authored presence POIs. The static REST response supplies topology, presence, and capability membership; the dynamic response supplies per-player capability activity. Live player presence and stats remain client-side. |
|
|
299
299
|
| **replication** | Production and delivery of snapshots from server to clients. |
|
|
300
300
|
| **simulation phase** | A named step inside one simulation tick. |
|
|
301
301
|
| **healthy** | All three Cyberia services up and connected; game is playable. |
|
|
@@ -35,28 +35,38 @@ Import PNG assets, generate procedural layers, build atlas sprite sheets, push t
|
|
|
35
35
|
cyberia ol [item-id] [options]
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
| Option | Description
|
|
39
|
-
| ------------------------------------------------------------------------------------ |
|
|
40
|
-
| `--import` | Import specific item-id(s), comma-separated
|
|
41
|
-
| `--
|
|
42
|
-
| `--
|
|
43
|
-
| `--
|
|
44
|
-
| `--
|
|
45
|
-
| `--
|
|
46
|
-
| `--
|
|
47
|
-
| `--
|
|
48
|
-
| `--
|
|
49
|
-
| `--
|
|
50
|
-
| `--
|
|
51
|
-
| `--
|
|
38
|
+
| Option | Description |
|
|
39
|
+
| ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
|
|
40
|
+
| `--import` | Import specific item-id(s), comma-separated; needs one source below |
|
|
41
|
+
| `--instance <code>` | Source `--import` from that instance backup under `engine-private` |
|
|
42
|
+
| `--from-directory` | Source `--import` / `--import-types` from the asset directory |
|
|
43
|
+
| `--import-types [types]` | Batch import by type (e.g. `skin,floors`) or `all`; needs `--from-directory` |
|
|
44
|
+
| `--generate` | Generate procedural layers from a semantic item-id (e.g. `floor-desert`) |
|
|
45
|
+
| `--count <n>` / `--density <0..1>` | Shape count multiplier (default `3`) / density (default `0.5`) |
|
|
46
|
+
| `--seed <seed>` | Deterministic seed for `--generate` (e.g. `fx-42`) |
|
|
47
|
+
| `--frame-index <n>` / `--frame-count <n>` | Start frame (default `0`) / frame count (default `1`) |
|
|
48
|
+
| `--to-atlas-sprite-sheet [dim]` | Rebuild both atlas renders for the selected items |
|
|
49
|
+
| `--minify` | Refresh the minified render and the idle still; `--instance` narrows it |
|
|
50
|
+
| `--upscale <px-factor>` | Pixels per cell of the human-resolution render; alone, rebuilds it |
|
|
51
|
+
| `--normalize-stats` | Clamp the stats of every layer the action writes to its item type's bounds |
|
|
52
|
+
| `--random-stats` | Regenerate the stats of every layer the action writes at random |
|
|
53
|
+
| `--min-stat <n>` / `--max-stat <n>` | Narrow the range the two flags above may leave (default `-100`/`100`) |
|
|
54
|
+
| `--show-frame [dir_frame]` | View one frame (e.g. `08_0`; default `08_0`) |
|
|
55
|
+
| `--show-atlas-sprite-sheet` | Display the atlas PNG for the item |
|
|
56
|
+
| `--drop` | Drop existing data before importing (or standalone) |
|
|
57
|
+
| `--client-public` / `--git-clean` | With `--drop`: also remove static asset folders / run clean |
|
|
58
|
+
| `--env-path <path>` · `--mongo-host <host>` · `--dev` | env / DB / dev overrides |
|
|
52
59
|
|
|
53
60
|
```bash
|
|
54
|
-
#
|
|
55
|
-
cyberia ol hatchet,sword --
|
|
61
|
+
# Restore specific items from an instance backup: the backup is the authority for the item
|
|
62
|
+
cyberia ol hatchet,sword --instance FOREST --import
|
|
56
63
|
|
|
57
|
-
#
|
|
58
|
-
cyberia ol --import-
|
|
59
|
-
|
|
64
|
+
# Import specific items from the asset directory
|
|
65
|
+
cyberia ol hatchet,sword --from-directory --import --env-path ./engine-private/conf/dd-cyberia/.env.development
|
|
66
|
+
|
|
67
|
+
# Batch import by type, or everything, from the asset directory
|
|
68
|
+
cyberia ol --from-directory --import-types skin,floors
|
|
69
|
+
cyberia ol --from-directory --import-types all
|
|
60
70
|
|
|
61
71
|
# Procedural generation
|
|
62
72
|
cyberia ol floor-desert --generate --seed fx-42
|
|
@@ -66,16 +76,29 @@ cyberia ol floor-grass --generate --frame-count 4 --count 5 --density 0.7
|
|
|
66
76
|
cyberia ol hatchet --to-atlas-sprite-sheet
|
|
67
77
|
cyberia ol hatchet --show-frame 08_0
|
|
68
78
|
|
|
79
|
+
# Rebuild both atlas renders. The scope is an item-id, an instance, or everything.
|
|
80
|
+
cyberia ol hatchet --to-atlas-sprite-sheet --upscale 40
|
|
81
|
+
cyberia ol --instance TEST --upscale 20
|
|
82
|
+
cyberia ol --to-atlas-sprite-sheet
|
|
83
|
+
|
|
84
|
+
# Refresh the minified render the client downloads and the idle still every preview shows
|
|
85
|
+
cyberia ol hatchet --minify
|
|
86
|
+
cyberia ol --minify --instance FOREST
|
|
87
|
+
|
|
88
|
+
# Balance stats on every layer an action writes
|
|
89
|
+
cyberia ol --minify --instance FOREST --normalize-stats
|
|
90
|
+
cyberia ol hatchet --from-directory --import --random-stats --normalize-stats --max-stat 10
|
|
91
|
+
|
|
69
92
|
# Drop + re-import a single item, including static folders
|
|
70
|
-
cyberia ol hatchet --drop --client-public --import
|
|
93
|
+
cyberia ol hatchet --drop --client-public --from-directory --import
|
|
71
94
|
```
|
|
72
95
|
|
|
73
96
|
---
|
|
74
97
|
|
|
75
98
|
## `cyberia instance` — instance data
|
|
76
99
|
|
|
77
|
-
Export / import / drop a game instance and its related maps, entities, actions, quests,
|
|
78
|
-
layers in MongoDB.
|
|
100
|
+
Export / import / drop a game instance and its related maps, entities, actions, quests, object
|
|
101
|
+
layers and map audio in MongoDB.
|
|
79
102
|
|
|
80
103
|
```bash
|
|
81
104
|
cyberia instance [instance-code] [options]
|
|
@@ -87,6 +110,7 @@ cyberia instance [instance-code] [options]
|
|
|
87
110
|
| `--import [path]` | Import from a backup directory (upsert, preserves UUIDs) |
|
|
88
111
|
| `--conf` | With `--export`/`--import`: only `cyberia-instance.json` + `-conf.json` |
|
|
89
112
|
| `--drop` | Drop all documents associated with the instance code |
|
|
113
|
+
| `--sync-entities` | Sync the conf's entity-type default references and skill config |
|
|
90
114
|
| `--export-current-fallbackworld` | Capture the in-memory procedural fallback world, then export it |
|
|
91
115
|
| `--keep-fallback-codes` | Capture using the raw `fallback-map-*` / canonical action-quest codes |
|
|
92
116
|
| `--fallback-url <url>` | Capture the world a running engine serves instead of regenerating it |
|
|
@@ -98,6 +122,102 @@ cyberia instance FOREST --import ./backups/FOREST
|
|
|
98
122
|
cyberia instance FOREST --drop
|
|
99
123
|
```
|
|
100
124
|
|
|
125
|
+
A backup carries audio too. `cyberia-map-audio-confs/<map-code>.json` holds each map's bindings —
|
|
126
|
+
that configuration belongs to the map, so it travels with the instance and `--drop` removes it with
|
|
127
|
+
the map. The assets those bindings name travel as copies in `cyberia-audio/<code>.json` with their
|
|
128
|
+
WAV beside them in `files/`, because a `CyberiaAudio` document is global: the import upserts it by
|
|
129
|
+
code and leaves other instances' bindings alone, and `--drop` never removes one. A binding whose
|
|
130
|
+
asset is missing is kept as written — the code is the whole reference, so importing the asset later
|
|
131
|
+
is all it takes to make it play.
|
|
132
|
+
|
|
133
|
+
A backup also carries the entity-type defaults the instance's conf **references**, under
|
|
134
|
+
`cyberia-entity-type-defaults/<_id>.json`. `CyberiaInstanceConf.entityDefaults` holds
|
|
135
|
+
`CyberiaEntityTypeDefault` ids, never copies of the documents, and both directions travel by that
|
|
136
|
+
id: the export writes exactly the referenced documents, and the import restores them under their
|
|
137
|
+
original `_id` so the references keep resolving.
|
|
138
|
+
|
|
139
|
+
`--sync-entities` builds those references from the world's own content: a default belongs to the
|
|
140
|
+
instance when all of its `liveItemIds` appear together on some entity the maps place — the same
|
|
141
|
+
subset containment the runtime resolves an entity with. It is additive and idempotent, so a
|
|
142
|
+
hand-linked default that no map places (a player or coin default) is kept, and re-running links
|
|
143
|
+
nothing new. A match another instance already references is **reported, not adopted**: two worlds
|
|
144
|
+
built on the same art hold documents with identical live item ids, so matching alone cannot tell
|
|
145
|
+
them apart, and claiming one stays a deliberate act in the Entity engine.
|
|
146
|
+
|
|
147
|
+
Skills are **derived, never stored**. The `cyberia-skill` collection is deployment-wide and owns
|
|
148
|
+
the definitions; an instance runs the ones whose `triggerItemId` is an item id its own content
|
|
149
|
+
names. That content is four things and no more: what its maps place, what its entity-type defaults
|
|
150
|
+
wire, what its vendor and assembler catalogs trade, and what its quests ask for or pay out. The
|
|
151
|
+
canonical `ENTITY_TYPE_DEFAULTS` count alongside the instance's own, so a world referencing no
|
|
152
|
+
player default still holds `atlas_pistol_mk2` and keeps its projectile skill rather than being
|
|
153
|
+
disarmed.
|
|
154
|
+
|
|
155
|
+
That last source is why `hatchet` belongs to a world whose maps place no hatchet: a quest objective
|
|
156
|
+
or a shop shelf names one, so a player there can come to hold it and fire it. `--sync-entities`
|
|
157
|
+
reports the resolved list, the export writes exactly those documents to
|
|
158
|
+
`cyberia-skills/`, and the boot payload sends exactly those to the simulation — one rule, so the
|
|
159
|
+
three can no longer disagree. Nothing is written to the instance conf, which carries no
|
|
160
|
+
`skillConfig` field: a stored list was a second answer to the same question, and it was the one
|
|
161
|
+
that went stale.
|
|
162
|
+
|
|
163
|
+
The Instance engine has the same action as a button, syncing against the map codes currently
|
|
164
|
+
selected.
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
cyberia instance FOREST --sync-entities --dev
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
A reference cannot outlive its document. Deleting an entity-type default unlinks it from every
|
|
171
|
+
conf first, and both `--export` and `--import` compact the instance's references — dropping any
|
|
172
|
+
whose document is gone — so a backup never carries a dangling id and restoring one never recreates
|
|
173
|
+
it. Saving a default in the Entity engine compacts the collection too. What is exported is
|
|
174
|
+
therefore exactly what resolves.
|
|
175
|
+
|
|
176
|
+
That reference is what scopes a default to a world. Membership used to be inferred by matching item
|
|
177
|
+
ids, and two instances built on the same art therefore matched each other: exporting one dragged in
|
|
178
|
+
the other's wiring, and importing it overwrote the original by an `(entityType, liveItemIds)`
|
|
179
|
+
"natural key". An id names one document, so neither is possible. A backup written before the change
|
|
180
|
+
still embeds the documents in its conf; importing it converts them to references against the
|
|
181
|
+
documents in that same backup, creating any it cannot find.
|
|
182
|
+
|
|
183
|
+
An instance that references nothing is complete, not empty: it runs on the canonical
|
|
184
|
+
`ENTITY_TYPE_DEFAULTS`, and referenced documents override only the entity types they cover.
|
|
185
|
+
|
|
186
|
+
Those documents are also where a world's starting inventory comes from, and an entity has exactly
|
|
187
|
+
one. It carries the **union** of every id its default names — `liveItemIds`, `deadItemIds`,
|
|
188
|
+
`dropItemIds` and the inventory-only `inventoryItemsIds` — deduplicated. Nothing stores which slots
|
|
189
|
+
are worn: the three lifecycle lists are discriminators, and the runtime activates the ones the
|
|
190
|
+
context calls for, which is why the whole union is seeded (the server activates a slot that is
|
|
191
|
+
already there rather than appending one). Spawn state is alive, so the live ids are the active
|
|
192
|
+
ones; everything else is carried empty, a coin balance included.
|
|
193
|
+
|
|
194
|
+
`overrideItemsIdsState` is the one adjustment to that derivation, per id: `active` forces the spawn
|
|
195
|
+
state — a skin the equipment rules would otherwise leave inactive — `quantity` sizes a stack,
|
|
196
|
+
which is how a drop bundle declares how many tokens it scatters, and `dropChance` (0–1) says how
|
|
197
|
+
often the id actually scatters when the entity dies. It never adds an id; the union decides
|
|
198
|
+
membership, an override only what a member starts as.
|
|
199
|
+
|
|
200
|
+
`dropChance` is meaningful only for an id the build carries in `dropItemIds`; on any other row it is
|
|
201
|
+
inert, and the resolver reports 1 there so the simulation reads one field and never a missing one.
|
|
202
|
+
Saying nothing means 1, which is what every world did before the field existed, and each drop id is
|
|
203
|
+
rolled independently — a build can pair a common drop with a rare one and have both decided on their
|
|
204
|
+
own. A deliberate 0 survives, because the wire field is explicitly optional: absent and zero are
|
|
205
|
+
different answers.
|
|
206
|
+
|
|
207
|
+
`inventoryItemsIds` is therefore only for what no lifecycle state ever activates. The instance holds
|
|
208
|
+
no item list of its own: it names entity-type defaults, and the items follow from them, so there is
|
|
209
|
+
exactly one place to read or change a starting kit.
|
|
210
|
+
|
|
211
|
+
To point a world at the seeded collection, name it:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cyberia run-workflow seed-entities --instance FOREST --dev
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
`seed-entities` upserts `ENTITY_TYPE_DEFAULTS` into the collection; `--instance` then makes that
|
|
218
|
+
instance's conf reference exactly those documents, replacing whatever it referenced before, so
|
|
219
|
+
re-running converges rather than accumulating.
|
|
220
|
+
|
|
101
221
|
### Capturing the procedural fallback world
|
|
102
222
|
|
|
103
223
|
The fallback world is never persisted: every engine process rebuilds it from the code defaults at
|
|
@@ -105,7 +225,9 @@ boot and serves it whenever a requested instance is absent. `--export-current-fa
|
|
|
105
225
|
that in-memory world into MongoDB under a real instance code — maps and portal topology, the
|
|
106
226
|
instance conf, and the content collections the fallback path serves from code rather than the DB
|
|
107
227
|
(skills, entity-type defaults, dialogues, actions, quests) — and then exports it like any other
|
|
108
|
-
instance.
|
|
228
|
+
instance. It writes each captured map's audio configuration too, under the captured map code,
|
|
229
|
+
binding only the codes an imported `CyberiaAudio` actually carries and reporting the rest: the
|
|
230
|
+
client asks for audio by map code, so a namespaced capture would otherwise play nothing.
|
|
109
231
|
|
|
110
232
|
```bash
|
|
111
233
|
# Freeze the current fallback world as PROC-1 and back it up
|
|
@@ -119,7 +241,7 @@ Map, action and quest codes are namespaced under the instance code (`fallback-ma
|
|
|
119
241
|
`PROC-1-map-0`) so successive captures never overwrite each other; `--keep-fallback-codes` writes
|
|
120
242
|
the canonical codes verbatim instead. Sprites are the one thing a capture cannot synthesise: when a
|
|
121
243
|
referenced item id has no `ObjectLayer` document the command aborts and names the ids to import with
|
|
122
|
-
`cyberia ol <ids> --import`. Staged fallback default items live only in the serving engine process,
|
|
244
|
+
`cyberia ol <ids> --from-directory --import`. Staged fallback default items live only in the serving engine process,
|
|
123
245
|
so pass `--fallback-url http://localhost:4001` to capture a live world rather than regenerating it.
|
|
124
246
|
|
|
125
247
|
---
|
|
@@ -148,6 +270,140 @@ cyberia client-hints cyberia-main --export ./client-hints-cyberia-main.json
|
|
|
148
270
|
|
|
149
271
|
---
|
|
150
272
|
|
|
273
|
+
## `cyberia audio` — audio assets and map audio
|
|
274
|
+
|
|
275
|
+
Imports recorded [`cyberia-audio`](https://github.com/underpostnet/cyberia-audio) assets into MongoDB and binds
|
|
276
|
+
them to a map. Every recording is a pair — `<name>.wav` and its `<name>.json` manifest — and the pair is the unit
|
|
277
|
+
of import: a WAV with no manifest beside it is skipped. Produce the pair with `cyberia-audio sfx coin` or
|
|
278
|
+
`cyberia-audio music combat`.
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
cyberia audio [audio-code] [options]
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
| Option | Description |
|
|
285
|
+
| ----------------------------------------------------- | -------------------------------------------------------------------- |
|
|
286
|
+
| `--import` | Import WAV + manifest pairs; all of them when no code is given |
|
|
287
|
+
| `--records-path <path>` | Records directory to import from (default `./cyberia-audio/records`) |
|
|
288
|
+
| `--map <map-code>` | Target `cyberia-map` code to read or configure |
|
|
289
|
+
| `--set-default-music <audio-code>` | Default background music for `--map` |
|
|
290
|
+
| `--set-event <logic-event-id:audio-code>` | Bind an asset to a logic event (e.g. `combat`, `shoot`); repeatable |
|
|
291
|
+
| `--env-path <path>` · `--mongo-host <host>` · `--dev` | env / DB / dev overrides |
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
# Import every recorded asset, or a single one
|
|
295
|
+
cyberia audio --import
|
|
296
|
+
cyberia audio combat --import
|
|
297
|
+
|
|
298
|
+
# Configure a map, then read back what it resolved to
|
|
299
|
+
cyberia audio --map FOREST --set-default-music exploration \
|
|
300
|
+
--set-event projectile:shoot --set-event coin_drop_or_transaction:coin
|
|
301
|
+
cyberia audio --map FOREST
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
An asset is identified by its `code` alone — `cyberia-audio` stores what a sound _is_ (`code`, `fileId`,
|
|
305
|
+
`manifest`) and never what it is for. `manifest.bus` is the `src/audio-module/<bus-id>/` directory the module
|
|
306
|
+
was authored in — the asset's natural route, recorded as provenance; a map binding decides where it actually
|
|
307
|
+
plays. Configuration lands in `cyberia-map-audio-conf`, one document per map code,
|
|
308
|
+
holding `defaultMusic`, a single `events` list and volume/loop/crossfade `settings`. Each binding is the same
|
|
309
|
+
pattern the skill model uses — a semantic `logicEventId` resolving to an `audioCode`:
|
|
310
|
+
|
|
311
|
+
```js
|
|
312
|
+
{ logicEventId: 'combat', audioCode: 'combat', settings: { bus: 'music', loop: true, crossfadeMs: 800 } }
|
|
313
|
+
{ logicEventId: 'hit', audioCode: 'hit' }
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
`bus` is one vocabulary with one spelling — `music` and `sfx`, declared once in
|
|
317
|
+
`SharedDefaultsCyberia.AUDIO_BUSES`. The same two ids name the `cyberia-audio/src/audio-module/<bus-id>/`
|
|
318
|
+
directory an asset is authored in, the argument `cyberia-audio <bus-id> <id>` dispatches on, the `bus` a
|
|
319
|
+
recorded manifest carries, and the route a binding's `settings.bus` selects.
|
|
320
|
+
|
|
321
|
+
The event vocabulary is centralized the same way: `SharedDefaultsCyberia.AUDIO_LOGIC_IDS` declares the
|
|
322
|
+
events a binding may answer and the bus each one naturally routes to, `cyberia-server-defaults` holds the seed's
|
|
323
|
+
bank (`DEFAULT_AUDIO_BANK`) and its bindings (`DEFAULT_AUDIO_BINDINGS`, expanded by `buildAudioEventBindings`),
|
|
324
|
+
and `cyberia-client/src/audio/audio_events.h` holds the same ids for the emitting side. A binding naming an
|
|
325
|
+
unknown event, or an asset the bank does not carry, throws at import rather than playing silence.
|
|
326
|
+
|
|
327
|
+
The fallback bank binds `projectile`, `coin_drop_or_transaction`, `drop`, `item-pickup`, `victory`, `level-up`,
|
|
328
|
+
`death`, `heal`, `hit`, `portal`, `ui-click` and `footsteps` as one-shots, and `combat`, `boss`, `portal-cooldown` and
|
|
329
|
+
`craft` as music. `victory` is a cue rather than a bed: completing a quest is an event, and holding the
|
|
330
|
+
bus for it would take the map's music away for the length of a flourish. `hit` follows the server's damage events, so it sounds for any entity in view rather than
|
|
331
|
+
only for the player; `level-up` and `death` arrive as server `audio_event` broadcasts, so a level gained or a defeat sounds for every viewer in reach; `ui-click` follows a tap the interface accepted.
|
|
332
|
+
|
|
333
|
+
`item-pickup` fires where every route into the inventory bar converges — world loot flying in, a quest
|
|
334
|
+
reward, a purchase, an assembly output — so one emission covers them all. It is deliberately plainer than
|
|
335
|
+
`coin`, which stays the reward gesture reserved for currency.
|
|
336
|
+
|
|
337
|
+
`craft` is a held bed rather than a cue, the same shape as `portal-cooldown`: it takes over the map's music
|
|
338
|
+
for exactly as long as a recipe's assembly bar charges, loops seamlessly while the player waits, and releases
|
|
339
|
+
back to the map on completion. Both holds are arbitrated in `audio_context.c`, which is also what makes them
|
|
340
|
+
outlive a combat exchange instead of being cut by it — the modal owns the bar and only reports whether one is
|
|
341
|
+
running.
|
|
342
|
+
|
|
343
|
+
Two cues are about the crowd rather than about one event, because sounding them per entity buries the bus.
|
|
344
|
+
`heal` is a milestone: regeneration ticks constantly and in small amounts, so it sounds only when an entity's
|
|
345
|
+
life crosses back above zero, 25%, 50% or 75%, once per snapshot however many entities crossed. `footsteps`
|
|
346
|
+
is a cadence: one gait cycle repeats for as long as anything with feet is walking in view, at one rate for the
|
|
347
|
+
whole scene rather than one per walker.
|
|
348
|
+
|
|
349
|
+
Portal audio follows the authoritative teleport charge, never the map code: `onPortal` holds `portal-cooldown` as
|
|
350
|
+
a bed for as long as the charge runs, and completing it fires the `portal` one-shot while the departing map's
|
|
351
|
+
bindings are still resident. An intra-map portal moves the player without changing maps, so watching the map code
|
|
352
|
+
was silent for exactly that case; stepping off the pad drops the bed without sounding the jump.
|
|
353
|
+
|
|
354
|
+
Whether a binding behaves as a bed, a one-shot or a transition follows from the logic event that fires it and the
|
|
355
|
+
settings it carries, not from a classification stored twice. The code is checked against the imported assets, so
|
|
356
|
+
an unimported one is rejected rather than stored as a dangling name. Bindings merge by `logicEventId`: naming an
|
|
357
|
+
event replaces that binding and leaves the others in place. `--map` on its own prints the current configuration
|
|
358
|
+
and writes nothing.
|
|
359
|
+
|
|
360
|
+
The fallback seed is the exception, and deliberately so: it states a map's complete binding set, so re-running it
|
|
361
|
+
converges. A binding whose logic event the bank no longer declares — a renamed cue, for instance — is dropped and
|
|
362
|
+
logged, instead of surviving as a name the client would keep asking the engine to resolve.
|
|
363
|
+
|
|
364
|
+
`settings.bus` selects `music` or `sfx` on the binding. It does not classify the asset.
|
|
365
|
+
Omitted settings inherit client or map defaults. Supported overrides include volume, loop, crossfadeMs, pitch, pan, and priority.
|
|
366
|
+
Set music event routing through the map configuration API or the fallback seed workflow.
|
|
367
|
+
Changing only an event's audio code preserves its existing settings.
|
|
368
|
+
|
|
369
|
+
Record and seed the complete fallback bank from the engine repository root:
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
cyberia run-workflow seed-audio --records-only
|
|
373
|
+
cyberia run-workflow seed-audio --dev --mongo-host 127.0.0.1
|
|
374
|
+
cyberia run-workflow seed-audio --instance my-instance --dev --mongo-host 127.0.0.1
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
The first command records thirteen WAV and manifest pairs and touches no database.
|
|
378
|
+
The second also upserts generic File references, CyberiaAudio metadata, and audio configuration for the fallback maps.
|
|
379
|
+
The third configures one instance's maps instead: `--instance <instance-code>` reads that instance's own
|
|
380
|
+
`cyberiaMapCodes` and scores every one of them with the same bank, bindings and default bed the fallback world
|
|
381
|
+
uses, so a world built on that topology sounds the way the fallback world does. Every map falls back to the
|
|
382
|
+
`exploration` bed; what makes a place sound different is the event that fires there. The instance must exist and
|
|
383
|
+
declare at least one map, or the run fails without writing anything.
|
|
384
|
+
|
|
385
|
+
Every form states each map's whole configuration, so re-running converges rather than accumulating: a bed is
|
|
386
|
+
reassigned and a binding the bank no longer declares is dropped.
|
|
387
|
+
It reuses the existing engine environment resolution. Full seeding requires that deployment configuration and MongoDB.
|
|
388
|
+
Use `--records-path` to select the output directory.
|
|
389
|
+
An asset's generic File `_id` is derived from its code and the bytes themselves, so re-importing an unchanged
|
|
390
|
+
bank rewrites nothing, and a changed render lands on a new `fileId` while the blob it replaced is deleted in the
|
|
391
|
+
same step. That is what keeps the client honest: it fetches a WAV as `/api/file/blob/<fileId>` and caches it, so
|
|
392
|
+
new bytes under a reused id would go on playing the old sound. `cyberia-audio.fileId` is registered in
|
|
393
|
+
`src/api/file/file.ref.json`, which is the list `underpost db clean-fs` treats as the complete set of File
|
|
394
|
+
references — a blob no registered field points at is deleted by that sweep. Deleting an asset, through the API or
|
|
395
|
+
by restoring an instance over it, deletes its blob with it. Interrupted imports can be rerun safely.
|
|
396
|
+
|
|
397
|
+
Recording produces nothing for the client to ship: `cyberia-client` bundles no WAV and fetches every asset from
|
|
398
|
+
engine-cyberia by code, so an asset is reachable only once it is seeded.
|
|
399
|
+
|
|
400
|
+
The client resolves `logicEventId → audioCode → fileId → /api/file/blob/:fileId` and caches decoded WAVs.
|
|
401
|
+
Fallback maps use exploration, combat, boss, and exploration music in order.
|
|
402
|
+
Missing remote content uses the generated local bank. Unknown effects become silence.
|
|
403
|
+
Regenerate the local bank before building the client after changing audio content.
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
151
407
|
## `cyberia chain` — Besu + ObjectLayerToken
|
|
152
408
|
|
|
153
409
|
Hyperledger Besu IBFT2 network and ERC-1155 `ObjectLayerToken` (CKY) lifecycle.
|