@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
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* browser editor — the procedural fallback world — still get a `preview`
|
|
9
9
|
* image for the client's Instance Map node backgrounds.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Every entity is drawn by its items' idle-preview stills, the same picture the
|
|
12
|
+
* editors show, read from the atlas the item key resolves to.
|
|
13
13
|
*
|
|
14
14
|
* Previews are pure functions of the map's entity list, so results are cached
|
|
15
15
|
* in memory keyed by a content hash — the fallback world is regenerated (and
|
|
@@ -19,92 +19,56 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import crypto from 'crypto';
|
|
22
|
-
import fs from 'fs-extra';
|
|
23
22
|
import sharp from 'sharp';
|
|
23
|
+
import { DataBaseProviderService } from '../../db/DataBaseProvider.js';
|
|
24
24
|
import { loggerFactory } from '../../server/ops/logger.js';
|
|
25
|
-
import {
|
|
26
|
-
ENTITY_TYPE_TO_ITEM_TYPES,
|
|
27
|
-
getDefaultCyberiaItemById,
|
|
28
|
-
} from '../../client/components/cyberia/SharedDefaultsCyberia.js';
|
|
29
25
|
|
|
30
26
|
const logger = loggerFactory(import.meta);
|
|
31
27
|
|
|
32
|
-
const ASSET_ROOT = './src/client/public/cyberia/assets';
|
|
33
|
-
/** Direction/frame the editor previews with (08 = down_idle, frame 0). */
|
|
34
|
-
const PREVIEW_DIRECTION = '08';
|
|
35
|
-
const PREVIEW_FRAME = '0.png';
|
|
36
|
-
|
|
37
28
|
/** Node backgrounds are small; render cells down so a 64×64 map stays cheap. */
|
|
38
29
|
const DEFAULT_CELL_PX = 8;
|
|
39
30
|
const MAX_SIDE_PX = 1024;
|
|
40
31
|
|
|
41
|
-
/** Item-type directories under ASSET_ROOT, read once. */
|
|
42
|
-
let assetTypeDirs = null;
|
|
43
|
-
|
|
44
|
-
async function itemTypeDirs() {
|
|
45
|
-
if (assetTypeDirs) return assetTypeDirs;
|
|
46
|
-
try {
|
|
47
|
-
const entries = await fs.readdir(ASSET_ROOT, { withFileTypes: true });
|
|
48
|
-
assetTypeDirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
49
|
-
} catch (error) {
|
|
50
|
-
logger.warn(`map preview: cannot read asset root: ${error.message}`);
|
|
51
|
-
assetTypeDirs = [];
|
|
52
|
-
}
|
|
53
|
-
return assetTypeDirs;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
32
|
/**
|
|
57
|
-
* itemId →
|
|
58
|
-
*
|
|
59
|
-
* The defaults registry only knows canonical items; saga-generated ones live on
|
|
60
|
-
* disk without an entry, so the item type is resolved by probing — registry
|
|
61
|
-
* first, then the types this entity type allows, then any remaining directory.
|
|
33
|
+
* Idle-still cache: itemId → Buffer | null. The still is keyed by item id on the
|
|
34
|
+
* atlas, so no type has to be known or probed to find it.
|
|
62
35
|
*/
|
|
63
|
-
const
|
|
36
|
+
const stillCache = new Map();
|
|
64
37
|
|
|
65
|
-
async function
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
for (const type of await itemTypeDirs()) pushType(type);
|
|
77
|
-
|
|
78
|
-
let found = null;
|
|
79
|
-
for (const type of candidates) {
|
|
80
|
-
const path = `${ASSET_ROOT}/${type}/${itemId}/${PREVIEW_DIRECTION}/${PREVIEW_FRAME}`;
|
|
81
|
-
if (await fs.pathExists(path)) {
|
|
82
|
-
found = path;
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
38
|
+
async function idleStill(itemId, options) {
|
|
39
|
+
if (stillCache.has(itemId)) return stillCache.get(itemId);
|
|
40
|
+
let buffer = null;
|
|
41
|
+
try {
|
|
42
|
+
const AtlasSpriteSheet = DataBaseProviderService.getModel('AtlasSpriteSheet', options);
|
|
43
|
+
const File = DataBaseProviderService.getModel('File', options);
|
|
44
|
+
const atlas = await AtlasSpriteSheet.findOne({ 'metadata.itemKey': itemId }, { idlePreviewFileId: 1 }).lean();
|
|
45
|
+
const file = atlas?.idlePreviewFileId ? await File.findById(atlas.idlePreviewFileId, { data: 1 }) : null;
|
|
46
|
+
if (file?.data) buffer = Buffer.from(file.data);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
logger.warn(`map preview: idle still lookup failed for "${itemId}": ${error.message}`);
|
|
85
49
|
}
|
|
86
|
-
|
|
87
|
-
return
|
|
50
|
+
stillCache.set(itemId, buffer);
|
|
51
|
+
return buffer;
|
|
88
52
|
}
|
|
89
53
|
|
|
90
54
|
/**
|
|
91
|
-
* Resized-frame cache: `${
|
|
55
|
+
* Resized-frame cache: `${itemId}:${w}x${h}` → Buffer | null.
|
|
92
56
|
* A map tiles thousands of floor cells from a handful of distinct items, so
|
|
93
|
-
* resizing once per (
|
|
57
|
+
* resizing once per (item, size) is the difference between fast and unusable.
|
|
94
58
|
*/
|
|
95
59
|
const frameCache = new Map();
|
|
96
60
|
|
|
97
|
-
async function resizedFrame(itemId,
|
|
98
|
-
const
|
|
99
|
-
if (!
|
|
61
|
+
async function resizedFrame(itemId, width, height, options) {
|
|
62
|
+
const still = await idleStill(itemId, options);
|
|
63
|
+
if (!still) return null;
|
|
100
64
|
|
|
101
|
-
const key = `${
|
|
65
|
+
const key = `${itemId}:${width}x${height}`;
|
|
102
66
|
if (frameCache.has(key)) return frameCache.get(key);
|
|
103
67
|
|
|
104
68
|
let buffer = null;
|
|
105
69
|
try {
|
|
106
70
|
// `nearest` keeps the pixel-art edges crisp at small sizes.
|
|
107
|
-
buffer = await sharp(
|
|
71
|
+
buffer = await sharp(still).resize(width, height, { kernel: 'nearest' }).png().toBuffer();
|
|
108
72
|
} catch (error) {
|
|
109
73
|
logger.warn(`map preview: frame render failed for "${itemId}": ${error.message}`);
|
|
110
74
|
}
|
|
@@ -182,8 +146,7 @@ function mapPreviewHash(map, cellPx) {
|
|
|
182
146
|
e.dimX,
|
|
183
147
|
e.dimY,
|
|
184
148
|
(e.objectLayerItemIds || []).join(','),
|
|
185
|
-
//
|
|
186
|
-
e.entityType || '',
|
|
149
|
+
// The colour is the render fallback for an entity whose items have no still.
|
|
187
150
|
e.color || '',
|
|
188
151
|
]);
|
|
189
152
|
return crypto
|
|
@@ -198,9 +161,10 @@ function mapPreviewHash(map, cellPx) {
|
|
|
198
161
|
* @param {object} map CyberiaMap-shaped (code, gridX/gridY, entities).
|
|
199
162
|
* @param {object} [opts]
|
|
200
163
|
* @param {number} [opts.cellPx=8] Pixels per grid cell in the output.
|
|
164
|
+
* @param {object} [opts.options] Router options ({ host, path }) the stills are read with.
|
|
201
165
|
* @returns {Promise<Buffer|null>} PNG buffer, or null when nothing rendered.
|
|
202
166
|
*/
|
|
203
|
-
async function renderMapPreviewPng(map, { cellPx = DEFAULT_CELL_PX } = {}) {
|
|
167
|
+
async function renderMapPreviewPng(map, { cellPx = DEFAULT_CELL_PX, options } = {}) {
|
|
204
168
|
const gridX = map?.gridX || 0;
|
|
205
169
|
const gridY = map?.gridY || 0;
|
|
206
170
|
if (gridX <= 0 || gridY <= 0) return null;
|
|
@@ -211,8 +175,8 @@ async function renderMapPreviewPng(map, { cellPx = DEFAULT_CELL_PX } = {}) {
|
|
|
211
175
|
const width = gridX * cell;
|
|
212
176
|
const height = gridY * cell;
|
|
213
177
|
|
|
214
|
-
// Every entity of every entityType in the array renders something: its
|
|
215
|
-
//
|
|
178
|
+
// Every entity of every entityType in the array renders something: its items'
|
|
179
|
+
// stills when the atlases hold them, otherwise a flat fill of its colour.
|
|
216
180
|
const composites = [];
|
|
217
181
|
for (const entity of map.entities || []) {
|
|
218
182
|
const left = Math.round((entity.initCellX || 0) * cell);
|
|
@@ -224,7 +188,7 @@ async function renderMapPreviewPng(map, { cellPx = DEFAULT_CELL_PX } = {}) {
|
|
|
224
188
|
// Stack the entity's layers in declaration order, exactly like the editor.
|
|
225
189
|
let drew = false;
|
|
226
190
|
for (const itemId of entity.objectLayerItemIds || []) {
|
|
227
|
-
const input = await resizedFrame(itemId,
|
|
191
|
+
const input = await resizedFrame(itemId, w, h, options);
|
|
228
192
|
if (input) {
|
|
229
193
|
composites.push({ input, left, top });
|
|
230
194
|
drew = true;
|