cyberia 3.2.9 → 3.2.22
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 +7 -0
- package/.github/workflows/engine-cyberia.ci.yml +14 -2
- package/.github/workflows/ghpkg.ci.yml +1 -0
- package/.github/workflows/npmpkg.ci.yml +10 -5
- package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
- package/.github/workflows/release.cd.yml +1 -0
- package/.vscode/extensions.json +9 -9
- package/.vscode/settings.json +20 -4
- package/CHANGELOG.md +363 -1
- package/CLI-HELP.md +975 -1061
- package/README.md +190 -348
- package/bin/build.js +102 -125
- package/bin/build.template.js +33 -0
- package/bin/cyberia.js +238 -56
- package/bin/deploy.js +16 -3
- package/bin/index.js +238 -56
- package/bump.config.js +26 -0
- package/conf.js +131 -24
- package/deployment.yaml +76 -2
- package/hardhat/package-lock.json +113 -144
- package/hardhat/package.json +4 -3
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +2 -2
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +76 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/kind-config-dev.yaml +8 -0
- package/manifests/lxd/lxd-admin-profile.yaml +12 -3
- package/manifests/mongodb/pv-pvc.yaml +44 -8
- package/manifests/mongodb/statefulset.yaml +55 -68
- package/manifests/mongodb-4.4/headless-service.yaml +10 -0
- package/manifests/mongodb-4.4/kustomization.yaml +3 -1
- package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
- package/manifests/mongodb-4.4/pv-pvc.yaml +10 -14
- package/manifests/mongodb-4.4/statefulset.yaml +79 -0
- package/manifests/mongodb-4.4/storage-class.yaml +9 -0
- package/manifests/valkey/statefulset.yaml +1 -1
- package/manifests/valkey/valkey-nodeport.yaml +17 -0
- package/package.json +31 -19
- package/scripts/ipxe-setup.sh +52 -49
- package/scripts/k3s-node-setup.sh +81 -46
- package/scripts/link-local-underpost-cli.sh +6 -0
- package/scripts/lxd-vm-setup.sh +193 -8
- package/scripts/maas-nat-firewalld.sh +145 -0
- package/scripts/test-monitor.sh +250 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +38 -33
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +16 -16
- package/src/api/core/core.router.js +19 -14
- package/src/api/core/core.service.js +5 -5
- package/src/api/crypto/crypto.router.js +18 -12
- package/src/api/crypto/crypto.service.js +3 -3
- package/src/api/cyberia-action/cyberia-action.model.js +1 -1
- package/src/api/cyberia-action/cyberia-action.router.js +22 -18
- package/src/api/cyberia-action/cyberia-action.service.js +5 -5
- package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +74 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +99 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +98 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +152 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +25 -20
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +6 -6
- package/src/api/cyberia-entity/cyberia-entity.router.js +22 -18
- package/src/api/cyberia-entity/cyberia-entity.service.js +5 -5
- package/src/api/cyberia-instance/cyberia-fallback-world.js +79 -4
- package/src/api/cyberia-instance/cyberia-instance.router.js +57 -52
- package/src/api/cyberia-instance/cyberia-instance.service.js +10 -10
- package/src/api/cyberia-instance/cyberia-world-generator.js +3 -3
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +14 -48
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +22 -18
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +5 -5
- package/src/api/cyberia-map/cyberia-map.router.js +35 -30
- package/src/api/cyberia-map/cyberia-map.service.js +7 -7
- package/src/api/cyberia-quest/cyberia-quest.model.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.router.js +22 -18
- package/src/api/cyberia-quest/cyberia-quest.service.js +5 -5
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +22 -18
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +5 -5
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +458 -0
- package/src/api/default/default.router.js +22 -18
- package/src/api/default/default.service.js +5 -5
- package/src/api/document/document.router.js +28 -23
- package/src/api/document/document.service.js +100 -23
- package/src/api/file/file.router.js +19 -13
- package/src/api/file/file.service.js +9 -7
- package/src/api/instance/instance.router.js +29 -24
- package/src/api/instance/instance.service.js +6 -6
- package/src/api/ipfs/ipfs.router.js +21 -16
- package/src/api/ipfs/ipfs.service.js +8 -8
- package/src/api/object-layer/object-layer.router.js +512 -507
- package/src/api/object-layer/object-layer.service.js +17 -14
- package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +22 -18
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +5 -5
- package/src/api/test/test.router.js +17 -12
- package/src/api/types.js +24 -0
- package/src/api/user/guest.service.js +5 -4
- package/src/api/user/user.router.js +297 -288
- package/src/api/user/user.service.js +100 -35
- package/src/cli/baremetal.js +132 -101
- package/src/cli/cluster.js +700 -232
- package/src/cli/db.js +59 -60
- package/src/cli/deploy.js +291 -294
- package/src/cli/env.js +1 -4
- package/src/cli/fs.js +13 -3
- package/src/cli/image.js +58 -4
- package/src/cli/index.js +127 -15
- package/src/cli/ipfs.js +4 -6
- package/src/cli/kubectl.js +4 -1
- package/src/cli/lxd.js +1099 -223
- package/src/cli/monitor.js +396 -9
- package/src/cli/release.js +355 -146
- package/src/cli/repository.js +169 -30
- package/src/cli/run.js +347 -117
- package/src/cli/secrets.js +11 -2
- package/src/cli/test.js +9 -3
- package/src/client/Default.index.js +9 -3
- package/src/client/components/core/Auth.js +5 -0
- package/src/client/components/core/ClientEvents.js +76 -0
- package/src/client/components/core/EventBus.js +4 -0
- package/src/client/components/core/Modal.js +82 -41
- package/src/client/components/core/PanelForm.js +14 -10
- package/src/client/components/core/Worker.js +162 -363
- package/src/client/components/cyberia/MapEngineCyberia.js +1 -1
- package/src/client/components/cyberia/SharedDefaultsCyberia.js +330 -0
- package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +55 -1
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +223 -361
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +114 -327
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +200 -222
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +212 -185
- package/src/client/public/cyberia-docs/CYBERIA.md +259 -0
- package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +2 -2
- package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +23 -1
- package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
- package/src/client/public/cyberia-docs/UNDERPOST-PLATFORM.md +106 -0
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
- package/src/client/services/cyberia-client-hints/cyberia-client-hints.service.js +99 -0
- package/src/client/ssr/views/CyberiaServerMetrics.js +982 -0
- package/src/client/sw/core.sw.js +174 -112
- package/src/db/DataBaseProvider.js +115 -15
- package/src/db/mariadb/MariaDB.js +2 -1
- package/src/db/mongo/MongoBootstrap.js +657 -0
- package/src/db/mongo/MongooseDB.js +130 -21
- package/src/grpc/cyberia/grpc-server.js +25 -57
- package/src/index.js +1 -1
- package/src/runtime/cyberia-client/Dockerfile +10 -7
- package/src/runtime/cyberia-client/Dockerfile.dev +67 -0
- package/src/runtime/cyberia-server/Dockerfile +11 -6
- package/src/runtime/cyberia-server/Dockerfile.dev +47 -0
- package/src/runtime/express/Express.js +2 -2
- package/src/runtime/wp/Dockerfile +3 -3
- package/src/runtime/wp/Wp.js +8 -5
- package/src/server/auth.js +2 -2
- package/src/server/catalog-underpost.js +61 -0
- package/src/server/catalog.js +77 -0
- package/src/server/client-build-docs.js +1 -1
- package/src/server/client-build.js +94 -129
- package/src/server/conf.js +496 -135
- package/src/server/ipfs-client.js +5 -3
- package/src/server/process.js +180 -19
- package/src/server/proxy.js +9 -2
- package/src/server/runtime-status.js +235 -0
- package/src/server/runtime.js +1 -1
- package/src/server/start.js +44 -11
- package/src/server/valkey.js +2 -0
- package/src/ws/IoInterface.js +16 -16
- package/src/ws/core/channels/core.ws.chat.js +11 -11
- package/src/ws/core/channels/core.ws.mailer.js +29 -29
- package/src/ws/core/channels/core.ws.stream.js +19 -19
- package/src/ws/core/core.ws.connection.js +8 -8
- package/src/ws/core/core.ws.server.js +6 -5
- package/src/ws/default/channels/default.ws.main.js +10 -10
- package/src/ws/default/default.ws.connection.js +4 -4
- package/src/ws/default/default.ws.server.js +4 -3
- package/test/deploy-monitor.test.js +251 -0
- package/bin/file.js +0 -202
- package/bin/vs.js +0 -74
- package/bin/zed.js +0 -84
- package/manifests/deployment/dd-test-development/deployment.yaml +0 -254
- package/manifests/deployment/dd-test-development/proxy.yaml +0 -102
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +0 -574
- package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +0 -467
- package/src/client/ssr/email/DefaultRecoverEmail.js +0 -21
- package/src/client/ssr/email/DefaultVerifyEmail.js +0 -17
- package/src/client/ssr/pages/CyberiaServerMetrics.js +0 -461
- /package/src/client/ssr/{offline → views}/Maintenance.js +0 -0
- /package/src/client/ssr/{offline → views}/NoNetworkConnection.js +0 -0
- /package/src/client/ssr/{pages → views}/Test.js +0 -0
|
@@ -4,24 +4,28 @@ import express from 'express';
|
|
|
4
4
|
|
|
5
5
|
const logger = loggerFactory(import.meta);
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
router
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
async (req, res) => await CyberiaQuestProgressController.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
7
|
+
class CyberiaQuestProgressRouter {
|
|
8
|
+
/**
|
|
9
|
+
* @param {import('../types.js').RouterOptions} options
|
|
10
|
+
* @returns {import('express').Router}
|
|
11
|
+
*/
|
|
12
|
+
static router(options) {
|
|
13
|
+
const router = express.Router();
|
|
14
|
+
router.post(`/:id`, async (req, res) => await CyberiaQuestProgressController.post(req, res, options));
|
|
15
|
+
router.post(`/`, async (req, res) => await CyberiaQuestProgressController.post(req, res, options));
|
|
16
|
+
router.get(`/:id`,
|
|
17
|
+
// options.authMiddleware,
|
|
18
|
+
async (req, res) => await CyberiaQuestProgressController.get(req, res, options),
|
|
19
|
+
);
|
|
20
|
+
router.get(`/`, async (req, res) => await CyberiaQuestProgressController.get(req, res, options));
|
|
21
|
+
router.put(`/:id`, async (req, res) => await CyberiaQuestProgressController.put(req, res, options));
|
|
22
|
+
router.put(`/`, async (req, res) => await CyberiaQuestProgressController.put(req, res, options));
|
|
23
|
+
router.delete(`/:id`, async (req, res) => await CyberiaQuestProgressController.delete(req, res, options));
|
|
24
|
+
router.delete(`/`, async (req, res) => await CyberiaQuestProgressController.delete(req, res, options));
|
|
25
|
+
return router;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
24
28
|
|
|
25
|
-
const ApiRouter = CyberiaQuestProgressRouter;
|
|
29
|
+
const ApiRouter = (options) => CyberiaQuestProgressRouter.router(options);
|
|
26
30
|
|
|
27
31
|
export { ApiRouter, CyberiaQuestProgressRouter };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DataBaseProviderService } from '../../db/DataBaseProvider.js';
|
|
2
2
|
import { loggerFactory } from '../../server/logger.js';
|
|
3
3
|
import { DataQuery } from '../../server/data-query.js';
|
|
4
4
|
|
|
@@ -7,12 +7,12 @@ const logger = loggerFactory(import.meta);
|
|
|
7
7
|
class CyberiaQuestProgressService {
|
|
8
8
|
static post = async (req, res, options) => {
|
|
9
9
|
/** @type {import('./cyberia-quest-progress.model.js').CyberiaQuestProgressModel} */
|
|
10
|
-
const CyberiaQuestProgress =
|
|
10
|
+
const CyberiaQuestProgress = DataBaseProviderService.getModel("CyberiaQuestProgress", options);
|
|
11
11
|
return await new CyberiaQuestProgress(req.body).save();
|
|
12
12
|
};
|
|
13
13
|
static get = async (req, res, options) => {
|
|
14
14
|
/** @type {import('./cyberia-quest-progress.model.js').CyberiaQuestProgressModel} */
|
|
15
|
-
const CyberiaQuestProgress =
|
|
15
|
+
const CyberiaQuestProgress = DataBaseProviderService.getModel("CyberiaQuestProgress", options);
|
|
16
16
|
if (req.params.id) return await CyberiaQuestProgress.findById(req.params.id);
|
|
17
17
|
|
|
18
18
|
// Parse query parameters using DataQuery helper
|
|
@@ -28,12 +28,12 @@ class CyberiaQuestProgressService {
|
|
|
28
28
|
};
|
|
29
29
|
static put = async (req, res, options) => {
|
|
30
30
|
/** @type {import('./cyberia-quest-progress.model.js').CyberiaQuestProgressModel} */
|
|
31
|
-
const CyberiaQuestProgress =
|
|
31
|
+
const CyberiaQuestProgress = DataBaseProviderService.getModel("CyberiaQuestProgress", options);
|
|
32
32
|
return await CyberiaQuestProgress.findByIdAndUpdate(req.params.id, req.body);
|
|
33
33
|
};
|
|
34
34
|
static delete = async (req, res, options) => {
|
|
35
35
|
/** @type {import('./cyberia-quest-progress.model.js').CyberiaQuestProgressModel} */
|
|
36
|
-
const CyberiaQuestProgress =
|
|
36
|
+
const CyberiaQuestProgress = DataBaseProviderService.getModel("CyberiaQuestProgress", options);
|
|
37
37
|
if (req.params.id) return await CyberiaQuestProgress.findByIdAndDelete(req.params.id);
|
|
38
38
|
else return await CyberiaQuestProgress.deleteMany();
|
|
39
39
|
};
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical server-owned defaults for the Cyberia runtime.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for everything the **authoritative simulation
|
|
5
|
+
* server** (cyberia-server, Go) needs to build and run a world:
|
|
6
|
+
*
|
|
7
|
+
* - per-entity-type live / dead / drop item configuration
|
|
8
|
+
* - simulation, AOI, combat, economy, and skill rules
|
|
9
|
+
* - equipment rules
|
|
10
|
+
* - status-icon **numeric IDs** (visuals live in client defaults)
|
|
11
|
+
* - seed content (dialogues, actions, quests) consumed by the
|
|
12
|
+
* persistence/CLI tooling that bootstraps the world
|
|
13
|
+
* - native-dependency pin list for chain-bridge tooling
|
|
14
|
+
*
|
|
15
|
+
* STRICT BOUNDARY
|
|
16
|
+
* ---------------
|
|
17
|
+
* NEVER imported from any file under `src/client/`. The browser bundler
|
|
18
|
+
* resolves imports recursively, so a single browser-side import would drag
|
|
19
|
+
* the entire simulation defaults into the public JS payload.
|
|
20
|
+
*
|
|
21
|
+
* Shared content **vocabulary** (item/entity type enums, the
|
|
22
|
+
* `DefaultCyberiaItems` registry, `ENTITY_TYPE_TO_ITEM_TYPES`, quest /
|
|
23
|
+
* action enums) lives in `SharedDefaultsCyberia.js`. This file
|
|
24
|
+
* re-imports those so the browser editor never needs to reach into
|
|
25
|
+
* server-defaults to learn the schema.
|
|
26
|
+
*
|
|
27
|
+
* Consumers:
|
|
28
|
+
* - cyberia-instance-conf model + grpc-server (gameplay config)
|
|
29
|
+
* - cyberia-world-generator / cyberia-fallback-world (world build)
|
|
30
|
+
* - cyberia-quest / cyberia-action / Mongo seed scripts (content)
|
|
31
|
+
* - bin/cyberia + bin/build + bin/deploy (CLI + chain bridge)
|
|
32
|
+
*
|
|
33
|
+
* @module src/api/cyberia-server-defaults/cyberia-server-defaults.js
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
// The canonical client-defaults module lives under src/client/ so the
|
|
37
|
+
// browser bundler can resolve the URL inside the client tree. Engine-side
|
|
38
|
+
// Node imports work from any path, so we reach into it from here.
|
|
39
|
+
import { ITEM_TYPES, ENTITY_TYPES } from '../../client/components/cyberia/SharedDefaultsCyberia.js';
|
|
40
|
+
|
|
41
|
+
// Re-export the shared vocabulary so existing server-side imports keep
|
|
42
|
+
// working without each consumer having to know which module owns which.
|
|
43
|
+
export {
|
|
44
|
+
ITEM_TYPES,
|
|
45
|
+
ENTITY_TYPES,
|
|
46
|
+
ENTITY_TYPE_TO_ITEM_TYPES,
|
|
47
|
+
QUEST_STEPS_TYPES,
|
|
48
|
+
CYBERIA_ACTION_TYPES,
|
|
49
|
+
DefaultCyberiaItems,
|
|
50
|
+
getDefaultCyberiaItemById,
|
|
51
|
+
getDefaultCyberiaItemsByItemType,
|
|
52
|
+
getDefaultCyberiaItemsByEntityType,
|
|
53
|
+
} from '../../client/components/cyberia/SharedDefaultsCyberia.js';
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Native-dependency pin list. Consumed by `bin/build.js` and `bin/deploy.js`
|
|
57
|
+
* when materialising the Cyberia subtree so versions stay reproducible
|
|
58
|
+
* across CI / production deploys.
|
|
59
|
+
*/
|
|
60
|
+
export class CyberiaDependencies {
|
|
61
|
+
static 'maxrects-packer' = '^2.7.3';
|
|
62
|
+
static pngjs = '^7.0.0';
|
|
63
|
+
static jimp = '^1.6.0';
|
|
64
|
+
static sharp = '^0.34.5';
|
|
65
|
+
static ethers = '~6.16.0';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
69
|
+
// Skill / action / quest seed content
|
|
70
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Compact `triggerItemId → logicEventIds[]` table. The engine expands each
|
|
74
|
+
* entry into a richer skill record in CYBERIA_INSTANCE_CONF_DEFAULTS below.
|
|
75
|
+
*/
|
|
76
|
+
export const DefaultSkillConfig = [
|
|
77
|
+
{ triggerItemId: 'atlas_pistol_mk2', logicEventIds: ['projectile'] },
|
|
78
|
+
{ triggerItemId: 'coin', logicEventIds: ['coin_drop_or_transaction'] },
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Default dialogue seeds. Mirrors `CyberiaDialogue` model schema:
|
|
83
|
+
* { code, order, speaker, text, mood }
|
|
84
|
+
*
|
|
85
|
+
* Used by the seed/migration script to populate Mongo on first boot.
|
|
86
|
+
*/
|
|
87
|
+
export const DefaultCyberiaDialogues = [
|
|
88
|
+
{ code: 'default-coin', order: 0, speaker: 'Coin', text: 'A standard unit of exchange in the cyberia network.', mood: 'neutral' },
|
|
89
|
+
{ code: 'default-atlas_pistol_mk2', order: 0, speaker: 'Atlas Pistol MK2', text: 'Military-grade sidearm. Fires energy projectiles.', mood: 'neutral' },
|
|
90
|
+
{ code: 'default-atlas_pistol_mk2_bullet', order: 0, speaker: 'MK2 Bullet', text: 'High-velocity energy round. Dissipates on impact.', mood: 'neutral' },
|
|
91
|
+
{ code: 'default-hatchet', order: 0, speaker: 'Hatchet', text: 'A crude but reliable melee tool. Good for close quarters.', mood: 'neutral' },
|
|
92
|
+
{ code: 'default-wason', order: 0, speaker: 'Wason', text: 'They say I am just a wandering merchant... but I have seen things.', mood: 'neutral' },
|
|
93
|
+
{ code: 'default-wason', order: 1, speaker: 'Wason', text: 'The network was not always like this. There was a time before the portals.', mood: 'sad' },
|
|
94
|
+
{ code: 'default-scp-2040', order: 0, speaker: 'SCP-2040', text: 'CONTAINMENT PROTOCOL ACTIVE. Do not make direct eye contact.', mood: 'angry' },
|
|
95
|
+
{ code: 'default-scp-2040', order: 1, speaker: 'SCP-2040', text: 'I remember everything. Every iteration. Every reset.', mood: 'sad' },
|
|
96
|
+
{ code: 'default-purple', order: 0, speaker: 'Purple', text: 'The void between nodes is not empty — it is alive.', mood: 'neutral' },
|
|
97
|
+
{ code: 'default-punk', order: 0, speaker: 'Punk', text: 'Rules are just code someone else wrote. I write my own.', mood: 'happy' },
|
|
98
|
+
{ code: 'default-lain', order: 0, speaker: 'Lain', text: 'No matter where you go, everyone is connected.', mood: 'neutral' },
|
|
99
|
+
{ code: 'default-lain', order: 1, speaker: 'Lain', text: 'If you are not remembered, then you never existed.', mood: 'sad' },
|
|
100
|
+
{ code: 'default-lain', order: 2, speaker: 'Lain', text: 'The wired is not a separate world. It is layered over this one.', mood: 'neutral' },
|
|
101
|
+
{ code: 'default-kaneki', order: 0, speaker: 'Kaneki', text: 'I am not the protagonist of a novel. I am just... me.', mood: 'sad' },
|
|
102
|
+
{ code: 'default-kaneki', order: 1, speaker: 'Kaneki', text: 'What is 1000 minus 7?', mood: 'angry' },
|
|
103
|
+
{ code: 'default-junko', order: 0, speaker: 'Junko', text: 'Despair is the seed from which hope blooms!', mood: 'happy' },
|
|
104
|
+
{ code: 'default-junko', order: 1, speaker: 'Junko', text: 'How boring... nothing ever surprises me anymore.', mood: 'sad' },
|
|
105
|
+
{ code: 'default-ghost', order: 0, speaker: 'Ghost', text: '...', mood: 'neutral' },
|
|
106
|
+
{ code: 'default-eiri', order: 0, speaker: 'Eiri', text: 'I am the god of the wired. I designed the protocol.', mood: 'neutral' },
|
|
107
|
+
{ code: 'default-eiri', order: 1, speaker: 'Eiri', text: 'Flesh is just hardware. Consciousness is the only software that matters.', mood: 'neutral' },
|
|
108
|
+
{ code: 'default-anon', order: 0, speaker: '???', text: 'You should not be here. Turn back.', mood: 'angry' },
|
|
109
|
+
{ code: 'default-anon', order: 1, speaker: '???', text: 'Or stay. It does not matter. Nothing leaves this place.', mood: 'neutral' },
|
|
110
|
+
{ code: 'default-alex', order: 0, speaker: 'Alex', text: 'I have been mapping the portal network. Something does not add up.', mood: 'neutral' },
|
|
111
|
+
{ code: 'default-alex', order: 1, speaker: 'Alex', text: 'There are nodes that exist in the registry but have no physical anchor.', mood: 'neutral' },
|
|
112
|
+
{ code: 'default-agent', order: 0, speaker: 'Agent', text: 'Civilian, this area is restricted. State your business.', mood: 'neutral' },
|
|
113
|
+
{ code: 'default-agent', order: 1, speaker: 'Agent', text: 'Hmm. Proceed, but know that you are being watched.', mood: 'neutral' },
|
|
114
|
+
{ code: 'default-grass', order: 0, speaker: 'Grass', text: 'A patch of synthetic grass. It sways gently despite no wind.', mood: 'neutral' },
|
|
115
|
+
{ code: 'quest-talk-wason', order: 0, speaker: 'Wason', text: 'Wanderer! Glad you stopped by. I need a favor — nothing dangerous... mostly.', mood: 'happy' },
|
|
116
|
+
{ code: 'quest-talk-wason', order: 1, speaker: 'Wason', text: "First, find Alex — she's been surveying the nodes east of here. Then gather a hatchet for me.", mood: 'neutral' },
|
|
117
|
+
{ code: 'quest-talk-wason', order: 2, speaker: 'Wason', text: 'And one more thing: the SCP-2040 anomalies are overrunning my trade routes. Deal with two of them.', mood: 'sad' },
|
|
118
|
+
{ code: 'quest-talk-alex', order: 0, speaker: 'Alex', text: "Wason sent you? Good. The portal anomalies are getting worse. I've logged what I can.", mood: 'neutral' },
|
|
119
|
+
{ code: 'quest-talk-alex', order: 1, speaker: 'Alex', text: 'Tell Wason: the source is somewhere in the deeper nodes. The registry does not lie.', mood: 'neutral' },
|
|
120
|
+
{ code: 'talk-lain', order: 0, speaker: 'Lain', text: 'Present day... present time. You are here, so you are real.', mood: 'neutral' },
|
|
121
|
+
{ code: 'talk-lain', order: 1, speaker: 'Lain', text: 'There is nothing I can grant you. Only the wired remembers.', mood: 'neutral' },
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Default action catalog — drives NPC interaction overlays and quest grants.
|
|
126
|
+
* Each entry follows the `CyberiaAction` model schema.
|
|
127
|
+
*/
|
|
128
|
+
export const DefaultCyberiaActions = [
|
|
129
|
+
{
|
|
130
|
+
code: 'wason-quest-intro', type: 'quest-talk', label: 'Quest',
|
|
131
|
+
provideItemId: 'wason', grantQuestCode: 'fallback-intro-quest',
|
|
132
|
+
dialogCode: 'quest-talk-wason', questDialogueCodes: ['quest-talk-wason'],
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
code: 'alex-quest-talk', type: 'quest-talk', label: 'Quest Talk',
|
|
136
|
+
provideItemId: 'alex', grantQuestCode: '',
|
|
137
|
+
dialogCode: 'quest-talk-alex', questDialogueCodes: ['quest-talk-alex'],
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
code: 'agent-mission-brief', type: 'quest-talk', label: 'Mission Brief',
|
|
141
|
+
provideItemId: 'agent', grantQuestCode: 'bounty-quest-alpha',
|
|
142
|
+
dialogCode: 'default-agent', questDialogueCodes: ['default-agent'],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
code: 'wason-bounty-brief', type: 'quest-talk', label: 'Bounty Brief',
|
|
146
|
+
provideItemId: 'wason', grantQuestCode: '',
|
|
147
|
+
dialogCode: 'quest-talk-wason', questDialogueCodes: ['quest-talk-wason'],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
code: 'lain-talk', type: 'talk', label: 'Talk',
|
|
151
|
+
provideItemId: 'lain', grantQuestCode: '',
|
|
152
|
+
dialogCode: 'talk-lain', questDialogueCodes: ['talk-lain'],
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Default quest definitions for the fallback world. Mirrors `CyberiaQuest`
|
|
158
|
+
* schema. Objective types: 'talk' | 'collect' | 'kill'.
|
|
159
|
+
*/
|
|
160
|
+
export const DefaultCyberiaQuests = [
|
|
161
|
+
{
|
|
162
|
+
code: 'fallback-intro-quest',
|
|
163
|
+
title: "The Wanderer's Task",
|
|
164
|
+
description: 'Help Wason restore order to the fractured nodes.',
|
|
165
|
+
prerequisiteCodes: [],
|
|
166
|
+
unlocksQuestCodes: ['bounty-quest-alpha'],
|
|
167
|
+
steps: [
|
|
168
|
+
{ id: 'step-talk-alex', description: 'Find Alex and hear her report on the portal anomalies.',
|
|
169
|
+
objectives: [{ type: 'talk', itemId: 'alex', quantity: 1 }] },
|
|
170
|
+
{ id: 'step-collect-hatchet', description: 'Obtain a hatchet for Wason.',
|
|
171
|
+
objectives: [{ type: 'collect', itemId: 'hatchet', quantity: 1 }] },
|
|
172
|
+
{ id: 'step-kill-scp', description: 'Eliminate SCP-2040 anomalies threatening the trade routes.',
|
|
173
|
+
objectives: [{ type: 'kill', itemId: 'scp-2040', quantity: 2 }] },
|
|
174
|
+
],
|
|
175
|
+
rewards: [{ itemId: 'coin', quantity: 50 }],
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
code: 'bounty-quest-alpha',
|
|
179
|
+
title: 'Alpha Bounty',
|
|
180
|
+
description: 'A field test: eliminate a threat, claim your reward, then report back.',
|
|
181
|
+
prerequisiteCodes: ['fallback-intro-quest'],
|
|
182
|
+
unlocksQuestCodes: [],
|
|
183
|
+
steps: [
|
|
184
|
+
{ id: 'step-kill-first', description: 'Eliminate the SCP-2040 threat.',
|
|
185
|
+
objectives: [{ type: 'kill', itemId: 'scp-2040', quantity: 1 }] },
|
|
186
|
+
{ id: 'step-collect-reward', description: 'Collect the bounty coin drop.',
|
|
187
|
+
objectives: [{ type: 'collect', itemId: 'coin', quantity: 10 }] },
|
|
188
|
+
{ id: 'step-report-wason', description: 'Report back to Wason.',
|
|
189
|
+
objectives: [{ type: 'talk', itemId: 'wason', quantity: 1 }] },
|
|
190
|
+
],
|
|
191
|
+
rewards: [{ itemId: 'hatchet', quantity: 1 }],
|
|
192
|
+
},
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
196
|
+
// Equipment rules
|
|
197
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Governs which ObjectLayer item types may be simultaneously active on an
|
|
201
|
+
* entity and enforces the one-per-type constraint. The server validates
|
|
202
|
+
* every item_activation request against these rules.
|
|
203
|
+
*/
|
|
204
|
+
export const EQUIPMENT_RULES_DEFAULTS = Object.freeze({
|
|
205
|
+
activeItemTypes: [ITEM_TYPES.skin, ITEM_TYPES.breastplate, ITEM_TYPES.weapon],
|
|
206
|
+
onePerType: true,
|
|
207
|
+
requireSkin: true,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
211
|
+
// Entity Status Indicators (server-side numeric table)
|
|
212
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Numeric Entity Status Indicator (ESI) IDs. The Go server stamps one of
|
|
216
|
+
* these u8 IDs on every entity in the AOI binary wire format; the client
|
|
217
|
+
* resolves the icon stem + border colour from its own presentation
|
|
218
|
+
* defaults table (see `SharedDefaultsCyberia.js#STATUS_ICONS_PRESENTATION`).
|
|
219
|
+
*
|
|
220
|
+
* IDs MUST stay in sync with:
|
|
221
|
+
* cyberia-server/src/entity_status.go (StatusNone … StatusResourceExtracted)
|
|
222
|
+
*/
|
|
223
|
+
export const STATUS_ICONS = Object.freeze([
|
|
224
|
+
{ id: 0, name: 'none', description: 'No icon (skill/coin bots, world objects)' },
|
|
225
|
+
{ id: 1, name: 'passive', description: 'Passive bot — no weapon, non-aggressive' },
|
|
226
|
+
{ id: 2, name: 'hostile', description: 'Hostile bot — has weapon, will aggro' },
|
|
227
|
+
{ id: 3, name: 'frozen', description: 'Player in FrozenInteractionState (modal open)' },
|
|
228
|
+
{ id: 4, name: 'player', description: 'Normal player — alive, not frozen' },
|
|
229
|
+
{ id: 5, name: 'dead', description: 'Entity is dead / respawning' },
|
|
230
|
+
{ id: 6, name: 'resource', description: 'Resource entity — static, exploitable (wood, minerals, etc.)' },
|
|
231
|
+
{ id: 7, name: 'resource-extracted', description: 'Resource entity extracted/depleted (dead state)' },
|
|
232
|
+
{ id: 8, name: 'action-provider', description: 'Bot with available quest-talk/shop/storage/craft actions' },
|
|
233
|
+
]);
|
|
234
|
+
|
|
235
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
236
|
+
// Per-entity-type defaults (simulation-side only — no presentation here)
|
|
237
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Resource entity variants. Each declares the live / extracted / drop item
|
|
241
|
+
* triplet the simulation rotates through when a resource is depleted.
|
|
242
|
+
*/
|
|
243
|
+
export const RESOURCE_ENTITY_TYPE_DEFAULTS = Object.freeze([
|
|
244
|
+
Object.freeze({
|
|
245
|
+
entityType: ENTITY_TYPES.resource,
|
|
246
|
+
liveItemIds: ['wood-1'],
|
|
247
|
+
deadItemIds: ['wood-extracted-1'],
|
|
248
|
+
dropItemIds: ['wood-drop-1'],
|
|
249
|
+
defaultObjectLayers: [],
|
|
250
|
+
}),
|
|
251
|
+
Object.freeze({
|
|
252
|
+
entityType: ENTITY_TYPES.resource,
|
|
253
|
+
liveItemIds: ['wood-2'],
|
|
254
|
+
deadItemIds: ['wood-extracted-2'],
|
|
255
|
+
dropItemIds: ['wood-drop-2'],
|
|
256
|
+
defaultObjectLayers: [],
|
|
257
|
+
}),
|
|
258
|
+
]);
|
|
259
|
+
|
|
260
|
+
/** Convenience alias — first variant, used by single-resource fallbacks. */
|
|
261
|
+
export const RESOURCE_ENTITY_TYPE_DEFAULT = RESOURCE_ENTITY_TYPE_DEFAULTS[0];
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Per-entity-type defaults consumed by the Go server (live / dead / drop
|
|
265
|
+
* item IDs and the seed inventory for newly spawned entities).
|
|
266
|
+
*
|
|
267
|
+
* Field reference:
|
|
268
|
+
* entityType — server-side category string.
|
|
269
|
+
* liveItemIds — ObjectLayer item IDs while the entity is alive.
|
|
270
|
+
* deadItemIds — IDs swapped in on death / ghost state.
|
|
271
|
+
* dropItemIds — IDs granted to the killer on resource depletion.
|
|
272
|
+
* defaultObjectLayers — initial inventory rows ({itemId, active, qty}).
|
|
273
|
+
*/
|
|
274
|
+
export const ENTITY_TYPE_DEFAULTS = Object.freeze([
|
|
275
|
+
{
|
|
276
|
+
entityType: ENTITY_TYPES.player,
|
|
277
|
+
liveItemIds: ['anon', 'atlas_pistol_mk2'],
|
|
278
|
+
deadItemIds: ['ghost'],
|
|
279
|
+
defaultObjectLayers: [
|
|
280
|
+
{ itemId: 'anon', active: true, quantity: 1 },
|
|
281
|
+
{ itemId: 'atlas_pistol_mk2', active: true, quantity: 1 },
|
|
282
|
+
{ itemId: 'ghost', active: false, quantity: 1 },
|
|
283
|
+
{ itemId: 'coin', active: false, quantity: 0 },
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
entityType: ENTITY_TYPES.other_player,
|
|
288
|
+
liveItemIds: ['anon', 'atlas_pistol_mk2'],
|
|
289
|
+
deadItemIds: ['ghost'],
|
|
290
|
+
defaultObjectLayers: [
|
|
291
|
+
{ itemId: 'anon', active: true, quantity: 1 },
|
|
292
|
+
{ itemId: 'atlas_pistol_mk2', active: true, quantity: 1 },
|
|
293
|
+
{ itemId: 'ghost', active: false, quantity: 1 },
|
|
294
|
+
{ itemId: 'coin', active: false, quantity: 0 },
|
|
295
|
+
],
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
entityType: ENTITY_TYPES.bot,
|
|
299
|
+
liveItemIds: ['purple'],
|
|
300
|
+
deadItemIds: ['ghost'],
|
|
301
|
+
defaultObjectLayers: [
|
|
302
|
+
{ itemId: 'purple', active: true, quantity: 1 },
|
|
303
|
+
{ itemId: 'coin', active: false, quantity: 0 },
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
entityType: ENTITY_TYPES.skill,
|
|
308
|
+
liveItemIds: ['atlas_pistol_mk2_bullet'],
|
|
309
|
+
deadItemIds: [],
|
|
310
|
+
defaultObjectLayers: [{ itemId: 'atlas_pistol_mk2_bullet', active: true, quantity: 1 }],
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
entityType: ENTITY_TYPES.coin,
|
|
314
|
+
liveItemIds: ['coin'],
|
|
315
|
+
deadItemIds: [],
|
|
316
|
+
defaultObjectLayers: [{ itemId: 'coin', active: true, quantity: 1 }],
|
|
317
|
+
},
|
|
318
|
+
{ entityType: ENTITY_TYPES.floor, liveItemIds: ['grass'], deadItemIds: [], dropItemIds: [], defaultObjectLayers: [] },
|
|
319
|
+
{ entityType: ENTITY_TYPES.obstacle, liveItemIds: [], deadItemIds: [], dropItemIds: [], defaultObjectLayers: [] },
|
|
320
|
+
{ entityType: ENTITY_TYPES.portal, liveItemIds: [], deadItemIds: [], dropItemIds: [], defaultObjectLayers: [] },
|
|
321
|
+
{ entityType: ENTITY_TYPES.foreground, liveItemIds: [], deadItemIds: [], dropItemIds: [], defaultObjectLayers: [] },
|
|
322
|
+
...RESOURCE_ENTITY_TYPE_DEFAULTS,
|
|
323
|
+
]);
|
|
324
|
+
|
|
325
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
326
|
+
// Instance-level simulation configuration
|
|
327
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Canonical default Cyberia instance configuration consumed by the gRPC
|
|
331
|
+
* `InstanceConfig` payload. ONLY gameplay-affecting values live here.
|
|
332
|
+
*
|
|
333
|
+
* Anything that does not influence the authoritative simulation (cell-pixel
|
|
334
|
+
* size, camera tunings, palette, interpolation window, render flags) is
|
|
335
|
+
* forbidden — see `SharedDefaultsCyberia.js` and the
|
|
336
|
+
* `/api/cyberia-client-hints` REST endpoint for presentation overrides.
|
|
337
|
+
*/
|
|
338
|
+
export const CYBERIA_INSTANCE_CONF_DEFAULTS = {
|
|
339
|
+
// ── Tick model ─────────────────────────────────────────────────────
|
|
340
|
+
tickRate: 60,
|
|
341
|
+
snapshotRate: 20,
|
|
342
|
+
|
|
343
|
+
// ── World / AOI ────────────────────────────────────────────────────
|
|
344
|
+
aoiRadius: 10,
|
|
345
|
+
portalHoldTimeMs: 1000,
|
|
346
|
+
portalSpawnRadius: 3,
|
|
347
|
+
|
|
348
|
+
// ── Entity base stats ──────────────────────────────────────────────
|
|
349
|
+
entityBaseSpeed: 5,
|
|
350
|
+
entityBaseMaxLife: 100,
|
|
351
|
+
entityBaseActionCooldownMs: 500,
|
|
352
|
+
entityBaseMinActionCooldownMs: 100,
|
|
353
|
+
|
|
354
|
+
// ── Bot defaults ───────────────────────────────────────────────────
|
|
355
|
+
botAggroRange: 10,
|
|
356
|
+
|
|
357
|
+
// ── Player defaults ────────────────────────────────────────────────
|
|
358
|
+
defaultPlayerWidth: 2,
|
|
359
|
+
defaultPlayerHeight: 2,
|
|
360
|
+
playerBaseLifeRegenMin: 0.5,
|
|
361
|
+
playerBaseLifeRegenMax: 1.5,
|
|
362
|
+
sumStatsLimit: 500,
|
|
363
|
+
maxActiveLayers: 4,
|
|
364
|
+
initialLifeFraction: 1.0,
|
|
365
|
+
|
|
366
|
+
// ── Combat / death ─────────────────────────────────────────────────
|
|
367
|
+
respawnDurationMs: 3000,
|
|
368
|
+
collisionLifeLoss: 10,
|
|
369
|
+
|
|
370
|
+
// ── Economy — Fountain & Sink model ────────────────────────────────
|
|
371
|
+
economyRules: {
|
|
372
|
+
botSpawnCoins: 50,
|
|
373
|
+
playerSpawnCoins: 50,
|
|
374
|
+
coinKillPercentVsBot: 0.4,
|
|
375
|
+
coinKillPercentVsPlayer: 0.15,
|
|
376
|
+
coinKillMinAmount: 10,
|
|
377
|
+
respawnCostPercent: 0.0,
|
|
378
|
+
portalFee: 0,
|
|
379
|
+
craftingFeePercent: 0.0,
|
|
380
|
+
},
|
|
381
|
+
|
|
382
|
+
// ── Regen ──────────────────────────────────────────────────────────
|
|
383
|
+
lifeRegenChance: 300,
|
|
384
|
+
maxChance: 10000,
|
|
385
|
+
|
|
386
|
+
// ── Per-entity-type defaults ───────────────────────────────────────
|
|
387
|
+
entityDefaults: ENTITY_TYPE_DEFAULTS.map((e) => ({ ...e })),
|
|
388
|
+
|
|
389
|
+
// ── Status icons (numeric IDs only — visuals live in client defaults) ──
|
|
390
|
+
statusIcons: STATUS_ICONS.map((s) => ({ ...s })),
|
|
391
|
+
|
|
392
|
+
// ── Skill system ───────────────────────────────────────────────────
|
|
393
|
+
skillConfig: [
|
|
394
|
+
{
|
|
395
|
+
triggerItemId: 'atlas_pistol_mk2',
|
|
396
|
+
skills: [
|
|
397
|
+
{
|
|
398
|
+
logicEventId: 'projectile',
|
|
399
|
+
name: 'Projectile',
|
|
400
|
+
description:
|
|
401
|
+
'Fires a projectile in the direction of the tap. Spawn chance and lifetime scale with Intelligence and Range.',
|
|
402
|
+
summonedEntityItemId: 'atlas_pistol_mk2_bullet',
|
|
403
|
+
},
|
|
404
|
+
],
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
triggerItemId: 'coin',
|
|
408
|
+
skills: [
|
|
409
|
+
{
|
|
410
|
+
logicEventId: 'coin_drop_or_transaction',
|
|
411
|
+
name: 'Coin Drop',
|
|
412
|
+
description:
|
|
413
|
+
'Coins are dropped automatically when an entity is killed. Transfer amount scales with kill percent rules.',
|
|
414
|
+
summonedEntityItemId: 'coin',
|
|
415
|
+
},
|
|
416
|
+
],
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
triggerItemId: 'anon',
|
|
420
|
+
skills: [
|
|
421
|
+
{
|
|
422
|
+
logicEventId: 'doppelganger',
|
|
423
|
+
name: 'Doppelganger',
|
|
424
|
+
description:
|
|
425
|
+
'Summons a passive clone of yourself that wanders nearby. Spawn chance scales with Intelligence.',
|
|
426
|
+
summonedEntityItemId: '$active_skin',
|
|
427
|
+
},
|
|
428
|
+
],
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
triggerItemId: 'hatchet',
|
|
432
|
+
skills: [
|
|
433
|
+
{
|
|
434
|
+
logicEventId: 'projectile',
|
|
435
|
+
name: 'Projectile',
|
|
436
|
+
description:
|
|
437
|
+
'Fires a projectile in the direction of the tap. Spawn chance and lifetime scale with Intelligence and Range.',
|
|
438
|
+
summonedEntityItemId: 'hatchet-skill',
|
|
439
|
+
},
|
|
440
|
+
],
|
|
441
|
+
},
|
|
442
|
+
],
|
|
443
|
+
|
|
444
|
+
skillRules: {
|
|
445
|
+
projectileSpawnChance: 0.5,
|
|
446
|
+
projectileLifetimeMs: 2000,
|
|
447
|
+
projectileWidth: 1,
|
|
448
|
+
projectileHeight: 1,
|
|
449
|
+
projectileSpeedMultiplier: 3,
|
|
450
|
+
doppelgangerSpawnChance: 0.5,
|
|
451
|
+
doppelgangerLifetimeMs: 5000,
|
|
452
|
+
doppelgangerSpawnRadius: 3,
|
|
453
|
+
doppelgangerInitialLifeFraction: 1.0,
|
|
454
|
+
},
|
|
455
|
+
|
|
456
|
+
// ── Equipment Rules ────────────────────────────────────────────────
|
|
457
|
+
equipmentRules: { ...EQUIPMENT_RULES_DEFAULTS },
|
|
458
|
+
};
|
|
@@ -4,24 +4,28 @@ import express from 'express';
|
|
|
4
4
|
|
|
5
5
|
const logger = loggerFactory(import.meta);
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
router
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
async (req, res) => await DefaultController.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
7
|
+
class DefaultRouter {
|
|
8
|
+
/**
|
|
9
|
+
* @param {import('../types.js').RouterOptions} options
|
|
10
|
+
* @returns {import('express').Router}
|
|
11
|
+
*/
|
|
12
|
+
static router(options) {
|
|
13
|
+
const router = express.Router();
|
|
14
|
+
router.post(`/:id`, async (req, res) => await DefaultController.post(req, res, options));
|
|
15
|
+
router.post(`/`, async (req, res) => await DefaultController.post(req, res, options));
|
|
16
|
+
router.get(`/:id`,
|
|
17
|
+
// options.authMiddleware,
|
|
18
|
+
async (req, res) => await DefaultController.get(req, res, options),
|
|
19
|
+
);
|
|
20
|
+
router.get(`/`, async (req, res) => await DefaultController.get(req, res, options));
|
|
21
|
+
router.put(`/:id`, async (req, res) => await DefaultController.put(req, res, options));
|
|
22
|
+
router.put(`/`, async (req, res) => await DefaultController.put(req, res, options));
|
|
23
|
+
router.delete(`/:id`, async (req, res) => await DefaultController.delete(req, res, options));
|
|
24
|
+
router.delete(`/`, async (req, res) => await DefaultController.delete(req, res, options));
|
|
25
|
+
return router;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
24
28
|
|
|
25
|
-
const ApiRouter = DefaultRouter;
|
|
29
|
+
const ApiRouter = (options) => DefaultRouter.router(options);
|
|
26
30
|
|
|
27
31
|
export { ApiRouter, DefaultRouter };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DataBaseProviderService } from '../../db/DataBaseProvider.js';
|
|
2
2
|
import { loggerFactory } from '../../server/logger.js';
|
|
3
3
|
import { DataQuery } from '../../server/data-query.js';
|
|
4
4
|
|
|
@@ -7,12 +7,12 @@ const logger = loggerFactory(import.meta);
|
|
|
7
7
|
class DefaultService {
|
|
8
8
|
static post = async (req, res, options) => {
|
|
9
9
|
/** @type {import('./default.model.js').DefaultModel} */
|
|
10
|
-
const Default =
|
|
10
|
+
const Default = DataBaseProviderService.getModel("Default", options);
|
|
11
11
|
return await new Default(req.body).save();
|
|
12
12
|
};
|
|
13
13
|
static get = async (req, res, options) => {
|
|
14
14
|
/** @type {import('./default.model.js').DefaultModel} */
|
|
15
|
-
const Default =
|
|
15
|
+
const Default = DataBaseProviderService.getModel("Default", options);
|
|
16
16
|
if (req.params.id) return await Default.findById(req.params.id);
|
|
17
17
|
|
|
18
18
|
// Parse query parameters using DataQuery helper
|
|
@@ -28,12 +28,12 @@ class DefaultService {
|
|
|
28
28
|
};
|
|
29
29
|
static put = async (req, res, options) => {
|
|
30
30
|
/** @type {import('./default.model.js').DefaultModel} */
|
|
31
|
-
const Default =
|
|
31
|
+
const Default = DataBaseProviderService.getModel("Default", options);
|
|
32
32
|
return await Default.findByIdAndUpdate(req.params.id, req.body);
|
|
33
33
|
};
|
|
34
34
|
static delete = async (req, res, options) => {
|
|
35
35
|
/** @type {import('./default.model.js').DefaultModel} */
|
|
36
|
-
const Default =
|
|
36
|
+
const Default = DataBaseProviderService.getModel("Default", options);
|
|
37
37
|
if (req.params.id) return await Default.findByIdAndDelete(req.params.id);
|
|
38
38
|
else return await Default.deleteMany();
|
|
39
39
|
};
|