cyberia 3.1.3 → 3.2.5
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 +0 -2
- package/.github/workflows/engine-cyberia.cd.yml +10 -8
- package/.github/workflows/engine-cyberia.ci.yml +12 -29
- package/.github/workflows/ghpkg.ci.yml +4 -4
- package/.github/workflows/npmpkg.ci.yml +28 -11
- package/.github/workflows/publish.ci.yml +21 -2
- package/.github/workflows/pwa-microservices-template-page.cd.yml +4 -5
- package/.github/workflows/pwa-microservices-template-test.ci.yml +3 -3
- package/.github/workflows/release.cd.yml +13 -8
- package/CHANGELOG.md +433 -1
- package/CLI-HELP.md +57 -7
- package/Dockerfile +4 -2
- package/README.md +347 -22
- package/bin/build.js +5 -2
- package/bin/cyberia.js +1789 -112
- package/bin/deploy.js +177 -124
- package/bin/file.js +3 -0
- package/bin/index.js +1789 -112
- package/conf.js +64 -8
- package/deployment.yaml +92 -20
- package/hardhat/hardhat.config.js +13 -13
- package/hardhat/ignition/modules/ObjectLayerToken.js +1 -1
- package/hardhat/package-lock.json +2554 -5859
- package/hardhat/package.json +13 -22
- package/hardhat/scripts/deployObjectLayerToken.js +1 -1
- package/hardhat/test/ObjectLayerToken.js +4 -2
- package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
- package/hardhat/types/ethers-contracts/common.ts +92 -0
- package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
- package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
- package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
- package/hardhat/types/ethers-contracts/index.ts +6 -0
- package/jsdoc.dd-cyberia.json +64 -55
- package/jsdoc.json +64 -55
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +5 -4
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +5 -4
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +92 -20
- package/manifests/deployment/dd-cyberia-development/proxy.yaml +54 -18
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +88 -74
- package/manifests/deployment/dd-test-development/proxy.yaml +13 -4
- package/manifests/deployment/playwright/deployment.yaml +1 -1
- package/nodemon.json +1 -1
- package/package.json +22 -16
- package/proxy.yaml +54 -18
- package/scripts/rhel-grpc-setup.sh +56 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +44 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +16 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +80 -7
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +93 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +29 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +51 -0
- package/src/api/cyberia-entity/cyberia-entity.controller.js +74 -0
- package/src/api/cyberia-entity/cyberia-entity.model.js +24 -0
- package/src/api/cyberia-entity/cyberia-entity.router.js +27 -0
- package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +368 -0
- package/src/api/cyberia-instance/cyberia-instance.controller.js +92 -0
- package/src/api/cyberia-instance/cyberia-instance.model.js +84 -0
- package/src/api/cyberia-instance/cyberia-instance.router.js +63 -0
- package/src/api/cyberia-instance/cyberia-instance.service.js +191 -0
- package/src/api/cyberia-instance/cyberia-portal-connector.js +486 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +74 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +413 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +228 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +27 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +42 -0
- package/src/api/cyberia-map/cyberia-map.controller.js +79 -0
- package/src/api/cyberia-map/cyberia-map.model.js +30 -0
- package/src/api/cyberia-map/cyberia-map.router.js +40 -0
- package/src/api/cyberia-map/cyberia-map.service.js +74 -0
- package/src/api/file/file.ref.json +18 -0
- package/src/api/ipfs/ipfs.controller.js +4 -25
- package/src/api/ipfs/ipfs.model.js +43 -34
- package/src/api/ipfs/ipfs.router.js +8 -13
- package/src/api/ipfs/ipfs.service.js +54 -102
- package/src/api/object-layer/README.md +347 -22
- package/src/api/object-layer/object-layer.router.js +30 -0
- package/src/api/object-layer/object-layer.service.js +114 -31
- package/src/api/user/user.service.js +8 -7
- package/src/cli/cluster.js +7 -7
- package/src/cli/db.js +710 -827
- package/src/cli/deploy.js +151 -93
- package/src/cli/env.js +29 -0
- package/src/cli/fs.js +5 -2
- package/src/cli/index.js +48 -2
- package/src/cli/kubectl.js +211 -0
- package/src/cli/release.js +284 -0
- package/src/cli/repository.js +438 -75
- package/src/cli/run.js +195 -35
- package/src/cli/secrets.js +73 -0
- package/src/cli/test.js +3 -3
- package/src/client/Cryptokoyn.index.js +3 -4
- package/src/client/CyberiaPortal.index.js +3 -4
- package/src/client/Default.index.js +3 -4
- package/src/client/Itemledger.index.js +3 -4
- package/src/client/Underpost.index.js +3 -4
- package/src/client/components/core/AppStore.js +69 -0
- package/src/client/components/core/CalendarCore.js +2 -2
- package/src/client/components/core/DropDown.js +137 -17
- package/src/client/components/core/Keyboard.js +2 -2
- package/src/client/components/core/LogIn.js +2 -2
- package/src/client/components/core/LogOut.js +2 -2
- package/src/client/components/core/Modal.js +0 -1
- package/src/client/components/core/Panel.js +0 -1
- package/src/client/components/core/PanelForm.js +19 -19
- package/src/client/components/core/SocketIo.js +82 -29
- package/src/client/components/core/SocketIoHandler.js +75 -0
- package/src/client/components/core/Stream.js +143 -95
- package/src/client/components/core/Webhook.js +40 -7
- package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
- package/src/client/components/cryptokoyn/LogInCryptokoyn.js +3 -3
- package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +2 -2
- package/src/client/components/cryptokoyn/MenuCryptokoyn.js +3 -3
- package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +3 -51
- package/src/client/components/cyberia/InstanceEngineCyberia.js +700 -0
- package/src/client/components/cyberia/MapEngineCyberia.js +1359 -2
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +17 -6
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +92 -54
- package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
- package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +216 -30
- package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +3 -3
- package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +2 -2
- package/src/client/components/cyberia-portal/MenuCyberiaPortal.js +40 -7
- package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +4 -0
- package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +3 -49
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
- package/src/client/components/default/AppStoreDefault.js +5 -0
- package/src/client/components/default/LogInDefault.js +3 -3
- package/src/client/components/default/LogOutDefault.js +2 -2
- package/src/client/components/default/MenuDefault.js +5 -5
- package/src/client/components/default/SocketIoDefault.js +3 -51
- package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
- package/src/client/components/itemledger/LogInItemledger.js +3 -3
- package/src/client/components/itemledger/LogOutItemledger.js +2 -2
- package/src/client/components/itemledger/MenuItemledger.js +3 -3
- package/src/client/components/itemledger/SocketIoItemledger.js +3 -51
- package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
- package/src/client/components/underpost/LogInUnderpost.js +3 -3
- package/src/client/components/underpost/LogOutUnderpost.js +2 -2
- package/src/client/components/underpost/MenuUnderpost.js +5 -5
- package/src/client/components/underpost/SocketIoUnderpost.js +3 -51
- package/src/client/services/core/core.service.js +20 -8
- package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +105 -0
- package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
- package/src/client/services/cyberia-entity/cyberia-entity.service.js +105 -0
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +122 -0
- package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +105 -0
- package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
- package/src/client/services/cyberia-map/cyberia-map.service.js +126 -0
- package/src/client/services/instance/instance.management.js +2 -2
- package/src/client/services/ipfs/ipfs.service.js +3 -23
- package/src/client/services/object-layer/object-layer.management.js +3 -3
- package/src/client/services/object-layer/object-layer.service.js +21 -0
- package/src/client/services/user/user.management.js +2 -2
- package/src/client/ssr/pages/CyberiaServerMetrics.js +1 -1
- package/src/grpc/cyberia/OFF_CHAIN_ECONOMY.md +305 -0
- package/src/grpc/cyberia/README.md +326 -0
- package/src/grpc/cyberia/grpc-server.js +530 -0
- package/src/index.js +24 -1
- package/src/runtime/express/Dockerfile +4 -0
- package/src/runtime/express/Express.js +18 -1
- package/src/runtime/lampp/Dockerfile +13 -2
- package/src/runtime/lampp/Lampp.js +27 -4
- package/src/runtime/wp/Dockerfile +68 -0
- package/src/runtime/wp/Wp.js +639 -0
- package/src/server/auth.js +24 -1
- package/src/server/backup.js +37 -9
- package/src/server/client-build-docs.js +9 -2
- package/src/server/client-build.js +31 -31
- package/src/server/client-formatted.js +109 -57
- package/src/server/conf.js +24 -9
- package/src/server/cron.js +25 -23
- package/src/server/dns.js +2 -1
- package/src/server/ipfs-client.js +24 -1
- package/src/server/object-layer.js +149 -108
- package/src/server/peer.js +8 -0
- package/src/server/runtime.js +25 -1
- package/src/server/semantic-layer-generator-floor.js +359 -0
- package/src/server/semantic-layer-generator-skin.js +1294 -0
- package/src/server/semantic-layer-generator.js +116 -555
- package/src/server/start.js +2 -2
- package/src/ws/IoInterface.js +1 -10
- package/src/ws/IoServer.js +14 -33
- package/src/ws/core/channels/core.ws.chat.js +65 -20
- package/src/ws/core/channels/core.ws.mailer.js +113 -32
- package/src/ws/core/channels/core.ws.stream.js +90 -31
- package/src/ws/core/core.ws.connection.js +12 -33
- package/src/ws/core/core.ws.emit.js +10 -26
- package/src/ws/core/core.ws.server.js +25 -58
- package/src/ws/default/channels/default.ws.main.js +53 -12
- package/src/ws/default/default.ws.connection.js +26 -13
- package/src/ws/default/default.ws.server.js +30 -12
- package/src/client/components/cryptokoyn/CommonCryptokoyn.js +0 -29
- package/src/client/components/cryptokoyn/ElementsCryptokoyn.js +0 -38
- package/src/client/components/cyberia-portal/ElementsCyberiaPortal.js +0 -38
- package/src/client/components/default/ElementsDefault.js +0 -38
- package/src/client/components/itemledger/CommonItemledger.js +0 -29
- package/src/client/components/itemledger/ElementsItemledger.js +0 -38
- package/src/client/components/underpost/CommonUnderpost.js +0 -29
- package/src/client/components/underpost/ElementsUnderpost.js +0 -38
- package/src/ws/core/management/core.ws.chat.js +0 -8
- package/src/ws/core/management/core.ws.mailer.js +0 -16
- package/src/ws/core/management/core.ws.stream.js +0 -8
- package/src/ws/default/management/default.ws.main.js +0 -8
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Schema, model } from 'mongoose';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Directed edge in a graph.
|
|
5
|
+
* Each portal represents an adjacency relation:
|
|
6
|
+
* source node -> target node
|
|
7
|
+
*/
|
|
8
|
+
const PortalEdgeSchema = new Schema(
|
|
9
|
+
{
|
|
10
|
+
// Origin node (graph source vertex)
|
|
11
|
+
sourceMapCode: { type: String, required: true, trim: true },
|
|
12
|
+
sourceCellX: { type: Number },
|
|
13
|
+
sourceCellY: { type: Number },
|
|
14
|
+
|
|
15
|
+
// Destination node (graph target vertex)
|
|
16
|
+
targetMapCode: { type: String, required: true, trim: true },
|
|
17
|
+
targetCellX: { type: Number },
|
|
18
|
+
targetCellY: { type: Number },
|
|
19
|
+
|
|
20
|
+
// Transport behaviour of this edge:
|
|
21
|
+
// inter-portal — teleport to a portal entity on another map
|
|
22
|
+
// inter-random — teleport to a random walkable cell on another map
|
|
23
|
+
// intra-random — teleport to a random walkable cell on the same map
|
|
24
|
+
// intra-portal — teleport to a portal entity on the same map
|
|
25
|
+
portalMode: {
|
|
26
|
+
type: String,
|
|
27
|
+
enum: ['inter-portal', 'inter-random', 'intra-random', 'intra-portal'],
|
|
28
|
+
default: 'inter-portal',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{ _id: false },
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Graph container / instance.
|
|
36
|
+
* The instance stores:
|
|
37
|
+
* - nodes: cyberiaMapCodes[]
|
|
38
|
+
* - edges: portals[]
|
|
39
|
+
*/
|
|
40
|
+
const CyberiaInstanceSchema = new Schema(
|
|
41
|
+
{
|
|
42
|
+
// Instance identifier
|
|
43
|
+
code: { type: String, default: '', trim: true, unique: true },
|
|
44
|
+
|
|
45
|
+
name: { type: String, default: '', trim: true },
|
|
46
|
+
description: { type: String, default: '' },
|
|
47
|
+
tags: { type: [String], default: [] },
|
|
48
|
+
creator: { type: Schema.Types.ObjectId, ref: 'User' },
|
|
49
|
+
status: { type: String, default: 'unlisted' },
|
|
50
|
+
thumbnail: { type: Schema.Types.ObjectId, ref: 'File' },
|
|
51
|
+
|
|
52
|
+
// Vertex set of the graph
|
|
53
|
+
cyberiaMapCodes: { type: [String], default: [] },
|
|
54
|
+
|
|
55
|
+
// Directed edge set of the graph
|
|
56
|
+
portals: { type: [PortalEdgeSchema], default: [] },
|
|
57
|
+
|
|
58
|
+
// Optional topology generation mode
|
|
59
|
+
seed: { type: String, default: '' },
|
|
60
|
+
topologyMode: {
|
|
61
|
+
type: String,
|
|
62
|
+
enum: ['manual', 'procedural', 'hybrid'],
|
|
63
|
+
default: 'hybrid',
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
// Game server configuration (all tuning parameters live in a separate document).
|
|
67
|
+
// Linked to CyberiaInstanceConf.instanceCode === this.code.
|
|
68
|
+
conf: { type: Schema.Types.ObjectId, ref: 'CyberiaInstanceConf' },
|
|
69
|
+
},
|
|
70
|
+
{ timestamps: true },
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Indexes for fast adjacency lookups.
|
|
75
|
+
* Useful for traversing the graph by source or target node.
|
|
76
|
+
*/
|
|
77
|
+
CyberiaInstanceSchema.index({ 'portals.sourceMapCode': 1 });
|
|
78
|
+
CyberiaInstanceSchema.index({ 'portals.targetMapCode': 1 });
|
|
79
|
+
|
|
80
|
+
const CyberiaInstanceModel = model('CyberiaInstance', CyberiaInstanceSchema);
|
|
81
|
+
|
|
82
|
+
const ProviderSchema = CyberiaInstanceSchema;
|
|
83
|
+
|
|
84
|
+
export { CyberiaInstanceSchema, CyberiaInstanceModel, ProviderSchema };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { loggerFactory } from '../../server/logger.js';
|
|
2
|
+
import { CyberiaInstanceController } from './cyberia-instance.controller.js';
|
|
3
|
+
import { userGuard, adminGuard } from '../../server/auth.js';
|
|
4
|
+
import express from 'express';
|
|
5
|
+
|
|
6
|
+
const logger = loggerFactory(import.meta);
|
|
7
|
+
|
|
8
|
+
const CyberiaInstanceRouter = (options) => {
|
|
9
|
+
const router = express.Router();
|
|
10
|
+
const authMiddleware = options.authMiddleware;
|
|
11
|
+
// ── Custom actions (must come before generic /:id routes) ──────────────
|
|
12
|
+
router.get(`/fallback-world`, async (req, res) => await CyberiaInstanceController.fallbackWorld(req, res, options));
|
|
13
|
+
router.get(
|
|
14
|
+
`/:id/portal-connect`,
|
|
15
|
+
authMiddleware,
|
|
16
|
+
userGuard,
|
|
17
|
+
async (req, res) => await CyberiaInstanceController.portalConnect(req, res, options),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
router.post(
|
|
21
|
+
`/:id`,
|
|
22
|
+
authMiddleware,
|
|
23
|
+
userGuard,
|
|
24
|
+
async (req, res) => await CyberiaInstanceController.post(req, res, options),
|
|
25
|
+
);
|
|
26
|
+
router.post(
|
|
27
|
+
`/`,
|
|
28
|
+
authMiddleware,
|
|
29
|
+
userGuard,
|
|
30
|
+
async (req, res) => await CyberiaInstanceController.post(req, res, options),
|
|
31
|
+
);
|
|
32
|
+
router.get(`/:id`, async (req, res) => await CyberiaInstanceController.get(req, res, options));
|
|
33
|
+
router.get(`/`, async (req, res) => await CyberiaInstanceController.get(req, res, options));
|
|
34
|
+
router.put(
|
|
35
|
+
`/:id`,
|
|
36
|
+
authMiddleware,
|
|
37
|
+
userGuard,
|
|
38
|
+
async (req, res) => await CyberiaInstanceController.put(req, res, options),
|
|
39
|
+
);
|
|
40
|
+
router.put(
|
|
41
|
+
`/`,
|
|
42
|
+
authMiddleware,
|
|
43
|
+
userGuard,
|
|
44
|
+
async (req, res) => await CyberiaInstanceController.put(req, res, options),
|
|
45
|
+
);
|
|
46
|
+
router.delete(
|
|
47
|
+
`/:id`,
|
|
48
|
+
authMiddleware,
|
|
49
|
+
userGuard,
|
|
50
|
+
async (req, res) => await CyberiaInstanceController.delete(req, res, options),
|
|
51
|
+
);
|
|
52
|
+
router.delete(
|
|
53
|
+
`/`,
|
|
54
|
+
authMiddleware,
|
|
55
|
+
adminGuard,
|
|
56
|
+
async (req, res) => await CyberiaInstanceController.delete(req, res, options),
|
|
57
|
+
);
|
|
58
|
+
return router;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const ApiRouter = CyberiaInstanceRouter;
|
|
62
|
+
|
|
63
|
+
export { ApiRouter, CyberiaInstanceRouter };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { DataBaseProvider } from '../../db/DataBaseProvider.js';
|
|
2
|
+
import { loggerFactory } from '../../server/logger.js';
|
|
3
|
+
import { DataQuery } from '../../server/data-query.js';
|
|
4
|
+
import { connectPortals, generateProceduralEntities } from './cyberia-portal-connector.js';
|
|
5
|
+
import { generateFallbackWorld } from './cyberia-fallback-world.js';
|
|
6
|
+
import { CYBERIA_INSTANCE_CONF_DEFAULTS } from '../cyberia-instance-conf/cyberia-instance-conf.defaults.js';
|
|
7
|
+
|
|
8
|
+
const logger = loggerFactory(import.meta);
|
|
9
|
+
|
|
10
|
+
const CyberiaInstanceService = {
|
|
11
|
+
post: async (req, res, options) => {
|
|
12
|
+
/** @type {import('./cyberia-instance.model.js').CyberiaInstanceModel} */
|
|
13
|
+
const CyberiaInstance = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaInstance;
|
|
14
|
+
const CyberiaInstanceConf =
|
|
15
|
+
DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaInstanceConf;
|
|
16
|
+
if (req.auth && req.auth.user) req.body.creator = req.auth.user._id;
|
|
17
|
+
const instance = await new CyberiaInstance(req.body).save();
|
|
18
|
+
|
|
19
|
+
// Auto-upsert a CyberiaInstanceConf for this instance using schema defaults.
|
|
20
|
+
// $setOnInsert ensures existing conf documents are never overwritten.
|
|
21
|
+
if (instance.code && CyberiaInstanceConf) {
|
|
22
|
+
try {
|
|
23
|
+
const conf = await CyberiaInstanceConf.findOneAndUpdate(
|
|
24
|
+
{ instanceCode: instance.code },
|
|
25
|
+
{ $setOnInsert: { instanceCode: instance.code } },
|
|
26
|
+
{ upsert: true, new: true },
|
|
27
|
+
);
|
|
28
|
+
if (conf && !instance.conf) {
|
|
29
|
+
await CyberiaInstance.findByIdAndUpdate(instance._id, { conf: conf._id });
|
|
30
|
+
instance.conf = conf._id;
|
|
31
|
+
}
|
|
32
|
+
} catch (e) {
|
|
33
|
+
logger.error('auto-upsert CyberiaInstanceConf failed:', e);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return instance;
|
|
38
|
+
},
|
|
39
|
+
get: async (req, res, options) => {
|
|
40
|
+
/** @type {import('./cyberia-instance.model.js').CyberiaInstanceModel} */
|
|
41
|
+
const CyberiaInstance = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaInstance;
|
|
42
|
+
const populateCreator = { path: 'creator', model: 'User', select: '_id username' };
|
|
43
|
+
if (req.params.id) return await CyberiaInstance.findById(req.params.id).populate(populateCreator);
|
|
44
|
+
|
|
45
|
+
// Parse query parameters using DataQuery helper
|
|
46
|
+
const { query, sort, skip, limit, page } = DataQuery.parse(req.query);
|
|
47
|
+
|
|
48
|
+
const [data, total] = await Promise.all([
|
|
49
|
+
CyberiaInstance.find(query).sort(sort).limit(limit).skip(skip).populate(populateCreator),
|
|
50
|
+
CyberiaInstance.countDocuments(query),
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
const totalPages = Math.ceil(total / limit);
|
|
54
|
+
return { data, total, page, totalPages };
|
|
55
|
+
},
|
|
56
|
+
put: async (req, res, options) => {
|
|
57
|
+
/** @type {import('./cyberia-instance.model.js').CyberiaInstanceModel} */
|
|
58
|
+
const CyberiaInstance = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaInstance;
|
|
59
|
+
const instance = await CyberiaInstance.findById(req.params.id);
|
|
60
|
+
if (!instance) throw new Error('instance not found');
|
|
61
|
+
if (req.auth.user.role !== 'admin' && String(instance.creator) !== String(req.auth.user._id))
|
|
62
|
+
throw new Error('insufficient permission');
|
|
63
|
+
if (req.body.thumbnail && instance.thumbnail && String(req.body.thumbnail) !== String(instance.thumbnail)) {
|
|
64
|
+
const File = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.File;
|
|
65
|
+
await File.findByIdAndDelete(instance.thumbnail);
|
|
66
|
+
}
|
|
67
|
+
return await CyberiaInstance.findByIdAndUpdate(req.params.id, req.body, { returnDocument: 'after' });
|
|
68
|
+
},
|
|
69
|
+
/**
|
|
70
|
+
* Central portal connector endpoint.
|
|
71
|
+
*
|
|
72
|
+
* Delegates topology computation to the pure-function `connectPortals()`
|
|
73
|
+
* from cyberia-portal-connector.js so the same logic can be used by the
|
|
74
|
+
* GUI without a DB dependency.
|
|
75
|
+
*
|
|
76
|
+
* Optionally generates procedural fallback obstacle/foreground entities
|
|
77
|
+
* for maps that have none, controlled by query flags:
|
|
78
|
+
* ?generateEntities=true — append procedural obstacles & foreground
|
|
79
|
+
* ?obstacleCount=N — obstacles per map (default 5)
|
|
80
|
+
* ?foregroundCount=N — foreground per map (default 3)
|
|
81
|
+
* ?persist=true — save generated portals & entities to DB
|
|
82
|
+
*/
|
|
83
|
+
portalConnect: async (req, res, options) => {
|
|
84
|
+
const CyberiaInstance = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaInstance;
|
|
85
|
+
const CyberiaMap = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaMap;
|
|
86
|
+
|
|
87
|
+
const instance = await CyberiaInstance.findById(req.params.id).lean();
|
|
88
|
+
if (!instance) throw new Error('instance not found');
|
|
89
|
+
|
|
90
|
+
const mapCodes = instance.cyberiaMapCodes || [];
|
|
91
|
+
|
|
92
|
+
// Load maps with the fields needed by the connector.
|
|
93
|
+
const mapDocs = await CyberiaMap.find(
|
|
94
|
+
{ code: { $in: mapCodes } },
|
|
95
|
+
{
|
|
96
|
+
code: 1,
|
|
97
|
+
gridX: 1,
|
|
98
|
+
gridY: 1,
|
|
99
|
+
entities: 1,
|
|
100
|
+
},
|
|
101
|
+
).lean();
|
|
102
|
+
|
|
103
|
+
// ── Portal topology (pure function) ──────────────────────────────────
|
|
104
|
+
const result = connectPortals(mapCodes, mapDocs);
|
|
105
|
+
|
|
106
|
+
// ── Procedural entity generation (optional) ──────────────────────────
|
|
107
|
+
const colors = CYBERIA_INSTANCE_CONF_DEFAULTS.colors;
|
|
108
|
+
const wantEntities = req.query?.generateEntities === 'true';
|
|
109
|
+
const obstacleCount = req.query?.obstacleCount ? parseInt(req.query.obstacleCount, 10) : undefined;
|
|
110
|
+
const foregroundCount = req.query?.foregroundCount ? parseInt(req.query.foregroundCount, 10) : undefined;
|
|
111
|
+
const seed = instance.seed || '';
|
|
112
|
+
|
|
113
|
+
const generatedEntities = {};
|
|
114
|
+
if (wantEntities) {
|
|
115
|
+
for (const doc of mapDocs) {
|
|
116
|
+
const hasObstacles = (doc.entities || []).some((e) => e.entityType === 'obstacle');
|
|
117
|
+
const hasForeground = (doc.entities || []).some((e) => e.entityType === 'foreground');
|
|
118
|
+
if (!hasObstacles || !hasForeground) {
|
|
119
|
+
const mapSeed = seed ? `${seed}:${doc.code}` : doc.code;
|
|
120
|
+
const generated = generateProceduralEntities({ gridX: doc.gridX || 16, gridY: doc.gridY || 16 }, colors, {
|
|
121
|
+
obstacleCount,
|
|
122
|
+
foregroundCount,
|
|
123
|
+
seed: mapSeed,
|
|
124
|
+
});
|
|
125
|
+
generatedEntities[doc.code] = {
|
|
126
|
+
obstacles: hasObstacles ? [] : generated.obstacles,
|
|
127
|
+
foreground: hasForeground ? [] : generated.foreground,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ── Persist to DB when requested ─────────────────────────────────────
|
|
134
|
+
const persist = req.query?.persist === 'true';
|
|
135
|
+
if (persist) {
|
|
136
|
+
await CyberiaInstance.findByIdAndUpdate(req.params.id, { portals: result.portals });
|
|
137
|
+
for (const [mapCode, ents] of Object.entries(generatedEntities)) {
|
|
138
|
+
const toAdd = [...ents.obstacles, ...ents.foreground];
|
|
139
|
+
if (toAdd.length > 0) {
|
|
140
|
+
await CyberiaMap.findOneAndUpdate({ code: mapCode }, { $push: { entities: { $each: toAdd } } });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
...result,
|
|
147
|
+
...(wantEntities ? { generatedEntities } : {}),
|
|
148
|
+
persisted: persist,
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
delete: async (req, res, options) => {
|
|
153
|
+
/** @type {import('./cyberia-instance.model.js').CyberiaInstanceModel} */
|
|
154
|
+
const CyberiaInstance = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaInstance;
|
|
155
|
+
if (req.params.id) {
|
|
156
|
+
const instance = await CyberiaInstance.findById(req.params.id);
|
|
157
|
+
if (!instance) throw new Error('instance not found');
|
|
158
|
+
if (req.auth.user.role !== 'admin' && String(instance.creator) !== String(req.auth.user._id))
|
|
159
|
+
throw new Error('insufficient permission');
|
|
160
|
+
if (instance.thumbnail) {
|
|
161
|
+
const File = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.File;
|
|
162
|
+
await File.findByIdAndDelete(instance.thumbnail);
|
|
163
|
+
}
|
|
164
|
+
return await CyberiaInstance.findByIdAndDelete(req.params.id);
|
|
165
|
+
} else return await CyberiaInstance.deleteMany();
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Return an in-memory procedural fallback world.
|
|
170
|
+
*
|
|
171
|
+
* Nothing is persisted to MongoDB. The world is regenerated on every
|
|
172
|
+
* call but stays deterministic for a given seed.
|
|
173
|
+
*
|
|
174
|
+
* Query params:
|
|
175
|
+
* ?mapCount=<number> — maps to generate (default: 4)
|
|
176
|
+
* ?botCount=<number> — bots per map (random 8–16 if omitted)
|
|
177
|
+
* ?obstacleCount=<number> — obstacles per map (random 12–20 if omitted)
|
|
178
|
+
* ?foregroundCount=<number>— foreground per map (random 6–12 if omitted)
|
|
179
|
+
*/
|
|
180
|
+
fallbackWorld: async (req) => {
|
|
181
|
+
const q = req.query || {};
|
|
182
|
+
return generateFallbackWorld({
|
|
183
|
+
mapCount: q.mapCount ? parseInt(q.mapCount, 10) : undefined,
|
|
184
|
+
botCount: q.botCount ? parseInt(q.botCount, 10) : undefined,
|
|
185
|
+
obstacleCount: q.obstacleCount ? parseInt(q.obstacleCount, 10) : undefined,
|
|
186
|
+
foregroundCount: q.foregroundCount ? parseInt(q.foregroundCount, 10) : undefined,
|
|
187
|
+
});
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export { CyberiaInstanceService };
|