cyberia 3.2.12 → 3.2.70
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 +127 -68
- package/.github/workflows/cyberia-client.cd.yml +40 -0
- package/.github/workflows/cyberia-server.cd.yml +40 -0
- package/.github/workflows/docker-image.cyberia-client.ci.yml +49 -0
- package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +48 -0
- package/.github/workflows/docker-image.cyberia-server.ci.yml +69 -0
- package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +69 -0
- package/.github/workflows/docker-image.engine-cyberia.ci.yml +52 -0
- package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +52 -0
- package/.github/workflows/engine-cyberia.cd.yml +34 -24
- package/.github/workflows/engine-cyberia.ci.yml +27 -5
- package/.github/workflows/ghpkg.ci.yml +89 -1
- package/.github/workflows/gitlab.ci.yml +1 -1
- package/.github/workflows/hardhat.ci.yml +1 -1
- package/.github/workflows/npmpkg.ci.yml +19 -12
- package/.github/workflows/publish.ci.yml +2 -2
- package/.github/workflows/publish.cyberia.ci.yml +5 -16
- package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -8
- package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
- package/CHANGELOG.md +451 -1
- package/CLI-HELP.md +1040 -1130
- package/Dockerfile +141 -43
- package/Dockerfile.dev +143 -0
- package/Dockerfile.test +165 -0
- package/README.md +1 -1
- package/baremetal/commission-workflows.json +1 -0
- package/bin/build.js +128 -136
- package/bin/build.template.js +25 -179
- package/bin/cyberia.js +1089 -188
- package/bin/deploy.js +6 -3
- package/bin/index.js +1089 -188
- package/bump.config.js +1 -0
- package/compose.env +131 -0
- package/conf.js +19 -1
- package/deployment.yaml +74 -2
- package/docker-compose.yml +316 -0
- package/hardhat/hardhat.config.js +2 -2
- package/hardhat/package-lock.json +620 -2041
- package/hardhat/package.json +7 -5
- package/hardhat/scripts/deployObjectLayerToken.js +18 -18
- package/hardhat/test/ObjectLayerToken.js +378 -274
- package/ipfs/configure-ipfs.sh +13 -0
- 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 +74 -2
- package/manifests/deployment/dd-cyberia-development/grpc-service.yaml +17 -0
- package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +32 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/mongodb/entrypoint.sh +76 -0
- package/nginx.conf +87 -0
- package/package.json +34 -22
- package/pv-pvc.yaml +32 -0
- package/scripts/disk-clean.sh +85 -60
- package/scripts/kubeadm-node-setup.sh +317 -0
- package/scripts/link-local-underpost-cli.sh +6 -0
- package/scripts/rocky-kickstart.sh +877 -185
- package/scripts/rpmfusion-ffmpeg-setup.sh +26 -50
- package/scripts/test-monitor.sh +248 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +43 -7
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +17 -25
- package/src/api/cyberia-action/cyberia-action.controller.js +19 -0
- package/src/api/cyberia-action/cyberia-action.model.js +21 -29
- package/src/api/cyberia-action/cyberia-action.router.js +42 -7
- package/src/api/cyberia-action/cyberia-action.service.js +20 -4
- package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +58 -57
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +37 -6
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +8 -2
- package/src/api/cyberia-entity/cyberia-entity.router.js +39 -7
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +74 -0
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +67 -0
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +63 -0
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +46 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +62 -10
- package/src/api/cyberia-instance/cyberia-instance.model.js +32 -2
- package/src/api/cyberia-instance/cyberia-instance.router.js +6 -6
- package/src/api/cyberia-instance/cyberia-world-generator.js +116 -3
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +3 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +39 -7
- package/src/api/cyberia-map/cyberia-map.router.js +21 -6
- package/src/api/cyberia-quest/cyberia-quest.controller.js +38 -0
- package/src/api/cyberia-quest/cyberia-quest.router.js +47 -7
- package/src/api/cyberia-quest/cyberia-quest.service.js +59 -4
- package/src/api/cyberia-saga/cyberia-saga.controller.js +74 -0
- package/src/api/cyberia-saga/cyberia-saga.model.js +59 -0
- package/src/api/cyberia-saga/cyberia-saga.router.js +63 -0
- package/src/api/cyberia-saga/cyberia-saga.service.js +42 -0
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +551 -122
- package/src/api/cyberia-skill/cyberia-skill.controller.js +74 -0
- package/src/api/cyberia-skill/cyberia-skill.model.js +50 -0
- package/src/api/cyberia-skill/cyberia-skill.router.js +63 -0
- package/src/api/cyberia-skill/cyberia-skill.service.js +42 -0
- package/src/api/ipfs/ipfs.service.js +28 -15
- package/src/api/object-layer/object-layer.router.js +25 -15
- package/src/api/object-layer/object-layer.service.js +15 -20
- package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +39 -7
- package/src/cli/baremetal.js +717 -16
- package/src/cli/cluster.js +80 -5
- package/src/cli/deploy.js +326 -292
- package/src/cli/docker-compose.js +648 -0
- package/src/cli/env.js +12 -6
- package/src/cli/fs.js +75 -30
- package/src/cli/image.js +187 -55
- package/src/cli/index.js +157 -6
- package/src/cli/kickstart.js +142 -20
- package/src/cli/monitor.js +387 -6
- package/src/cli/release.js +72 -15
- package/src/cli/repository.js +339 -40
- package/src/cli/run.js +678 -186
- package/src/cli/secrets.js +82 -48
- package/src/cli/ssh.js +234 -0
- package/src/cli/static.js +2 -2
- package/src/client/components/core/PanelForm.js +44 -44
- package/src/client/components/cyberia/ActionEngineCyberia.js +1867 -0
- package/src/client/components/cyberia/EntityEngineCyberia.js +585 -0
- package/src/client/components/cyberia/InstanceEngineCyberia.js +219 -13
- package/src/client/components/cyberia/MapEngineCyberia.js +154 -71
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +40 -63
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +34 -20
- package/src/client/components/cyberia/SharedDefaultsCyberia.js +195 -4
- package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +66 -0
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +8 -0
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +8 -0
- package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +92 -20
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +272 -50
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +3 -3
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +39 -22
- package/src/client/public/cyberia-docs/CYBERIA-LORE.md +88 -0
- package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +394 -0
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +28 -12
- package/src/client/public/cyberia-docs/CYBERIA.md +1 -1
- package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +27 -5
- package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
- package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +99 -0
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +2 -2
- package/src/client/services/cyberia-map/cyberia-map.management.js +2 -2
- package/src/client/services/cyberia-saga/cyberia-saga.service.js +99 -0
- package/src/client/services/cyberia-skill/cyberia-skill.service.js +99 -0
- package/src/client/services/object-layer/object-layer.management.js +6 -6
- package/src/{server → client-builder}/client-build-docs.js +15 -5
- package/src/{server → client-builder}/client-build-live.js +3 -3
- package/src/{server → client-builder}/client-build.js +25 -22
- package/src/{server → client-builder}/client-dev-server.js +3 -3
- package/src/{server → client-builder}/client-icons.js +2 -2
- package/src/{server → client-builder}/ssr.js +5 -5
- package/src/client.build.js +1 -3
- package/src/client.dev.js +1 -1
- package/src/db/mongo/MongoBootstrap.js +12 -12
- package/src/db/mongo/MongooseDB.js +2 -1
- package/src/grpc/cyberia/grpc-server.js +255 -70
- package/src/index.js +12 -1
- package/src/mailer/EmailRender.js +1 -1
- package/src/{server → projects/cyberia}/atlas-sprite-sheet-generator.js +2 -2
- package/src/{server → projects/cyberia}/besu-genesis-generator.js +3 -3
- package/src/projects/cyberia/catalog-cyberia.js +81 -0
- package/src/projects/cyberia/gemini-client.js +175 -0
- package/src/projects/cyberia/generate-saga.js +2107 -0
- package/src/{server → projects/cyberia}/ipfs-client.js +6 -4
- package/src/{server → projects/cyberia}/object-layer.js +12 -108
- package/src/{server → projects/cyberia}/semantic-layer-generator-floor.js +1 -1
- package/src/{server → projects/cyberia}/semantic-layer-generator-resource.js +1 -1
- package/src/{server → projects/cyberia}/semantic-layer-generator-skin.js +1 -1
- package/src/{server → projects/cyberia}/semantic-layer-generator.js +2 -2
- package/src/{server → projects/cyberia}/shape-generator.js +2 -2
- package/src/projects/underpost/catalog-underpost.js +60 -0
- package/src/runtime/cyberia-client/Dockerfile +31 -83
- package/src/runtime/cyberia-client/Dockerfile.dev +23 -30
- package/src/runtime/cyberia-server/Dockerfile +23 -42
- package/src/runtime/cyberia-server/Dockerfile.dev +20 -35
- package/src/runtime/engine-cyberia/Dockerfile +143 -0
- package/src/runtime/engine-cyberia/Dockerfile.dev +143 -0
- package/src/runtime/engine-cyberia/Dockerfile.test +165 -0
- package/src/runtime/engine-cyberia/compose.env +131 -0
- package/src/runtime/engine-cyberia/docker-compose.yml +316 -0
- package/src/runtime/engine-cyberia/ipfs/configure-ipfs.sh +13 -0
- package/src/runtime/engine-cyberia/mongodb/entrypoint.sh +76 -0
- package/src/runtime/engine-cyberia/nginx.conf +87 -0
- package/src/runtime/express/Express.js +2 -2
- package/src/runtime/nginx/Nginx.js +250 -0
- package/src/runtime/wp/Dockerfile +3 -3
- package/src/server/catalog.js +72 -0
- package/src/server/conf.js +415 -60
- package/src/server/runtime-status.js +252 -0
- package/src/server/start.js +42 -11
- package/src/server.js +6 -2
- package/test/cyberia-instance-conf-defaults.test.js +140 -0
- package/test/deploy-monitor.test.js +267 -0
- package/test/shape-generator.test.js +7 -1
- package/typedoc.dd-cyberia.json +3 -1
- package/typedoc.json +3 -1
- package/manifests/deployment/dd-test-development/deployment.yaml +0 -256
- package/manifests/deployment/dd-test-development/proxy.yaml +0 -102
- /package/src/client/ssr/{Render.js → RootDocument.js} +0 -0
- /package/src/{server → client-builder}/client-formatted.js +0 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { BtnIcon } from '../core/BtnIcon.js';
|
|
2
2
|
import { Input, InputFile, getFileFromBlobEndpoint } from '../core/Input.js';
|
|
3
3
|
import { htmls, s } from '../core/VanillaJs.js';
|
|
4
|
+
import { commonModeratorGuard } from '../core/CommonJs.js';
|
|
4
5
|
import { NotificationManager } from '../core/NotificationManager.js';
|
|
5
6
|
import { Translate } from '../core/Translate.js';
|
|
6
7
|
import { dynamicCol, darkTheme, ThemeEvents } from '../core/Css.js';
|
|
7
8
|
import { DropDown } from '../core/DropDown.js';
|
|
8
9
|
import { CyberiaInstanceManagement } from '../../services/cyberia-instance/cyberia-instance.management.js';
|
|
9
10
|
import { CyberiaInstanceService } from '../../services/cyberia-instance/cyberia-instance.service.js';
|
|
11
|
+
import { CyberiaInstanceConfService } from '../../services/cyberia-instance-conf/cyberia-instance-conf.service.js';
|
|
10
12
|
import { CyberiaMapService } from '../../services/cyberia-map/cyberia-map.service.js';
|
|
11
13
|
import { FileService } from '../../services/file/file.service.js';
|
|
12
14
|
import { DefaultManagement } from '../../services/default/default.management.js';
|
|
@@ -27,28 +29,102 @@ class InstanceEngineCyberia {
|
|
|
27
29
|
static thumbnailDirty = false;
|
|
28
30
|
static portals = [];
|
|
29
31
|
static itemIdsDropdownId = 'instance-engine-item-ids-dropdown';
|
|
32
|
+
static itemInventoryListId = 'instance-engine-item-inventory-list';
|
|
33
|
+
// itemId → defaultPlayerInventory flag for the currently selected item ids.
|
|
34
|
+
static itemInventoryFlags = {};
|
|
35
|
+
|
|
36
|
+
// Current selection, read from the dropdown's `oncheckvalues` (always live —
|
|
37
|
+
// it is updated before `_renderSelectedBadges` runs, unlike `.value` which
|
|
38
|
+
// lags by one in the option-click path).
|
|
39
|
+
static getSelectedItemIds() {
|
|
40
|
+
const token = DropDown.Tokens[InstanceEngineCyberia.itemIdsDropdownId];
|
|
41
|
+
if (!token) return [];
|
|
42
|
+
const fromChecks = Object.values(token.oncheckvalues || {})
|
|
43
|
+
.map((v) => v.data)
|
|
44
|
+
.filter(Boolean);
|
|
45
|
+
if (fromChecks.length > 0) return fromChecks;
|
|
46
|
+
return Array.isArray(token.value) ? token.value.filter(Boolean) : [];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Render the per-item "Default Player Inventory" toggles for every selected
|
|
50
|
+
// item id. Kept in sync with the dropdown via a MutationObserver on its badge
|
|
51
|
+
// container (see render()).
|
|
52
|
+
static renderItemInventoryList(containerId = InstanceEngineCyberia.itemInventoryListId) {
|
|
53
|
+
const container = s(`.${containerId}`);
|
|
54
|
+
if (!container) return;
|
|
55
|
+
|
|
56
|
+
const selected = InstanceEngineCyberia.getSelectedItemIds();
|
|
57
|
+
|
|
58
|
+
// Drop flags for items no longer selected so the payload never carries them.
|
|
59
|
+
for (const key of Object.keys(InstanceEngineCyberia.itemInventoryFlags)) {
|
|
60
|
+
if (!selected.includes(key)) delete InstanceEngineCyberia.itemInventoryFlags[key];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (selected.length === 0) {
|
|
64
|
+
htmls(`.${containerId}`, html`<div style="color:#888;font-size:12px;">No item IDs selected.</div>`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let listHtml = '';
|
|
69
|
+
for (const itemId of selected) {
|
|
70
|
+
const checked = InstanceEngineCyberia.itemInventoryFlags[itemId] ? 'checked' : '';
|
|
71
|
+
listHtml += html`<div class="fl" style="border-bottom:1px solid #444;padding:4px 0;align-items:center;">
|
|
72
|
+
<div class="in fll" style="flex:1;font-size:12px;font-family:monospace;">${itemId}</div>
|
|
73
|
+
<div class="in fll" style="display:flex;align-items:center;justify-content:flex-end;">
|
|
74
|
+
<label style="font-size:11px;cursor:pointer;display:flex;align-items:center;gap:5px;">
|
|
75
|
+
<input
|
|
76
|
+
type="checkbox"
|
|
77
|
+
class="instance-engine-item-inv-checkbox"
|
|
78
|
+
data-item-id="${itemId}"
|
|
79
|
+
${checked}
|
|
80
|
+
style="cursor:pointer;"
|
|
81
|
+
/>
|
|
82
|
+
Default Player Inventory
|
|
83
|
+
</label>
|
|
84
|
+
</div>
|
|
85
|
+
</div>`;
|
|
86
|
+
}
|
|
87
|
+
htmls(`.${containerId}`, listHtml);
|
|
88
|
+
|
|
89
|
+
container.querySelectorAll('.instance-engine-item-inv-checkbox').forEach((cb) => {
|
|
90
|
+
cb.onchange = () => {
|
|
91
|
+
InstanceEngineCyberia.itemInventoryFlags[cb.dataset.itemId] = cb.checked;
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
}
|
|
30
95
|
|
|
31
96
|
static syncItemIdsDropdownSelection(itemIds = []) {
|
|
32
97
|
const dropdownId = InstanceEngineCyberia.itemIdsDropdownId;
|
|
33
98
|
if (!DropDown.Tokens[dropdownId]) return;
|
|
34
99
|
|
|
100
|
+
// Accept both the new [{ id, defaultPlayerInventory }] shape and the legacy
|
|
101
|
+
// string[] shape so older instance docs keep loading.
|
|
102
|
+
const normalized = (itemIds || [])
|
|
103
|
+
.map((entry) => (typeof entry === 'string' ? { id: entry, defaultPlayerInventory: false } : entry))
|
|
104
|
+
.filter((entry) => entry && entry.id);
|
|
105
|
+
|
|
35
106
|
DropDown.Tokens[dropdownId].value = [];
|
|
36
107
|
if (s(`.${dropdownId}`)) s(`.${dropdownId}`).value = [];
|
|
37
108
|
DropDown.Tokens[dropdownId].oncheckvalues = {};
|
|
38
109
|
htmls(`.dropdown-current-${dropdownId}`, '');
|
|
39
110
|
htmls(`.${dropdownId}-render-container`, '');
|
|
40
111
|
|
|
41
|
-
|
|
42
|
-
|
|
112
|
+
InstanceEngineCyberia.itemInventoryFlags = {};
|
|
113
|
+
const ids = [];
|
|
114
|
+
for (const entry of normalized) {
|
|
115
|
+
const key = dropdownValueKey(entry.id);
|
|
43
116
|
DropDown.Tokens[dropdownId].oncheckvalues[key] = {
|
|
44
|
-
data:
|
|
45
|
-
display:
|
|
46
|
-
value:
|
|
117
|
+
data: entry.id,
|
|
118
|
+
display: entry.id,
|
|
119
|
+
value: entry.id,
|
|
47
120
|
};
|
|
121
|
+
InstanceEngineCyberia.itemInventoryFlags[entry.id] = !!entry.defaultPlayerInventory;
|
|
122
|
+
ids.push(entry.id);
|
|
48
123
|
}
|
|
49
|
-
DropDown.Tokens[dropdownId].value = [...
|
|
50
|
-
if (s(`.${dropdownId}`)) s(`.${dropdownId}`).value = [...
|
|
124
|
+
DropDown.Tokens[dropdownId].value = [...ids];
|
|
125
|
+
if (s(`.${dropdownId}`)) s(`.${dropdownId}`).value = [...ids];
|
|
51
126
|
DropDown.Tokens[dropdownId]._renderSelectedBadges?.();
|
|
127
|
+
InstanceEngineCyberia.renderItemInventoryList();
|
|
52
128
|
}
|
|
53
129
|
|
|
54
130
|
static async buildItemIdsDropdown() {
|
|
@@ -151,6 +227,8 @@ class InstanceEngineCyberia {
|
|
|
151
227
|
|
|
152
228
|
static async render(options = {}) {
|
|
153
229
|
const { appStore } = options;
|
|
230
|
+
const role = appStore?.Data?.user?.main?.model?.user?.role || 'guest';
|
|
231
|
+
const canMutate = commonModeratorGuard(role);
|
|
154
232
|
const idCode = 'instance-engine-input-code';
|
|
155
233
|
const idName = 'instance-engine-input-name';
|
|
156
234
|
const idDescription = 'instance-engine-input-description';
|
|
@@ -169,6 +247,11 @@ class InstanceEngineCyberia {
|
|
|
169
247
|
const idTargetCellY = 'instance-engine-target-cell-y';
|
|
170
248
|
const idFilterSource = 'instance-engine-filter-source';
|
|
171
249
|
const idFilterTarget = 'instance-engine-filter-target';
|
|
250
|
+
const idSpawnMapCode = 'instance-engine-spawn-map-code';
|
|
251
|
+
const idSpawnCellX = 'instance-engine-spawn-cell-x';
|
|
252
|
+
const idSpawnCellY = 'instance-engine-spawn-cell-y';
|
|
253
|
+
const idSpawnRandom = 'instance-engine-spawn-random';
|
|
254
|
+
const idAoiRadius = 'instance-engine-aoi-radius';
|
|
172
255
|
|
|
173
256
|
InstanceEngineCyberia.currentInstanceId = null;
|
|
174
257
|
InstanceEngineCyberia.currentThumbnailId = null;
|
|
@@ -184,7 +267,10 @@ class InstanceEngineCyberia {
|
|
|
184
267
|
const cyberiaMapCodes = DropDown.Tokens[idMapCodesDropdown]?.value
|
|
185
268
|
? [...DropDown.Tokens[idMapCodesDropdown].value]
|
|
186
269
|
: [];
|
|
187
|
-
const itemIds =
|
|
270
|
+
const itemIds = InstanceEngineCyberia.getSelectedItemIds().map((id) => ({
|
|
271
|
+
id,
|
|
272
|
+
defaultPlayerInventory: !!InstanceEngineCyberia.itemInventoryFlags[id],
|
|
273
|
+
}));
|
|
188
274
|
const payload = {
|
|
189
275
|
code: s(`.${idCode}`)?.value || '',
|
|
190
276
|
name: s(`.${idName}`)?.value || '',
|
|
@@ -194,11 +280,37 @@ class InstanceEngineCyberia {
|
|
|
194
280
|
cyberiaMapCodes,
|
|
195
281
|
itemIds,
|
|
196
282
|
portals: InstanceEngineCyberia.portals,
|
|
283
|
+
playerSpawn: {
|
|
284
|
+
sourceMapCode: s(`.${idSpawnMapCode}`)?.value?.trim() || '',
|
|
285
|
+
sourceCellX: parseInt(s(`.${idSpawnCellX}`)?.value) || 0,
|
|
286
|
+
sourceCellY: parseInt(s(`.${idSpawnCellY}`)?.value) || 0,
|
|
287
|
+
random: !!s(`.${idSpawnRandom}`)?.checked,
|
|
288
|
+
},
|
|
197
289
|
};
|
|
198
290
|
if (InstanceEngineCyberia.currentThumbnailId) payload.thumbnail = InstanceEngineCyberia.currentThumbnailId;
|
|
199
291
|
return payload;
|
|
200
292
|
};
|
|
201
293
|
|
|
294
|
+
// AOI radius lives on the linked CyberiaInstanceConf (auto-upserted on
|
|
295
|
+
// instance save). Fetch / update it by instanceCode so the engine can edit
|
|
296
|
+
// it alongside instance identity without touching the rest of the conf.
|
|
297
|
+
const fetchConfByCode = async (instanceCode) => {
|
|
298
|
+
if (!instanceCode) return null;
|
|
299
|
+
const res = await CyberiaInstanceConfService.get({
|
|
300
|
+
filterModel: { instanceCode: { filterType: 'text', type: 'equals', filter: instanceCode } },
|
|
301
|
+
});
|
|
302
|
+
return res?.data?.data?.[0] || null;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const persistAoiRadius = async (instanceCode) => {
|
|
306
|
+
const raw = s(`.${idAoiRadius}`)?.value;
|
|
307
|
+
if (raw === undefined || raw === '') return;
|
|
308
|
+
const aoiRadius = parseFloat(raw);
|
|
309
|
+
if (!Number.isFinite(aoiRadius)) return;
|
|
310
|
+
const conf = await fetchConfByCode(instanceCode);
|
|
311
|
+
if (conf?._id) await CyberiaInstanceConfService.put({ id: conf._id, body: { aoiRadius } });
|
|
312
|
+
};
|
|
313
|
+
|
|
202
314
|
const persistInstance = async ({ notify = true } = {}) => {
|
|
203
315
|
// Upload thumbnail file only if user selected a new one
|
|
204
316
|
const thumbnailInput = s(`.${idThumbnail}`);
|
|
@@ -245,6 +357,9 @@ class InstanceEngineCyberia {
|
|
|
245
357
|
}
|
|
246
358
|
if (result.status === 'success') {
|
|
247
359
|
if (result.data?._id) InstanceEngineCyberia.currentInstanceId = result.data._id;
|
|
360
|
+
// The conf is auto-upserted on instance save; persist the AOI radius onto
|
|
361
|
+
// it now that we know the instance code resolves to a conf document.
|
|
362
|
+
await persistAoiRadius(body.code);
|
|
248
363
|
await DefaultManagement.loadTable(managementId, { force: true, reload: true });
|
|
249
364
|
}
|
|
250
365
|
return result;
|
|
@@ -347,6 +462,17 @@ class InstanceEngineCyberia {
|
|
|
347
462
|
portalMode: p.portalMode || 'inter-portal',
|
|
348
463
|
}));
|
|
349
464
|
InstanceEngineCyberia.renderPortalList(portalListId);
|
|
465
|
+
|
|
466
|
+
// Player spawn (instance-level).
|
|
467
|
+
const spawn = instanceData.playerSpawn || {};
|
|
468
|
+
if (s(`.${idSpawnMapCode}`)) s(`.${idSpawnMapCode}`).value = spawn.sourceMapCode || '';
|
|
469
|
+
if (s(`.${idSpawnCellX}`)) s(`.${idSpawnCellX}`).value = spawn.sourceCellX ?? 0;
|
|
470
|
+
if (s(`.${idSpawnCellY}`)) s(`.${idSpawnCellY}`).value = spawn.sourceCellY ?? 0;
|
|
471
|
+
if (s(`.${idSpawnRandom}`)) s(`.${idSpawnRandom}`).checked = !!spawn.random;
|
|
472
|
+
|
|
473
|
+
// AOI radius (lives on the linked conf, fetched by instance code).
|
|
474
|
+
const conf = await fetchConfByCode(instanceData.code);
|
|
475
|
+
if (s(`.${idAoiRadius}`)) s(`.${idAoiRadius}`).value = conf?.aoiRadius ?? '';
|
|
350
476
|
};
|
|
351
477
|
|
|
352
478
|
const resetForm = () => {
|
|
@@ -381,8 +507,15 @@ class InstanceEngineCyberia {
|
|
|
381
507
|
htmls(`.dropdown-current-${idItemIdsDropdown}`, '');
|
|
382
508
|
htmls(`.${idItemIdsDropdown}-render-container`, '');
|
|
383
509
|
}
|
|
510
|
+
InstanceEngineCyberia.itemInventoryFlags = {};
|
|
511
|
+
InstanceEngineCyberia.renderItemInventoryList();
|
|
384
512
|
InstanceEngineCyberia.portals = [];
|
|
385
513
|
InstanceEngineCyberia.renderPortalList(portalListId);
|
|
514
|
+
if (s(`.${idSpawnMapCode}`)) s(`.${idSpawnMapCode}`).value = '';
|
|
515
|
+
if (s(`.${idSpawnCellX}`)) s(`.${idSpawnCellX}`).value = 0;
|
|
516
|
+
if (s(`.${idSpawnCellY}`)) s(`.${idSpawnCellY}`).value = 0;
|
|
517
|
+
if (s(`.${idSpawnRandom}`)) s(`.${idSpawnRandom}`).checked = false;
|
|
518
|
+
if (s(`.${idAoiRadius}`)) s(`.${idAoiRadius}`).value = '';
|
|
386
519
|
};
|
|
387
520
|
|
|
388
521
|
setTimeout(() => {
|
|
@@ -495,6 +628,19 @@ class InstanceEngineCyberia {
|
|
|
495
628
|
InstanceEngineCyberia.renderPortalList(portalListId);
|
|
496
629
|
};
|
|
497
630
|
|
|
631
|
+
// Keep the per-item "Default Player Inventory" toggles in sync with the
|
|
632
|
+
// item-ids dropdown. Every add/remove/clear re-renders the dropdown badge
|
|
633
|
+
// container, so observing it is a reliable change hook (the dropdown
|
|
634
|
+
// exposes no onChange callback).
|
|
635
|
+
const itemBadgeContainer = s(`.dropdown-current-${idItemIdsDropdown}`);
|
|
636
|
+
if (itemBadgeContainer) {
|
|
637
|
+
const itemInventoryObserver = new MutationObserver(() => {
|
|
638
|
+
InstanceEngineCyberia.renderItemInventoryList();
|
|
639
|
+
});
|
|
640
|
+
itemInventoryObserver.observe(itemBadgeContainer, { childList: true, subtree: true });
|
|
641
|
+
}
|
|
642
|
+
InstanceEngineCyberia.renderItemInventoryList();
|
|
643
|
+
|
|
498
644
|
ThemeEvents['instance-engine-theme'] = () => {
|
|
499
645
|
InstanceEngineCyberia.renderPortalList(portalListId);
|
|
500
646
|
};
|
|
@@ -527,6 +673,7 @@ class InstanceEngineCyberia {
|
|
|
527
673
|
const dcPortalSource = 'instance-engine-dc-portal-source';
|
|
528
674
|
const dcPortalTarget = 'instance-engine-dc-portal-target';
|
|
529
675
|
const dcPortalFilter = 'instance-engine-dc-portal-filter';
|
|
676
|
+
const dcSpawn = 'instance-engine-dc-spawn';
|
|
530
677
|
|
|
531
678
|
return html`<div class="in section-mp instance-engine-container">
|
|
532
679
|
${dynamicCol({ containerSelector: 'instance-engine-container', id: dcFields, type: 'search-inputs' })}
|
|
@@ -645,6 +792,10 @@ class InstanceEngineCyberia {
|
|
|
645
792
|
})}
|
|
646
793
|
</div>
|
|
647
794
|
<div class="in section-mp" style="margin-top: 10px;">${await InstanceEngineCyberia.buildItemIdsDropdown()}</div>
|
|
795
|
+
<div class="in section-mp" style="margin-top: 5px;">
|
|
796
|
+
<div class="in input-label" style="font-size:13px;margin-bottom:5px;">Default Player Inventory</div>
|
|
797
|
+
<div class="in ${InstanceEngineCyberia.itemInventoryListId}" style="max-height:200px;overflow-y:auto;"></div>
|
|
798
|
+
</div>
|
|
648
799
|
<div class="in section-mp" style="margin-top: 10px;">
|
|
649
800
|
<div class="in input-label" style="font-size:14px;margin-bottom:5px;">Portals</div>
|
|
650
801
|
${dynamicCol({ containerSelector: 'instance-engine-container', id: dcPortalSource, type: 'search-inputs' })}
|
|
@@ -757,14 +908,69 @@ class InstanceEngineCyberia {
|
|
|
757
908
|
<div class="in ${portalListId}" style="margin-top: 10px; max-height: 200px; overflow-y: auto;"></div>
|
|
758
909
|
</div>
|
|
759
910
|
<div class="in section-mp" style="margin-top: 10px;">
|
|
760
|
-
|
|
911
|
+
<div class="in input-label" style="font-size:14px;margin-bottom:5px;">Player Spawn & World</div>
|
|
912
|
+
<div class="in" style="font-size:12px;color:#888;margin-bottom:6px;">
|
|
913
|
+
Fixed spawn places every new player at the cell below. Enable Random (or leave the map code blank) to spawn at
|
|
914
|
+
a random walkable cell on a random map.
|
|
915
|
+
</div>
|
|
916
|
+
${dynamicCol({ containerSelector: 'instance-engine-container', id: dcSpawn, type: 'search-inputs' })}
|
|
761
917
|
<div class="fl">
|
|
762
|
-
<div class="in fll ${
|
|
763
|
-
${await
|
|
764
|
-
|
|
765
|
-
label: html
|
|
918
|
+
<div class="in fll ${dcSpawn}-col-a">
|
|
919
|
+
${await Input.instance({
|
|
920
|
+
id: idSpawnMapCode,
|
|
921
|
+
label: html`Spawn Map Code`,
|
|
922
|
+
containerClass: 'inl',
|
|
923
|
+
type: 'text',
|
|
924
|
+
})}
|
|
925
|
+
</div>
|
|
926
|
+
<div class="in fll ${dcSpawn}-col-b">
|
|
927
|
+
${await Input.instance({
|
|
928
|
+
id: idSpawnCellX,
|
|
929
|
+
label: html`Spawn Cell X`,
|
|
930
|
+
containerClass: 'inl',
|
|
931
|
+
type: 'number',
|
|
932
|
+
min: 0,
|
|
933
|
+
value: 0,
|
|
934
|
+
})}
|
|
935
|
+
</div>
|
|
936
|
+
<div class="in fll ${dcSpawn}-col-c">
|
|
937
|
+
${await Input.instance({
|
|
938
|
+
id: idSpawnCellY,
|
|
939
|
+
label: html`Spawn Cell Y`,
|
|
940
|
+
containerClass: 'inl',
|
|
941
|
+
type: 'number',
|
|
942
|
+
min: 0,
|
|
943
|
+
value: 0,
|
|
766
944
|
})}
|
|
767
945
|
</div>
|
|
946
|
+
</div>
|
|
947
|
+
<div class="in" style="margin-top:6px;">
|
|
948
|
+
<label style="font-size:13px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;">
|
|
949
|
+
<input class="${idSpawnRandom}" type="checkbox" style="cursor:pointer;" /> Random spawn (ignore the fixed
|
|
950
|
+
cell)
|
|
951
|
+
</label>
|
|
952
|
+
</div>
|
|
953
|
+
<div class="in" style="margin-top:10px;">
|
|
954
|
+
${await Input.instance({
|
|
955
|
+
id: idAoiRadius,
|
|
956
|
+
label: html`AOI Radius (cells)`,
|
|
957
|
+
containerClass: 'inl',
|
|
958
|
+
type: 'number',
|
|
959
|
+
min: 1,
|
|
960
|
+
})}
|
|
961
|
+
</div>
|
|
962
|
+
</div>
|
|
963
|
+
<div class="in section-mp" style="margin-top: 10px;">
|
|
964
|
+
${dynamicCol({ containerSelector: 'instance-engine-container', id: dcSaveNew, type: 'a-50-b-50' })}
|
|
965
|
+
<div class="fl">
|
|
966
|
+
${canMutate
|
|
967
|
+
? html`<div class="in fll ${dcSaveNew}-col-a" style="padding: 5px;">
|
|
968
|
+
${await BtnIcon.instance({
|
|
969
|
+
class: 'wfa btn-instance-engine-save',
|
|
970
|
+
label: html`<i class="fa-solid fa-floppy-disk"></i> Save Instance`,
|
|
971
|
+
})}
|
|
972
|
+
</div>`
|
|
973
|
+
: ''}
|
|
768
974
|
<div class="in fll ${dcSaveNew}-col-b" style="padding: 5px;">
|
|
769
975
|
${await BtnIcon.instance({
|
|
770
976
|
class: 'wfa btn-instance-engine-new',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BtnIcon } from '../core/BtnIcon.js';
|
|
2
2
|
import { Input, InputFile, getFileFromBlobEndpoint } from '../core/Input.js';
|
|
3
3
|
import { htmls, s } from '../core/VanillaJs.js';
|
|
4
|
+
import { commonModeratorGuard } from '../core/CommonJs.js';
|
|
4
5
|
import { NotificationManager } from '../core/NotificationManager.js';
|
|
5
6
|
import { Translate } from '../core/Translate.js';
|
|
6
7
|
import { darkTheme, dynamicCol, ThemeEvents } from '../core/Css.js';
|
|
@@ -33,6 +34,7 @@ class MapEngineCyberia {
|
|
|
33
34
|
static loadMap = null;
|
|
34
35
|
static showGridBorders = true;
|
|
35
36
|
static addOnClick = true;
|
|
37
|
+
static removeOnClick = false;
|
|
36
38
|
static showObjectLayers = false;
|
|
37
39
|
static enableRandomFactors = false;
|
|
38
40
|
static captureObjLayerThumbnail = true;
|
|
@@ -151,13 +153,43 @@ class MapEngineCyberia {
|
|
|
151
153
|
return false;
|
|
152
154
|
}
|
|
153
155
|
|
|
156
|
+
// Collect indices of filtered entities that have the source itemId
|
|
157
|
+
const eligible = [];
|
|
158
|
+
for (const { i } of filtered) {
|
|
159
|
+
const entity = MapEngineCyberia.entities[i];
|
|
160
|
+
if (Array.isArray(entity?.objectLayerItemIds) && entity.objectLayerItemIds.includes(source)) {
|
|
161
|
+
eligible.push(i);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (!eligible.length) {
|
|
166
|
+
NotificationManager.Push({
|
|
167
|
+
html: `No exact ItemId matches for "${source}" were found in the current filtered entities.`,
|
|
168
|
+
status: 'error',
|
|
169
|
+
});
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// When enableRandomFactors is active, each matching entity independently rolls
|
|
174
|
+
// a random probability check in [fMin, fMax]. If the roll passes, it gets renamed;
|
|
175
|
+
// otherwise it stays unchanged. This produces an intermediate intensity between
|
|
176
|
+
// "almost everyone" (factors near/above 1.0) and "almost no one" (factors near 0).
|
|
154
177
|
let matchedEntities = 0;
|
|
155
178
|
let renamedReferences = 0;
|
|
156
179
|
const changed = MapEngineCyberia.commitEntityMutation(() => {
|
|
157
|
-
for (const
|
|
180
|
+
for (const i of eligible) {
|
|
181
|
+
if (MapEngineCyberia.enableRandomFactors) {
|
|
182
|
+
const rawA = parseFloat(s('.map-engine-factor-a')?.value);
|
|
183
|
+
const rawB = parseFloat(s('.map-engine-factor-b')?.value);
|
|
184
|
+
const minF = Number.isFinite(rawA) ? rawA : 0.5;
|
|
185
|
+
const maxF = Number.isFinite(rawB) ? rawB : 1.5;
|
|
186
|
+
const fMin = Math.min(minF, maxF);
|
|
187
|
+
const fMax = Math.max(minF, maxF);
|
|
188
|
+
const roll = fMin + Math.random() * (fMax - fMin);
|
|
189
|
+
// If the roll is >= 1.0, always rename; otherwise compare against Math.random()
|
|
190
|
+
if (roll < 1.0 && Math.random() > roll) continue;
|
|
191
|
+
}
|
|
158
192
|
const entity = MapEngineCyberia.entities[i];
|
|
159
|
-
if (!Array.isArray(entity?.objectLayerItemIds) || entity.objectLayerItemIds.length === 0) continue;
|
|
160
|
-
|
|
161
193
|
let entityChanged = false;
|
|
162
194
|
entity.objectLayerItemIds = entity.objectLayerItemIds.map((itemId) => {
|
|
163
195
|
if (itemId !== source) return itemId;
|
|
@@ -165,7 +197,6 @@ class MapEngineCyberia {
|
|
|
165
197
|
renamedReferences += 1;
|
|
166
198
|
return target;
|
|
167
199
|
});
|
|
168
|
-
|
|
169
200
|
if (entityChanged) matchedEntities += 1;
|
|
170
201
|
}
|
|
171
202
|
});
|
|
@@ -570,6 +601,8 @@ class MapEngineCyberia {
|
|
|
570
601
|
|
|
571
602
|
static async render(options = {}) {
|
|
572
603
|
const { appStore } = options;
|
|
604
|
+
const role = appStore?.Data?.user?.main?.model?.user?.role || 'guest';
|
|
605
|
+
const canMutate = commonModeratorGuard(role);
|
|
573
606
|
const idCode = 'map-engine-input-code';
|
|
574
607
|
const idName = 'map-engine-input-name';
|
|
575
608
|
const idDescription = 'map-engine-input-description';
|
|
@@ -1143,7 +1176,15 @@ class MapEngineCyberia {
|
|
|
1143
1176
|
if (s(`.${idInitCellX}`)) s(`.${idInitCellX}`).value = col;
|
|
1144
1177
|
if (s(`.${idInitCellY}`)) s(`.${idInitCellY}`).value = row;
|
|
1145
1178
|
|
|
1146
|
-
if (MapEngineCyberia.addOnClick)
|
|
1179
|
+
if (MapEngineCyberia.addOnClick) {
|
|
1180
|
+
addEntityLocally();
|
|
1181
|
+
} else if (MapEngineCyberia.removeOnClick) {
|
|
1182
|
+
MapEngineCyberia.commitEntityMutation(() => {
|
|
1183
|
+
MapEngineCyberia.entities = MapEngineCyberia.entities.filter(
|
|
1184
|
+
(entity) => !(entity.initCellX === col && entity.initCellY === row),
|
|
1185
|
+
);
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1147
1188
|
};
|
|
1148
1189
|
|
|
1149
1190
|
if (s(`.btn-map-engine-add-entity`)) s(`.btn-map-engine-add-entity`).onclick = () => addEntityLocally();
|
|
@@ -1461,67 +1502,107 @@ class MapEngineCyberia {
|
|
|
1461
1502
|
${dynamicCol({ containerSelector: 'map-engine-container', id: dcCanvasOpts, type: 'search-inputs' })}
|
|
1462
1503
|
<div class="fl" style="margin-bottom: 5px;">
|
|
1463
1504
|
<div class="in fll ${dcCanvasOpts}-col-a">
|
|
1464
|
-
<div class="
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
checked:
|
|
1473
|
-
|
|
1474
|
-
|
|
1505
|
+
<div class="in section-mp-border" style="padding: 10px;">
|
|
1506
|
+
<div class="in input-label" style="margin-bottom: 6px; font-size: 14px;">Click Action</div>
|
|
1507
|
+
<div class="fl" style="align-items: center; gap: 8px; font-size: 20px; text-align: left;">
|
|
1508
|
+
${await ToggleSwitch.instance({
|
|
1509
|
+
id: 'map-engine-add-on-click',
|
|
1510
|
+
type: 'checkbox',
|
|
1511
|
+
displayMode: 'checkbox',
|
|
1512
|
+
containerClass: 'in fll',
|
|
1513
|
+
checked: true,
|
|
1514
|
+
on: {
|
|
1515
|
+
checked: () => {
|
|
1516
|
+
MapEngineCyberia.addOnClick = true;
|
|
1517
|
+
MapEngineCyberia.removeOnClick = false;
|
|
1518
|
+
const removeToken = ToggleSwitch.Tokens['map-engine-remove-on-click'];
|
|
1519
|
+
if (removeToken) {
|
|
1520
|
+
const removeCheckbox = s('.map-engine-remove-on-click-checkbox');
|
|
1521
|
+
if (removeCheckbox && removeCheckbox.checked) removeToken.click();
|
|
1522
|
+
}
|
|
1523
|
+
},
|
|
1524
|
+
unchecked: () => {
|
|
1525
|
+
MapEngineCyberia.addOnClick = false;
|
|
1526
|
+
},
|
|
1475
1527
|
},
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1528
|
+
})}
|
|
1529
|
+
<div class="section-mp">    Add on Click</div>
|
|
1530
|
+
</div>
|
|
1531
|
+
<div
|
|
1532
|
+
class="fl"
|
|
1533
|
+
style="align-items: center; gap: 8px; font-size: 20px; text-align: left; margin-top: 4px;"
|
|
1534
|
+
>
|
|
1535
|
+
${await ToggleSwitch.instance({
|
|
1536
|
+
id: 'map-engine-remove-on-click',
|
|
1537
|
+
type: 'checkbox',
|
|
1538
|
+
displayMode: 'checkbox',
|
|
1539
|
+
containerClass: 'in fll',
|
|
1540
|
+
checked: false,
|
|
1541
|
+
on: {
|
|
1542
|
+
checked: () => {
|
|
1543
|
+
MapEngineCyberia.removeOnClick = true;
|
|
1544
|
+
MapEngineCyberia.addOnClick = false;
|
|
1545
|
+
const addToken = ToggleSwitch.Tokens['map-engine-add-on-click'];
|
|
1546
|
+
if (addToken) {
|
|
1547
|
+
const addCheckbox = s('.map-engine-add-on-click-checkbox');
|
|
1548
|
+
if (addCheckbox && addCheckbox.checked) addToken.click();
|
|
1549
|
+
}
|
|
1550
|
+
},
|
|
1551
|
+
unchecked: () => {
|
|
1552
|
+
MapEngineCyberia.removeOnClick = false;
|
|
1553
|
+
},
|
|
1479
1554
|
},
|
|
1480
|
-
}
|
|
1481
|
-
|
|
1482
|
-
|
|
1555
|
+
})}
|
|
1556
|
+
<div class="section-mp">    Remove on Click</div>
|
|
1557
|
+
</div>
|
|
1483
1558
|
</div>
|
|
1484
1559
|
</div>
|
|
1485
1560
|
<div class="in fll ${dcCanvasOpts}-col-b">
|
|
1486
|
-
<div class="
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
checked:
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1561
|
+
<div class="in section-mp-border" style="padding: 10px;">
|
|
1562
|
+
<div class="in input-label" style="margin-bottom: 6px; font-size: 14px;">View Options</div>
|
|
1563
|
+
<div class="fl" style="align-items: center; gap: 8px; font-size: 20px; text-align: left;">
|
|
1564
|
+
${await ToggleSwitch.instance({
|
|
1565
|
+
id: 'map-engine-show-grid',
|
|
1566
|
+
type: 'checkbox',
|
|
1567
|
+
displayMode: 'checkbox',
|
|
1568
|
+
containerClass: 'in fll',
|
|
1569
|
+
checked: true,
|
|
1570
|
+
on: {
|
|
1571
|
+
checked: () => {
|
|
1572
|
+
MapEngineCyberia.showGridBorders = true;
|
|
1573
|
+
rerenderCanvas();
|
|
1574
|
+
},
|
|
1575
|
+
unchecked: () => {
|
|
1576
|
+
MapEngineCyberia.showGridBorders = false;
|
|
1577
|
+
rerenderCanvas();
|
|
1578
|
+
},
|
|
1499
1579
|
},
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1580
|
+
})}
|
|
1581
|
+
<div class="section-mp">    Show Grid</div>
|
|
1582
|
+
</div>
|
|
1583
|
+
<div
|
|
1584
|
+
class="fl"
|
|
1585
|
+
style="align-items: center; gap: 8px; font-size: 20px; text-align: left; margin-top: 4px;"
|
|
1586
|
+
>
|
|
1587
|
+
${await ToggleSwitch.instance({
|
|
1588
|
+
id: 'map-engine-show-object-layers',
|
|
1589
|
+
type: 'checkbox',
|
|
1590
|
+
displayMode: 'checkbox',
|
|
1591
|
+
containerClass: 'in fll',
|
|
1592
|
+
checked: false,
|
|
1593
|
+
on: {
|
|
1594
|
+
checked: () => {
|
|
1595
|
+
MapEngineCyberia.showObjectLayers = true;
|
|
1596
|
+
rerenderCanvas();
|
|
1597
|
+
},
|
|
1598
|
+
unchecked: () => {
|
|
1599
|
+
MapEngineCyberia.showObjectLayers = false;
|
|
1600
|
+
rerenderCanvas();
|
|
1601
|
+
},
|
|
1521
1602
|
},
|
|
1522
|
-
}
|
|
1523
|
-
|
|
1524
|
-
|
|
1603
|
+
})}
|
|
1604
|
+
<div class="section-mp">    Object Layers</div>
|
|
1605
|
+
</div>
|
|
1525
1606
|
</div>
|
|
1526
1607
|
</div>
|
|
1527
1608
|
</div>
|
|
@@ -1813,18 +1894,20 @@ class MapEngineCyberia {
|
|
|
1813
1894
|
<div class="in ${entityListId}" style="margin-top: 10px; max-height: 200px; overflow-y: auto;"></div>
|
|
1814
1895
|
${dynamicCol({ containerSelector: 'map-engine-container', id: dcSaveNew, type: 'search-inputs' })}
|
|
1815
1896
|
<div class="fl" style="margin-top: 10px;">
|
|
1816
|
-
|
|
1817
|
-
${
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1897
|
+
${canMutate
|
|
1898
|
+
? html`<div class="in fll ${dcSaveNew}-col-a" style="padding: 5px;">
|
|
1899
|
+
${await BtnIcon.instance({
|
|
1900
|
+
class: 'wfa btn-map-engine-save-map',
|
|
1901
|
+
label: html`<i class="fa-solid fa-floppy-disk"></i> Save Map`,
|
|
1902
|
+
})}
|
|
1903
|
+
</div>
|
|
1904
|
+
<div class="in fll ${dcSaveNew}-col-b" style="padding: 5px;">
|
|
1905
|
+
${await BtnIcon.instance({
|
|
1906
|
+
class: 'wfa btn-map-engine-clone-map',
|
|
1907
|
+
label: html`<i class="fa-solid fa-clone"></i> Clone Map`,
|
|
1908
|
+
})}
|
|
1909
|
+
</div>`
|
|
1910
|
+
: ''}
|
|
1828
1911
|
<div class="in fll ${dcSaveNew}-col-c" style="padding: 5px;">
|
|
1829
1912
|
${await BtnIcon.instance({
|
|
1830
1913
|
class: 'wfa btn-map-engine-new-map',
|