cyberia 3.0.1 → 3.0.2
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/.github/workflows/engine-cyberia.cd.yml +1 -0
- package/CHANGELOG.md +56 -1
- package/CLI-HELP.md +2 -4
- package/README.md +139 -0
- package/bin/build.js +5 -0
- package/bin/cyberia.js +385 -71
- package/bin/deploy.js +18 -26
- package/bin/file.js +3 -0
- package/bin/index.js +385 -71
- package/conf.js +32 -3
- package/deployment.yaml +2 -2
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
- package/manifests/ipfs/configmap.yaml +7 -0
- package/package.json +8 -8
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +2 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +7 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +93 -2
- package/src/api/file/file.controller.js +3 -13
- package/src/api/file/file.ref.json +0 -21
- package/src/api/ipfs/ipfs.controller.js +104 -0
- package/src/api/ipfs/ipfs.model.js +71 -0
- package/src/api/ipfs/ipfs.router.js +31 -0
- package/src/api/ipfs/ipfs.service.js +193 -0
- package/src/api/object-layer/README.md +139 -0
- package/src/api/object-layer/object-layer.controller.js +3 -0
- package/src/api/object-layer/object-layer.model.js +15 -1
- package/src/api/object-layer/object-layer.router.js +6 -10
- package/src/api/object-layer/object-layer.service.js +311 -182
- package/src/cli/cluster.js +30 -38
- package/src/cli/index.js +0 -1
- package/src/cli/run.js +14 -0
- package/src/client/components/core/LoadingAnimation.js +2 -3
- package/src/client/components/core/Modal.js +1 -1
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +4 -5
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +280 -29
- package/src/client/services/ipfs/ipfs.service.js +144 -0
- package/src/client/services/object-layer/object-layer.management.js +161 -8
- package/src/index.js +1 -1
- package/src/runtime/express/Express.js +1 -1
- package/src/server/auth.js +18 -18
- package/src/server/ipfs-client.js +433 -0
- package/src/server/object-layer.js +649 -18
- package/src/server/semantic-layer-generator.js +1083 -0
- package/src/server/shape-generator.js +952 -0
- package/test/shape-generator.test.js +457 -0
- package/bin/ssl.js +0 -63
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Provides utilities and engine logic for processing and managing Cyberia Online's object layer assets (skins, floors, weapons, etc.).
|
|
3
|
+
* Centralizes shared logic consumed by both the Cyberia CLI and the REST API service layer.
|
|
3
4
|
* @module src/server/object-layer.js
|
|
4
5
|
* @namespace CyberiaObjectLayer
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import fs from 'fs-extra';
|
|
9
|
+
import path from 'path';
|
|
8
10
|
import { PNG } from 'pngjs';
|
|
9
11
|
import sharp from 'sharp';
|
|
10
12
|
import { Jimp, intToRGBA, rgbaToInt } from 'jimp';
|
|
13
|
+
import crypto from 'crypto';
|
|
14
|
+
import stringify from 'fast-json-stable-stringify';
|
|
11
15
|
|
|
12
16
|
import { range } from '../client/components/core/CommonJs.js';
|
|
13
17
|
import { random } from '../client/components/core/CommonJs.js';
|
|
@@ -21,14 +25,71 @@ const logger = loggerFactory(import.meta);
|
|
|
21
25
|
* @property {string} objectLayerType - The type of object layer (e.g., 'skin', 'floor').
|
|
22
26
|
* @property {string} objectLayerId - The unique ID of the object layer asset.
|
|
23
27
|
* @property {string} direction - The direction folder name (e.g., '08', '12').
|
|
24
|
-
* @memberof CyberiaObjectLayer
|
|
25
28
|
* @property {string} frame - The frame file name.
|
|
29
|
+
* @memberof CyberiaObjectLayer
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {Object} ObjectLayerRenderFramesData
|
|
34
|
+
* @property {Object<string, number[][][]>} frames - Map of direction names to arrays of frame matrices.
|
|
35
|
+
* @property {Array<number[]>} colors - Global color palette shared across all frames.
|
|
36
|
+
* @property {number} frame_duration - Duration of each frame in milliseconds.
|
|
37
|
+
* @property {boolean} is_stateless - Whether the render layer is stateless (no animation state).
|
|
38
|
+
* @memberof CyberiaObjectLayer
|
|
26
39
|
*/
|
|
27
40
|
|
|
41
|
+
/**
|
|
42
|
+
* @typedef {Object} ObjectLayerData
|
|
43
|
+
* @property {Object} data - Object layer data payload.
|
|
44
|
+
* @property {Object} data.item - Item descriptor.
|
|
45
|
+
* @property {string} data.item.id - Unique identifier for the item.
|
|
46
|
+
* @property {string} data.item.type - Type of the item (e.g., 'skin', 'floor').
|
|
47
|
+
* @property {string} [data.item.description] - Human-readable description.
|
|
48
|
+
* @property {boolean} [data.item.activable] - Whether the item can be activated.
|
|
49
|
+
* @property {Object} data.stats - Statistical attributes of the object layer.
|
|
50
|
+
* @property {string} data.seed - Random UUID v4 for unique state generation.
|
|
51
|
+
* @property {string} [data.atlasSpriteSheetCid] - IPFS CID for the consolidated atlas sprite sheet PNG.
|
|
52
|
+
* @property {ObjectLayerRenderFramesData} [objectLayerRenderFramesData] - Render frames data (transient, used before persisting).
|
|
53
|
+
* @property {import('mongoose').Types.ObjectId} [objectLayerRenderFramesId] - Reference to persisted ObjectLayerRenderFrames document.
|
|
54
|
+
* @property {string} [sha256] - SHA-256 hash of the object layer data.
|
|
55
|
+
* @memberof CyberiaObjectLayer
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @typedef {Object} BuildFromDirectoryResult
|
|
60
|
+
* @property {ObjectLayerRenderFramesData} objectLayerRenderFramesData - The assembled render frames data.
|
|
61
|
+
* @property {Object} objectLayerData - The assembled object layer data (without render frames reference or sha256).
|
|
62
|
+
* @memberof CyberiaObjectLayer
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @typedef {Object} CreateDocumentsOptions
|
|
67
|
+
* @property {boolean} [generateAtlas=true] - Whether to generate the atlas sprite sheet after creating documents.
|
|
68
|
+
* @property {Object} [atlasServiceContext] - Context required by AtlasSpriteSheetService.generate (req, res, options).
|
|
69
|
+
* @property {Object} [atlasServiceContext.req] - Express-like request object (must include auth).
|
|
70
|
+
* @property {Object} [atlasServiceContext.res] - Express-like response object.
|
|
71
|
+
* @property {Object} [atlasServiceContext.options] - Server options (host, path).
|
|
72
|
+
* @memberof CyberiaObjectLayer
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @typedef {Object} CreateDocumentsResult
|
|
77
|
+
* @property {Object} objectLayer - The persisted ObjectLayer mongoose document.
|
|
78
|
+
* @property {Object} objectLayerRenderFramesDoc - The persisted ObjectLayerRenderFrames mongoose document.
|
|
79
|
+
* @memberof CyberiaObjectLayer
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Engine class providing static utilities for Cyberia Online object layer asset processing,
|
|
84
|
+
* frame extraction, directory iteration, image building, and centralized document creation logic.
|
|
85
|
+
* @class ObjectLayerEngine
|
|
86
|
+
* @memberof CyberiaObjectLayer
|
|
87
|
+
*/
|
|
28
88
|
export class ObjectLayerEngine {
|
|
29
89
|
/**
|
|
90
|
+
* Iterates through the directory structure of object layer PNG assets for a given type.
|
|
91
|
+
* Walks `./src/client/public/cyberia/assets/{objectLayerType}/{id}/{direction}/{frame}`.
|
|
30
92
|
* @static
|
|
31
|
-
* @description Iterates through the directory structure of object layer PNG assets for a given type.
|
|
32
93
|
* @param {string} [objectLayerType='skin'] - The type of object layer to iterate over (e.g., 'skin', 'floor').
|
|
33
94
|
* @param {function(ObjectLayerCallbackPayload): Promise<void>} [callback=() => {}] - The async function to execute for each image file found.
|
|
34
95
|
* @returns {Promise<void>}
|
|
@@ -61,10 +122,10 @@ export class ObjectLayerEngine {
|
|
|
61
122
|
}
|
|
62
123
|
|
|
63
124
|
/**
|
|
125
|
+
* Asynchronously reads a PNG file and resolves with its raw bitmap data, width, and height.
|
|
64
126
|
* @static
|
|
65
|
-
* @description Asynchronously reads a PNG file and resolves with its raw bitmap data, width, and height.
|
|
66
127
|
* @param {string} filePath - The path to the PNG file.
|
|
67
|
-
* @returns {Promise<{width: number, height: number, data: Buffer} | {error: true, message: string}>}
|
|
128
|
+
* @returns {Promise<{width: number, height: number, data: Buffer} | {error: true, message: string}>} The image data or an error object.
|
|
68
129
|
* @memberof CyberiaObjectLayer
|
|
69
130
|
*/
|
|
70
131
|
static readPngAsync(filePath) {
|
|
@@ -87,12 +148,12 @@ export class ObjectLayerEngine {
|
|
|
87
148
|
}
|
|
88
149
|
|
|
89
150
|
/**
|
|
90
|
-
*
|
|
91
|
-
* @description Processes an image file (PNG or GIF) to generate a frame matrix and a color palette (map_color).
|
|
151
|
+
* Processes an image file (PNG or GIF) to generate a frame matrix and a color palette (map_color).
|
|
92
152
|
* It quantizes the image based on a factor derived from image height (mazeFactor).
|
|
153
|
+
* @static
|
|
93
154
|
* @param {string} path - The path to the image file.
|
|
94
155
|
* @param {Array<number[]>} [colors=[]] - The existing color palette array to append new colors to.
|
|
95
|
-
* @returns {Promise<{frame: number[][], colors: Array<number[]>}>}
|
|
156
|
+
* @returns {Promise<{frame: number[][], colors: Array<number[]>}>} The frame matrix and the updated color palette.
|
|
96
157
|
* @memberof CyberiaObjectLayer
|
|
97
158
|
*/
|
|
98
159
|
static async frameFactory(path, colors = []) {
|
|
@@ -146,10 +207,10 @@ export class ObjectLayerEngine {
|
|
|
146
207
|
}
|
|
147
208
|
|
|
148
209
|
/**
|
|
210
|
+
* Converts a numerical folder direction (e.g., '08', '14') into an array of corresponding keyframe names (e.g., 'down_idle', 'left_walking').
|
|
149
211
|
* @static
|
|
150
|
-
* @description Converts a numerical folder direction (e.g., '08', '14') into an array of corresponding keyframe names (e.g., 'down_idle', 'left_walking').
|
|
151
212
|
* @param {string} direction - The numerical direction string.
|
|
152
|
-
* @returns {string[]}
|
|
213
|
+
* @returns {string[]} An array of keyframe direction names.
|
|
153
214
|
* @memberof CyberiaObjectLayer
|
|
154
215
|
*/
|
|
155
216
|
static getKeyFramesDirectionsFromNumberFolderDirection(direction) {
|
|
@@ -186,14 +247,14 @@ export class ObjectLayerEngine {
|
|
|
186
247
|
}
|
|
187
248
|
|
|
188
249
|
/**
|
|
189
|
-
* @
|
|
190
|
-
* @description Processes an image file through frameFactory and adds the resulting frame to the render data structure.
|
|
250
|
+
* Processes an image file through {@link ObjectLayerEngine.frameFactory} and adds the resulting frame to the render data structure.
|
|
191
251
|
* Updates the color palette and pushes the frame to all keyframe directions corresponding to the given direction code.
|
|
192
252
|
* Initializes colors array, frames object, and direction arrays if they don't exist.
|
|
193
|
-
* @
|
|
253
|
+
* @static
|
|
254
|
+
* @param {ObjectLayerRenderFramesData} objectLayerRenderFramesData - The render data object containing frames and colors.
|
|
194
255
|
* @param {string} imagePath - The path to the image file to process.
|
|
195
256
|
* @param {string} directionCode - The numerical direction code (e.g., '08', '14').
|
|
196
|
-
* @returns {Promise<
|
|
257
|
+
* @returns {Promise<ObjectLayerRenderFramesData>} The updated render data object.
|
|
197
258
|
* @memberof CyberiaObjectLayer
|
|
198
259
|
*/
|
|
199
260
|
static async processAndPushFrame(objectLayerRenderFramesData, imagePath, directionCode) {
|
|
@@ -231,8 +292,8 @@ export class ObjectLayerEngine {
|
|
|
231
292
|
}
|
|
232
293
|
|
|
233
294
|
/**
|
|
295
|
+
* Builds a PNG image file from a tile matrix and color map using Jimp and Sharp.
|
|
234
296
|
* @static
|
|
235
|
-
* @description Builds a PNG image file from a tile matrix and color map using Jimp and Sharp.
|
|
236
297
|
* @param {Object} options - Options object.
|
|
237
298
|
* @param {Object} options.tile - The tile data.
|
|
238
299
|
* @param {Array<number[]>} options.tile.map_color - The color palette.
|
|
@@ -295,9 +356,9 @@ export class ObjectLayerEngine {
|
|
|
295
356
|
}
|
|
296
357
|
|
|
297
358
|
/**
|
|
359
|
+
* Generates a random set of character statistics for an item, with values between 0 and 10.
|
|
298
360
|
* @static
|
|
299
|
-
* @
|
|
300
|
-
* @returns {{effect: number, resistance: number, agility: number, range: number, intelligence: number, utility: number}} - The random stats object.
|
|
361
|
+
* @returns {{effect: number, resistance: number, agility: number, range: number, intelligence: number, utility: number}} The random stats object.
|
|
301
362
|
* @memberof CyberiaObjectLayer
|
|
302
363
|
*/
|
|
303
364
|
static generateRandomStats() {
|
|
@@ -310,22 +371,592 @@ export class ObjectLayerEngine {
|
|
|
310
371
|
utility: random(0, 10),
|
|
311
372
|
};
|
|
312
373
|
}
|
|
374
|
+
|
|
375
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
376
|
+
// Centralized document lifecycle methods
|
|
377
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Scans a local asset directory for PNG frame images and assembles both
|
|
381
|
+
* {@link ObjectLayerRenderFramesData} and {@link ObjectLayerData} from the directory contents
|
|
382
|
+
* and an optional `metadata.json` file.
|
|
383
|
+
*
|
|
384
|
+
* This is the shared first step consumed by both the Cyberia CLI `--import` flow
|
|
385
|
+
* and the REST API service `post` / `put` `/metadata` endpoints.
|
|
386
|
+
*
|
|
387
|
+
* @static
|
|
388
|
+
* @param {Object} params - Parameters.
|
|
389
|
+
* @param {string} params.folder - Absolute or relative path to the asset folder
|
|
390
|
+
* (e.g., `./src/client/public/cyberia/assets/skin/myskin`). Must contain numeric
|
|
391
|
+
* direction sub-folders (`08`, `18`, …) with PNG frame files.
|
|
392
|
+
* @param {string} params.objectLayerType - The item type string (e.g., 'skin', 'floor').
|
|
393
|
+
* @param {string} params.objectLayerId - The item id string.
|
|
394
|
+
* @param {Object} [params.metadataOverride=null] - When provided, used as the authoritative
|
|
395
|
+
* metadata instead of reading `metadata.json` from disk. The REST API passes `req.body`
|
|
396
|
+
* here; the CLI passes `null` so the file is read from disk.
|
|
397
|
+
* @returns {Promise<BuildFromDirectoryResult>} The assembled render frames data and object layer data.
|
|
398
|
+
* @memberof CyberiaObjectLayer
|
|
399
|
+
*/
|
|
400
|
+
static async buildObjectLayerDataFromDirectory({ folder, objectLayerType, objectLayerId, metadataOverride = null }) {
|
|
401
|
+
let metadata = metadataOverride;
|
|
402
|
+
|
|
403
|
+
// If no override was supplied, try to read metadata.json from the folder
|
|
404
|
+
if (!metadata) {
|
|
405
|
+
const metadataPath = `${folder}/metadata.json`;
|
|
406
|
+
if (fs.existsSync(metadataPath)) {
|
|
407
|
+
metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Build objectLayerRenderFramesData
|
|
412
|
+
let objectLayerRenderFramesData;
|
|
413
|
+
if (metadata && metadata.objectLayerRenderFramesData) {
|
|
414
|
+
objectLayerRenderFramesData = {
|
|
415
|
+
frame_duration: metadata.objectLayerRenderFramesData.frame_duration || 250,
|
|
416
|
+
is_stateless: metadata.objectLayerRenderFramesData.is_stateless || false,
|
|
417
|
+
frames: {},
|
|
418
|
+
colors: [],
|
|
419
|
+
};
|
|
420
|
+
} else if (metadata && metadata.data && metadata.data.render) {
|
|
421
|
+
objectLayerRenderFramesData = {
|
|
422
|
+
frame_duration: metadata.data.render.frame_duration || 250,
|
|
423
|
+
is_stateless: metadata.data.render.is_stateless || false,
|
|
424
|
+
frames: {},
|
|
425
|
+
colors: [],
|
|
426
|
+
};
|
|
427
|
+
} else {
|
|
428
|
+
objectLayerRenderFramesData = {
|
|
429
|
+
frame_duration: 250,
|
|
430
|
+
is_stateless: false,
|
|
431
|
+
frames: {},
|
|
432
|
+
colors: [],
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Build objectLayerData
|
|
437
|
+
let objectLayerData;
|
|
438
|
+
if (metadata && metadata.data) {
|
|
439
|
+
objectLayerData = {
|
|
440
|
+
data: {
|
|
441
|
+
item: metadata.data.item || {
|
|
442
|
+
id: objectLayerId,
|
|
443
|
+
type: objectLayerType,
|
|
444
|
+
description: '',
|
|
445
|
+
activable: true,
|
|
446
|
+
},
|
|
447
|
+
stats: metadata.data.stats || ObjectLayerEngine.generateRandomStats(),
|
|
448
|
+
seed: metadata.data.seed || crypto.randomUUID(),
|
|
449
|
+
},
|
|
450
|
+
};
|
|
451
|
+
} else {
|
|
452
|
+
objectLayerData = {
|
|
453
|
+
data: {
|
|
454
|
+
item: {
|
|
455
|
+
id: objectLayerId,
|
|
456
|
+
type: objectLayerType,
|
|
457
|
+
description: '',
|
|
458
|
+
activable: true,
|
|
459
|
+
},
|
|
460
|
+
stats: ObjectLayerEngine.generateRandomStats(),
|
|
461
|
+
seed: crypto.randomUUID(),
|
|
462
|
+
},
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Process all PNG files from direction sub-folders
|
|
467
|
+
if (fs.existsSync(folder)) {
|
|
468
|
+
const directionFolders = await fs.readdir(folder);
|
|
469
|
+
for (const directionCode of directionFolders) {
|
|
470
|
+
const directionPath = `${folder}/${directionCode}`;
|
|
471
|
+
|
|
472
|
+
// Skip non-directories (metadata.json, etc.)
|
|
473
|
+
try {
|
|
474
|
+
const stat = await fs.stat(directionPath);
|
|
475
|
+
if (!stat.isDirectory()) continue;
|
|
476
|
+
} catch (error) {
|
|
477
|
+
logger.warn(`Skipping ${directionCode}: ${error.message}`);
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const frameFiles = await fs.readdir(directionPath);
|
|
482
|
+
// Sort frame files numerically
|
|
483
|
+
frameFiles.sort((a, b) => {
|
|
484
|
+
const numA = parseInt(a.split('.')[0]);
|
|
485
|
+
const numB = parseInt(b.split('.')[0]);
|
|
486
|
+
return numA - numB;
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
for (const frameFile of frameFiles) {
|
|
490
|
+
if (!frameFile.endsWith('.png')) continue;
|
|
491
|
+
|
|
492
|
+
const framePath = `${directionPath}/${frameFile}`;
|
|
493
|
+
await ObjectLayerEngine.processAndPushFrame(objectLayerRenderFramesData, framePath, directionCode);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return { objectLayerRenderFramesData, objectLayerData };
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Computes a SHA-256 hash of the given object layer data using deterministic JSON serialisation.
|
|
503
|
+
* @static
|
|
504
|
+
* @param {Object} data - The `data` sub-document of an ObjectLayer (item, stats, seed, atlasSpriteSheetCid, …).
|
|
505
|
+
* @returns {string} Hex-encoded SHA-256 hash.
|
|
506
|
+
* @memberof CyberiaObjectLayer
|
|
507
|
+
*/
|
|
508
|
+
static computeSha256(data) {
|
|
509
|
+
return crypto.createHash('sha256').update(stringify(data)).digest('hex');
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Map of keyframe direction names to their numeric folder direction codes.
|
|
514
|
+
* Inverse of {@link ObjectLayerEngine.getKeyFramesDirectionsFromNumberFolderDirection}.
|
|
515
|
+
* @static
|
|
516
|
+
* @type {Object<string, string>}
|
|
517
|
+
* @memberof CyberiaObjectLayer
|
|
518
|
+
*/
|
|
519
|
+
static directionNameToCode = {
|
|
520
|
+
down_idle: '08',
|
|
521
|
+
none_idle: '08',
|
|
522
|
+
default_idle: '08',
|
|
523
|
+
up_idle: '02',
|
|
524
|
+
left_idle: '04',
|
|
525
|
+
up_left_idle: '04',
|
|
526
|
+
down_left_idle: '04',
|
|
527
|
+
right_idle: '06',
|
|
528
|
+
up_right_idle: '06',
|
|
529
|
+
down_right_idle: '06',
|
|
530
|
+
down_walking: '18',
|
|
531
|
+
up_walking: '12',
|
|
532
|
+
left_walking: '14',
|
|
533
|
+
up_left_walking: '14',
|
|
534
|
+
down_left_walking: '14',
|
|
535
|
+
right_walking: '16',
|
|
536
|
+
up_right_walking: '16',
|
|
537
|
+
down_right_walking: '16',
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Writes frame PNGs and an optional metadata.json to one or more base asset
|
|
542
|
+
* directories. This is the shared write-to-disk step consumed by both the
|
|
543
|
+
* Cyberia CLI `--generate` / `--import` flows and the REST API service
|
|
544
|
+
* `post` / `put` `/metadata` endpoints.
|
|
545
|
+
*
|
|
546
|
+
* For each base path the layout produced is:
|
|
547
|
+
* ```
|
|
548
|
+
* {basePath}/assets/{itemType}/{itemId}/{directionCode}/{frameIndex}.png
|
|
549
|
+
* {basePath}/assets/{itemType}/{itemId}/metadata.json (optional)
|
|
550
|
+
* ```
|
|
551
|
+
*
|
|
552
|
+
* @static
|
|
553
|
+
* @param {Object} params
|
|
554
|
+
* @param {string[]} params.basePaths - One or more root paths
|
|
555
|
+
* (e.g. `['./src/client/public/cyberia/', './public/host/path/']`).
|
|
556
|
+
* The conventional `assets/` prefix is appended automatically.
|
|
557
|
+
* @param {string} params.itemType - Object layer type ('floor', 'skin', …).
|
|
558
|
+
* @param {string} params.itemId - Unique item identifier.
|
|
559
|
+
* @param {ObjectLayerRenderFramesData} params.objectLayerRenderFramesData
|
|
560
|
+
* - The render frames data containing `frames`, `colors`,
|
|
561
|
+
* `frame_duration` and `is_stateless`.
|
|
562
|
+
* @param {Object} [params.objectLayerData=null] - When provided, a
|
|
563
|
+
* `metadata.json` file is written alongside the frame PNGs.
|
|
564
|
+
* @param {number} [params.cellPixelDim=20] - Pixel size per grid cell.
|
|
565
|
+
* @returns {Promise<string[]>} Flat list of every file path written.
|
|
566
|
+
* @memberof CyberiaObjectLayer
|
|
567
|
+
*/
|
|
568
|
+
static async writeStaticFrameAssets({
|
|
569
|
+
basePaths,
|
|
570
|
+
itemType,
|
|
571
|
+
itemId,
|
|
572
|
+
objectLayerRenderFramesData,
|
|
573
|
+
objectLayerData = null,
|
|
574
|
+
cellPixelDim = 20,
|
|
575
|
+
}) {
|
|
576
|
+
const writtenPaths = [];
|
|
577
|
+
const dirToCode = ObjectLayerEngine.directionNameToCode;
|
|
578
|
+
|
|
579
|
+
for (const basePath of basePaths) {
|
|
580
|
+
// Track which directionCode/frameIndex combos we already wrote for
|
|
581
|
+
// this basePath so duplicate direction names (e.g. down_idle,
|
|
582
|
+
// none_idle, default_idle all map to '08') only write once.
|
|
583
|
+
const written = new Set();
|
|
584
|
+
|
|
585
|
+
for (const [dirName, dirFrames] of Object.entries(objectLayerRenderFramesData.frames)) {
|
|
586
|
+
const code = dirToCode[dirName];
|
|
587
|
+
if (!code) continue;
|
|
588
|
+
|
|
589
|
+
for (let fi = 0; fi < dirFrames.length; fi++) {
|
|
590
|
+
const key = `${code}/${fi}`;
|
|
591
|
+
if (written.has(key)) continue;
|
|
592
|
+
written.add(key);
|
|
593
|
+
|
|
594
|
+
const dirFolder = path.join(basePath, 'assets', itemType, itemId, code);
|
|
595
|
+
await fs.ensureDir(dirFolder);
|
|
596
|
+
|
|
597
|
+
const filePath = path.join(dirFolder, `${fi}.png`);
|
|
598
|
+
|
|
599
|
+
await ObjectLayerEngine.buildImgFromTile({
|
|
600
|
+
tile: {
|
|
601
|
+
map_color: objectLayerRenderFramesData.colors,
|
|
602
|
+
frame_matrix: dirFrames[fi],
|
|
603
|
+
},
|
|
604
|
+
cellPixelDim,
|
|
605
|
+
opacityFilter: (x, y, color) => 255,
|
|
606
|
+
imagePath: filePath,
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
writtenPaths.push(filePath);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// Write metadata.json when objectLayerData is supplied
|
|
614
|
+
if (objectLayerData) {
|
|
615
|
+
const metaDir = path.join(basePath, 'assets', itemType, itemId);
|
|
616
|
+
await fs.ensureDir(metaDir);
|
|
617
|
+
const metadataPath = path.join(metaDir, 'metadata.json');
|
|
618
|
+
|
|
619
|
+
await fs.writeJson(
|
|
620
|
+
metadataPath,
|
|
621
|
+
{
|
|
622
|
+
data: objectLayerData.data,
|
|
623
|
+
objectLayerRenderFramesData: {
|
|
624
|
+
frame_duration: objectLayerRenderFramesData.frame_duration,
|
|
625
|
+
is_stateless: objectLayerRenderFramesData.is_stateless,
|
|
626
|
+
},
|
|
627
|
+
generated: true,
|
|
628
|
+
generatorVersion: '1.0.0',
|
|
629
|
+
},
|
|
630
|
+
{ spaces: 2 },
|
|
631
|
+
);
|
|
632
|
+
writtenPaths.push(metadataPath);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return writtenPaths;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Creates new ObjectLayerRenderFrames and ObjectLayer documents in MongoDB from the
|
|
641
|
+
* provided data, computes an initial SHA-256, and optionally generates the atlas sprite sheet.
|
|
642
|
+
*
|
|
643
|
+
* When `generateAtlas` is `true` (the default) the method delegates to
|
|
644
|
+
* `AtlasSpriteSheetService.generate` and then recomputes the definitive SHA-256
|
|
645
|
+
* (which now includes `data.atlasSpriteSheetCid`) and persists an IPFS CID.
|
|
646
|
+
*
|
|
647
|
+
* @static
|
|
648
|
+
* @param {Object} params - Parameters.
|
|
649
|
+
* @param {Object} params.ObjectLayer - Mongoose ObjectLayer model.
|
|
650
|
+
* @param {Object} params.ObjectLayerRenderFrames - Mongoose ObjectLayerRenderFrames model.
|
|
651
|
+
* @param {ObjectLayerRenderFramesData} params.objectLayerRenderFramesData - Render frames payload.
|
|
652
|
+
* @param {Object} params.objectLayerData - Object layer payload (must include `data`).
|
|
653
|
+
* @param {CreateDocumentsOptions} [params.createOptions={}] - Additional options controlling atlas generation and IPFS pinning.
|
|
654
|
+
* @returns {Promise<CreateDocumentsResult>} The persisted documents.
|
|
655
|
+
* @memberof CyberiaObjectLayer
|
|
656
|
+
*/
|
|
657
|
+
static async createObjectLayerDocuments({
|
|
658
|
+
ObjectLayer,
|
|
659
|
+
ObjectLayerRenderFrames,
|
|
660
|
+
objectLayerRenderFramesData,
|
|
661
|
+
objectLayerData,
|
|
662
|
+
createOptions = {},
|
|
663
|
+
}) {
|
|
664
|
+
const { generateAtlas = true, atlasServiceContext = null } = createOptions;
|
|
665
|
+
|
|
666
|
+
// 1. Persist ObjectLayerRenderFrames
|
|
667
|
+
const objectLayerRenderFramesDoc = await ObjectLayerRenderFrames.create(objectLayerRenderFramesData);
|
|
668
|
+
|
|
669
|
+
// 2. Attach reference + compute temporary SHA-256
|
|
670
|
+
objectLayerData.objectLayerRenderFramesId = objectLayerRenderFramesDoc._id;
|
|
671
|
+
objectLayerData.data.atlasSpriteSheetCid = objectLayerData.data.atlasSpriteSheetCid || '';
|
|
672
|
+
objectLayerData.sha256 = ObjectLayerEngine.computeSha256(objectLayerData.data);
|
|
673
|
+
|
|
674
|
+
// 3. Upsert ObjectLayer (handle duplicate sha256 gracefully)
|
|
675
|
+
let objectLayer;
|
|
676
|
+
const existingObjectLayer = await ObjectLayer.findOne({ sha256: objectLayerData.sha256 });
|
|
677
|
+
if (existingObjectLayer) {
|
|
678
|
+
logger.info(`ObjectLayer with sha256 ${objectLayerData.sha256} already exists, updating...`);
|
|
679
|
+
objectLayer = await ObjectLayer.findByIdAndUpdate(existingObjectLayer._id, objectLayerData, {
|
|
680
|
+
new: true,
|
|
681
|
+
}).populate('objectLayerRenderFramesId');
|
|
682
|
+
} else {
|
|
683
|
+
objectLayer = await (await ObjectLayer.create(objectLayerData)).populate('objectLayerRenderFramesId');
|
|
684
|
+
logger.info(`ObjectLayer created successfully with id: ${objectLayer._id}`);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// 4. Optional atlas generation + final SHA-256 / IPFS CID
|
|
688
|
+
if (generateAtlas && atlasServiceContext) {
|
|
689
|
+
objectLayer = await ObjectLayerEngine._generateAtlasAndFinalize({
|
|
690
|
+
objectLayer,
|
|
691
|
+
ObjectLayer,
|
|
692
|
+
atlasServiceContext,
|
|
693
|
+
isNew: true,
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
return { objectLayer, objectLayerRenderFramesDoc };
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Updates an existing ObjectLayer and its ObjectLayerRenderFrames from the provided data,
|
|
702
|
+
* recomputes SHA-256, and optionally regenerates the atlas sprite sheet.
|
|
703
|
+
*
|
|
704
|
+
* @static
|
|
705
|
+
* @param {Object} params - Parameters.
|
|
706
|
+
* @param {string} params.objectLayerId - The `_id` of the ObjectLayer document to update.
|
|
707
|
+
* @param {Object} params.ObjectLayer - Mongoose ObjectLayer model.
|
|
708
|
+
* @param {Object} params.ObjectLayerRenderFrames - Mongoose ObjectLayerRenderFrames model.
|
|
709
|
+
* @param {ObjectLayerRenderFramesData} params.objectLayerRenderFramesData - Render frames payload.
|
|
710
|
+
* @param {Object} params.objectLayerData - Object layer payload (must include `data`).
|
|
711
|
+
* @param {CreateDocumentsOptions} [params.updateOptions={}] - Additional options controlling atlas generation and IPFS pinning.
|
|
712
|
+
* @returns {Promise<CreateDocumentsResult>} The persisted documents.
|
|
713
|
+
* @memberof CyberiaObjectLayer
|
|
714
|
+
*/
|
|
715
|
+
static async updateObjectLayerDocuments({
|
|
716
|
+
objectLayerId,
|
|
717
|
+
ObjectLayer,
|
|
718
|
+
ObjectLayerRenderFrames,
|
|
719
|
+
objectLayerRenderFramesData,
|
|
720
|
+
objectLayerData,
|
|
721
|
+
updateOptions = {},
|
|
722
|
+
}) {
|
|
723
|
+
const { generateAtlas = true, atlasServiceContext = null } = updateOptions;
|
|
724
|
+
|
|
725
|
+
// 1. Update or create ObjectLayerRenderFrames
|
|
726
|
+
let objectLayerRenderFramesDoc;
|
|
727
|
+
const existingObjectLayer = await ObjectLayer.findById(objectLayerId);
|
|
728
|
+
if (existingObjectLayer && existingObjectLayer.objectLayerRenderFramesId) {
|
|
729
|
+
objectLayerRenderFramesDoc = await ObjectLayerRenderFrames.findByIdAndUpdate(
|
|
730
|
+
existingObjectLayer.objectLayerRenderFramesId,
|
|
731
|
+
objectLayerRenderFramesData,
|
|
732
|
+
{ new: true },
|
|
733
|
+
);
|
|
734
|
+
objectLayerData.objectLayerRenderFramesId = existingObjectLayer.objectLayerRenderFramesId;
|
|
735
|
+
} else {
|
|
736
|
+
objectLayerRenderFramesDoc = await ObjectLayerRenderFrames.create(objectLayerRenderFramesData);
|
|
737
|
+
objectLayerData.objectLayerRenderFramesId = objectLayerRenderFramesDoc._id;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// 2. Compute temporary SHA-256
|
|
741
|
+
objectLayerData.data.atlasSpriteSheetCid = objectLayerData.data.atlasSpriteSheetCid || '';
|
|
742
|
+
objectLayerData.sha256 = ObjectLayerEngine.computeSha256(objectLayerData.data);
|
|
743
|
+
|
|
744
|
+
// 3. Persist ObjectLayer update
|
|
745
|
+
let objectLayer;
|
|
746
|
+
try {
|
|
747
|
+
objectLayer = await ObjectLayer.findByIdAndUpdate(objectLayerId, objectLayerData, {
|
|
748
|
+
new: true,
|
|
749
|
+
}).populate('objectLayerRenderFramesId');
|
|
750
|
+
if (!objectLayer) {
|
|
751
|
+
throw new Error('ObjectLayer not found for update');
|
|
752
|
+
}
|
|
753
|
+
logger.info(`ObjectLayer updated successfully with id: ${objectLayerId}`);
|
|
754
|
+
} catch (error) {
|
|
755
|
+
logger.error('Error updating ObjectLayer:', error);
|
|
756
|
+
throw error;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// 4. Optional atlas generation + final SHA-256 / IPFS CID
|
|
760
|
+
if (generateAtlas && atlasServiceContext) {
|
|
761
|
+
objectLayer = await ObjectLayerEngine._generateAtlasAndFinalize({
|
|
762
|
+
objectLayer,
|
|
763
|
+
ObjectLayer,
|
|
764
|
+
atlasServiceContext,
|
|
765
|
+
isNew: false,
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
return { objectLayer, objectLayerRenderFramesDoc };
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Recomputes the definitive SHA-256, pins the object layer data JSON to IPFS,
|
|
774
|
+
* and persists both fields on the ObjectLayer document.
|
|
775
|
+
*
|
|
776
|
+
* Intended for use after atlas generation has set `data.atlasSpriteSheetCid`.
|
|
777
|
+
*
|
|
778
|
+
* @static
|
|
779
|
+
* @param {Object} params - Parameters.
|
|
780
|
+
* @param {Object} params.objectLayer - The mongoose ObjectLayer document (must be populated).
|
|
781
|
+
* @param {Object} [params.ipfsClient=null] - The IpfsClient module; when `null`, IPFS pinning is skipped.
|
|
782
|
+
* @param {function} [params.createPinRecord=null] - The `createPinRecord` helper; when `null`, pin records are skipped.
|
|
783
|
+
* @param {string} [params.userId] - Authenticated user ID for IPFS pin record creation.
|
|
784
|
+
* @param {Object} [params.options] - Server options (host, path) forwarded to `createPinRecord`.
|
|
785
|
+
* @returns {Promise<Object>} The saved ObjectLayer document.
|
|
786
|
+
* @memberof CyberiaObjectLayer
|
|
787
|
+
*/
|
|
788
|
+
static async computeAndSaveFinalSha256({ objectLayer, ipfsClient = null, createPinRecord = null, userId, options }) {
|
|
789
|
+
const finalSha256 = ObjectLayerEngine.computeSha256(objectLayer.data);
|
|
790
|
+
|
|
791
|
+
if (ipfsClient) {
|
|
792
|
+
try {
|
|
793
|
+
const itemId = objectLayer.data.item.id;
|
|
794
|
+
const ipfsResult = await ipfsClient.addJsonToIpfs(
|
|
795
|
+
objectLayer.data,
|
|
796
|
+
`${itemId}_data.json`,
|
|
797
|
+
`/object-layer/${itemId}/${itemId}_data.json`,
|
|
798
|
+
);
|
|
799
|
+
if (ipfsResult) {
|
|
800
|
+
objectLayer.cid = ipfsResult.cid;
|
|
801
|
+
if (userId && createPinRecord) {
|
|
802
|
+
await createPinRecord({ cid: ipfsResult.cid, userId, options });
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
} catch (ipfsError) {
|
|
806
|
+
logger.warn('Failed to add object layer data to IPFS:', ipfsError.message);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
objectLayer.sha256 = finalSha256;
|
|
811
|
+
objectLayer.markModified('data');
|
|
812
|
+
await objectLayer.save();
|
|
813
|
+
|
|
814
|
+
return objectLayer;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* Internal helper that generates an atlas sprite sheet and then finalizes the SHA-256 / IPFS CID.
|
|
819
|
+
* @static
|
|
820
|
+
* @param {Object} params - Parameters.
|
|
821
|
+
* @param {Object} params.objectLayer - The mongoose ObjectLayer document.
|
|
822
|
+
* @param {Object} params.ObjectLayer - Mongoose ObjectLayer model (for re-reading).
|
|
823
|
+
* @param {Object} params.atlasServiceContext - Context with `{ req, res, options, AtlasSpriteSheetService, IpfsClient, createPinRecord }`.
|
|
824
|
+
* @param {boolean} params.isNew - Whether this is a newly created object layer (used for logging).
|
|
825
|
+
* @returns {Promise<Object>} The finalized ObjectLayer document.
|
|
826
|
+
* @memberof CyberiaObjectLayer
|
|
827
|
+
* @private
|
|
828
|
+
*/
|
|
829
|
+
static async _generateAtlasAndFinalize({ objectLayer, ObjectLayer, atlasServiceContext, isNew }) {
|
|
830
|
+
const { req, res, options, AtlasSpriteSheetService, IpfsClient: ipfsClient, createPinRecord } = atlasServiceContext;
|
|
831
|
+
|
|
832
|
+
// Generate atlas sprite sheet
|
|
833
|
+
try {
|
|
834
|
+
await AtlasSpriteSheetService.generate(
|
|
835
|
+
{ params: { id: objectLayer._id }, objectLayer, auth: req ? req.auth : undefined },
|
|
836
|
+
res,
|
|
837
|
+
options,
|
|
838
|
+
);
|
|
839
|
+
} catch (atlasError) {
|
|
840
|
+
logger.error(`Failed to auto-${isNew ? 'generate' : 'update'} atlas for ObjectLayer:`, atlasError);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// Re-read the objectLayer so data.atlasSpriteSheetCid is up-to-date
|
|
844
|
+
objectLayer = await ObjectLayer.findById(objectLayer._id).populate('objectLayerRenderFramesId');
|
|
845
|
+
|
|
846
|
+
// Compute definitive SHA-256 and IPFS CID
|
|
847
|
+
const userId = req && req.auth && req.auth.user ? req.auth.user._id : undefined;
|
|
848
|
+
objectLayer = await ObjectLayerEngine.computeAndSaveFinalSha256({
|
|
849
|
+
objectLayer,
|
|
850
|
+
ipfsClient: ipfsClient || null,
|
|
851
|
+
createPinRecord: createPinRecord || null,
|
|
852
|
+
userId,
|
|
853
|
+
options,
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
return objectLayer;
|
|
857
|
+
}
|
|
313
858
|
}
|
|
314
859
|
|
|
315
860
|
/**
|
|
861
|
+
* Mapping of item type names to numerical IDs.
|
|
316
862
|
* @constant
|
|
317
|
-
* @description Mapping of item type names to numerical IDs.
|
|
318
863
|
* @type {{floor: number, skin: number, weapon: number, skill: number, coin: number}}
|
|
319
864
|
* @memberof CyberiaObjectLayer
|
|
320
865
|
*/
|
|
321
866
|
export const itemTypes = { floor: 0, skin: 1, weapon: 2, skill: 3, coin: 4 };
|
|
322
867
|
|
|
323
|
-
//
|
|
868
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
869
|
+
// Backward-compatible named exports matching the original destructured imports.
|
|
870
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
* @see {@link ObjectLayerEngine.pngDirectoryIteratorByObjectLayerType}
|
|
874
|
+
* @function pngDirectoryIteratorByObjectLayerType
|
|
875
|
+
* @memberof CyberiaObjectLayer
|
|
876
|
+
*/
|
|
324
877
|
export const pngDirectoryIteratorByObjectLayerType = ObjectLayerEngine.pngDirectoryIteratorByObjectLayerType;
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* @see {@link ObjectLayerEngine.readPngAsync}
|
|
881
|
+
* @function readPngAsync
|
|
882
|
+
* @memberof CyberiaObjectLayer
|
|
883
|
+
*/
|
|
325
884
|
export const readPngAsync = ObjectLayerEngine.readPngAsync;
|
|
885
|
+
|
|
886
|
+
/**
|
|
887
|
+
* @see {@link ObjectLayerEngine.frameFactory}
|
|
888
|
+
* @function frameFactory
|
|
889
|
+
* @memberof CyberiaObjectLayer
|
|
890
|
+
*/
|
|
326
891
|
export const frameFactory = ObjectLayerEngine.frameFactory;
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* @see {@link ObjectLayerEngine.getKeyFramesDirectionsFromNumberFolderDirection}
|
|
895
|
+
* @function getKeyFramesDirectionsFromNumberFolderDirection
|
|
896
|
+
* @memberof CyberiaObjectLayer
|
|
897
|
+
*/
|
|
327
898
|
export const getKeyFramesDirectionsFromNumberFolderDirection =
|
|
328
899
|
ObjectLayerEngine.getKeyFramesDirectionsFromNumberFolderDirection;
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
* @see {@link ObjectLayerEngine.processAndPushFrame}
|
|
903
|
+
* @function processAndPushFrame
|
|
904
|
+
* @memberof CyberiaObjectLayer
|
|
905
|
+
*/
|
|
329
906
|
export const processAndPushFrame = ObjectLayerEngine.processAndPushFrame;
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* @see {@link ObjectLayerEngine.buildImgFromTile}
|
|
910
|
+
* @function buildImgFromTile
|
|
911
|
+
* @memberof CyberiaObjectLayer
|
|
912
|
+
*/
|
|
330
913
|
export const buildImgFromTile = ObjectLayerEngine.buildImgFromTile;
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* @see {@link ObjectLayerEngine.generateRandomStats}
|
|
917
|
+
* @function generateRandomStats
|
|
918
|
+
* @memberof CyberiaObjectLayer
|
|
919
|
+
*/
|
|
331
920
|
export const generateRandomStats = ObjectLayerEngine.generateRandomStats;
|
|
921
|
+
|
|
922
|
+
/**
|
|
923
|
+
* @see {@link ObjectLayerEngine.buildObjectLayerDataFromDirectory}
|
|
924
|
+
* @function buildObjectLayerDataFromDirectory
|
|
925
|
+
* @memberof CyberiaObjectLayer
|
|
926
|
+
*/
|
|
927
|
+
export const buildObjectLayerDataFromDirectory = ObjectLayerEngine.buildObjectLayerDataFromDirectory;
|
|
928
|
+
|
|
929
|
+
/**
|
|
930
|
+
* @see {@link ObjectLayerEngine.computeSha256}
|
|
931
|
+
* @function computeSha256
|
|
932
|
+
* @memberof CyberiaObjectLayer
|
|
933
|
+
*/
|
|
934
|
+
export const computeSha256 = ObjectLayerEngine.computeSha256;
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* @see {@link ObjectLayerEngine.createObjectLayerDocuments}
|
|
938
|
+
* @function createObjectLayerDocuments
|
|
939
|
+
* @memberof CyberiaObjectLayer
|
|
940
|
+
*/
|
|
941
|
+
export const createObjectLayerDocuments = ObjectLayerEngine.createObjectLayerDocuments;
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* @see {@link ObjectLayerEngine.updateObjectLayerDocuments}
|
|
945
|
+
* @function updateObjectLayerDocuments
|
|
946
|
+
* @memberof CyberiaObjectLayer
|
|
947
|
+
*/
|
|
948
|
+
export const updateObjectLayerDocuments = ObjectLayerEngine.updateObjectLayerDocuments;
|
|
949
|
+
|
|
950
|
+
/**
|
|
951
|
+
* @see {@link ObjectLayerEngine.computeAndSaveFinalSha256}
|
|
952
|
+
* @function computeAndSaveFinalSha256
|
|
953
|
+
* @memberof CyberiaObjectLayer
|
|
954
|
+
*/
|
|
955
|
+
export const computeAndSaveFinalSha256 = ObjectLayerEngine.computeAndSaveFinalSha256;
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* @see {@link ObjectLayerEngine.writeStaticFrameAssets}
|
|
959
|
+
* @function writeStaticFrameAssets
|
|
960
|
+
* @memberof CyberiaObjectLayer
|
|
961
|
+
*/
|
|
962
|
+
export const writeStaticFrameAssets = ObjectLayerEngine.writeStaticFrameAssets;
|