@underpostnet/cyberia 3.2.80

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.
Files changed (821) hide show
  1. package/.dockerignore +14 -0
  2. package/.env.example +144 -0
  3. package/.github/workflows/cyberia-client.cd.yml +40 -0
  4. package/.github/workflows/cyberia-server.cd.yml +40 -0
  5. package/.github/workflows/docker-image.cyberia-client.ci.yml +71 -0
  6. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +70 -0
  7. package/.github/workflows/docker-image.cyberia-server.ci.yml +71 -0
  8. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +71 -0
  9. package/.github/workflows/docker-image.engine-cyberia.ci.yml +53 -0
  10. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +53 -0
  11. package/.github/workflows/engine-cyberia.cd.yml +157 -0
  12. package/.github/workflows/engine-cyberia.ci.yml +125 -0
  13. package/.github/workflows/ghpkg.ci.yml +160 -0
  14. package/.github/workflows/gitlab.ci.yml +20 -0
  15. package/.github/workflows/hardhat.ci.yml +82 -0
  16. package/.github/workflows/npmpkg.ci.yml +126 -0
  17. package/.github/workflows/publish.ci.yml +87 -0
  18. package/.github/workflows/publish.cyberia.ci.yml +79 -0
  19. package/.github/workflows/pwa-microservices-template-page.cd.yml +65 -0
  20. package/.github/workflows/pwa-microservices-template-test.ci.yml +33 -0
  21. package/.github/workflows/release.cd.yml +46 -0
  22. package/.nycrc +9 -0
  23. package/.prettierignore +12 -0
  24. package/.prettierrc +9 -0
  25. package/.vscode/extensions.json +10 -0
  26. package/.vscode/settings.json +26 -0
  27. package/CHANGELOG.md +2516 -0
  28. package/CLI-HELP.md +1099 -0
  29. package/Dockerfile +161 -0
  30. package/Dockerfile.dev +161 -0
  31. package/Dockerfile.test +165 -0
  32. package/LICENSE +21 -0
  33. package/README.md +259 -0
  34. package/baremetal/commission-workflows.json +211 -0
  35. package/baremetal/packer-workflows.json +24 -0
  36. package/bin/build.js +261 -0
  37. package/bin/build.template.js +33 -0
  38. package/bin/cyberia.js +5627 -0
  39. package/bin/deploy.js +1547 -0
  40. package/bin/index.js +5627 -0
  41. package/bump.config.js +27 -0
  42. package/compose.env +144 -0
  43. package/conf.js +952 -0
  44. package/deployment.yaml +418 -0
  45. package/docker-compose.yml +434 -0
  46. package/examples/static-page/README.md +150 -0
  47. package/examples/static-page/ssr-components/CustomPage.js +554 -0
  48. package/examples/static-page/static-config-example.json +57 -0
  49. package/hardhat/.env.example +31 -0
  50. package/hardhat/contracts/ObjectLayerToken.sol +391 -0
  51. package/hardhat/deployments/.gitkeep +0 -0
  52. package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
  53. package/hardhat/hardhat.config.js +136 -0
  54. package/hardhat/ignition/modules/.gitkeep +0 -0
  55. package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
  56. package/hardhat/networks/besu-object-layer.network.json +138 -0
  57. package/hardhat/package-lock.json +2871 -0
  58. package/hardhat/package.json +43 -0
  59. package/hardhat/scripts/deployObjectLayerToken.js +98 -0
  60. package/hardhat/test/ObjectLayerToken.js +696 -0
  61. package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
  62. package/hardhat/types/ethers-contracts/common.ts +92 -0
  63. package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
  64. package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
  65. package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
  66. package/hardhat/types/ethers-contracts/index.ts +6 -0
  67. package/ipfs/configure-ipfs.sh +13 -0
  68. package/jsconfig.json +9 -0
  69. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +48 -0
  70. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +48 -0
  71. package/manifests/deployment/adminer/deployment.yaml +32 -0
  72. package/manifests/deployment/adminer/kustomization.yaml +7 -0
  73. package/manifests/deployment/adminer/service.yaml +13 -0
  74. package/manifests/deployment/dd-cyberia-development/deployment.yaml +418 -0
  75. package/manifests/deployment/dd-cyberia-development/grpc-service.yaml +17 -0
  76. package/manifests/deployment/dd-cyberia-development/proxy.yaml +189 -0
  77. package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +164 -0
  78. package/manifests/deployment/dd-default-development/deployment.yaml +163 -0
  79. package/manifests/deployment/dd-default-development/proxy.yaml +46 -0
  80. package/manifests/deployment/fastapi/backend-deployment.yml +120 -0
  81. package/manifests/deployment/fastapi/backend-service.yml +19 -0
  82. package/manifests/deployment/fastapi/frontend-deployment.yml +54 -0
  83. package/manifests/deployment/fastapi/frontend-service.yml +15 -0
  84. package/manifests/deployment/fastapi/initial_data.sh +8 -0
  85. package/manifests/deployment/kafka/deployment.yaml +67 -0
  86. package/manifests/deployment/mongo-express/deployment.yaml +62 -0
  87. package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
  88. package/manifests/deployment/playwright/deployment.yaml +52 -0
  89. package/manifests/deployment/spark/spark-pi-py.yaml +20 -0
  90. package/manifests/deployment/tensorflow/tf-gpu-test.yaml +63 -0
  91. package/manifests/envoy-service-nodeport.yaml +22 -0
  92. package/manifests/grafana/deployment.yaml +64 -0
  93. package/manifests/grafana/kustomization.yaml +7 -0
  94. package/manifests/grafana/pvc.yaml +12 -0
  95. package/manifests/grafana/service.yaml +14 -0
  96. package/manifests/grafana/storage-class.yaml +9 -0
  97. package/manifests/ipfs/configmap.yaml +64 -0
  98. package/manifests/ipfs/headless-service.yaml +35 -0
  99. package/manifests/ipfs/kustomization.yaml +8 -0
  100. package/manifests/ipfs/statefulset.yaml +149 -0
  101. package/manifests/ipfs/storage-class.yaml +9 -0
  102. package/manifests/kind-config-dev.yaml +20 -0
  103. package/manifests/kind-config.yaml +12 -0
  104. package/manifests/kubeadm-calico-config.yaml +14 -0
  105. package/manifests/letsencrypt-prod.yaml +14 -0
  106. package/manifests/lxd/lxd-admin-profile.yaml +26 -0
  107. package/manifests/lxd/lxd-preseed.yaml +30 -0
  108. package/manifests/mariadb/kustomization.yaml +9 -0
  109. package/manifests/mariadb/pv.yaml +12 -0
  110. package/manifests/mariadb/pvc.yaml +10 -0
  111. package/manifests/mariadb/service.yaml +10 -0
  112. package/manifests/mariadb/statefulset.yaml +56 -0
  113. package/manifests/mariadb/storage-class.yaml +10 -0
  114. package/manifests/mongodb/headless-service.yaml +10 -0
  115. package/manifests/mongodb/kustomization.yaml +11 -0
  116. package/manifests/mongodb/pv-pvc.yaml +59 -0
  117. package/manifests/mongodb/statefulset.yaml +113 -0
  118. package/manifests/mongodb/storage-class.yaml +9 -0
  119. package/manifests/mongodb-4.4/headless-service.yaml +10 -0
  120. package/manifests/mongodb-4.4/kustomization.yaml +9 -0
  121. package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
  122. package/manifests/mongodb-4.4/pv-pvc.yaml +19 -0
  123. package/manifests/mongodb-4.4/service-deployment.yaml +61 -0
  124. package/manifests/mongodb-4.4/statefulset.yaml +79 -0
  125. package/manifests/mongodb-4.4/storage-class.yaml +9 -0
  126. package/manifests/mysql/kustomization.yaml +7 -0
  127. package/manifests/mysql/pv-pvc.yaml +27 -0
  128. package/manifests/mysql/statefulset.yaml +55 -0
  129. package/manifests/postgresql/configmap.yaml +9 -0
  130. package/manifests/postgresql/kustomization.yaml +10 -0
  131. package/manifests/postgresql/pv.yaml +15 -0
  132. package/manifests/postgresql/pvc.yaml +13 -0
  133. package/manifests/postgresql/service.yaml +10 -0
  134. package/manifests/postgresql/statefulset.yaml +37 -0
  135. package/manifests/prometheus/deployment.yaml +82 -0
  136. package/manifests/pv-pvc-dd.yaml +34 -0
  137. package/manifests/valkey/kustomization.yaml +7 -0
  138. package/manifests/valkey/service.yaml +10 -0
  139. package/manifests/valkey/statefulset.yaml +37 -0
  140. package/manifests/valkey/valkey-nodeport.yaml +17 -0
  141. package/mongodb/entrypoint.sh +76 -0
  142. package/nginx.conf +128 -0
  143. package/nodemon.json +6 -0
  144. package/package.json +101 -0
  145. package/packer/images/Rocky9Amd64/Makefile +62 -0
  146. package/packer/images/Rocky9Amd64/QUICKSTART.md +113 -0
  147. package/packer/images/Rocky9Amd64/README.md +122 -0
  148. package/packer/images/Rocky9Amd64/http/rocky9.ks.pkrtpl.hcl +114 -0
  149. package/packer/images/Rocky9Amd64/rocky9.pkr.hcl +164 -0
  150. package/packer/images/Rocky9Arm64/Makefile +69 -0
  151. package/packer/images/Rocky9Arm64/README.md +122 -0
  152. package/packer/images/Rocky9Arm64/http/rocky9.ks.pkrtpl.hcl +114 -0
  153. package/packer/images/Rocky9Arm64/rocky9.pkr.hcl +171 -0
  154. package/packer/scripts/fuse-nbd +64 -0
  155. package/packer/scripts/fuse-tar-root +63 -0
  156. package/proxy.yaml +189 -0
  157. package/pv-pvc.yaml +164 -0
  158. package/scripts/device-scan.sh +65 -0
  159. package/scripts/disk-clean.sh +182 -0
  160. package/scripts/disk-devices.sh +13 -0
  161. package/scripts/gen-fqdns.sh +14 -0
  162. package/scripts/gpu-diag.sh +19 -0
  163. package/scripts/ip-info.sh +118 -0
  164. package/scripts/ipxe-setup.sh +200 -0
  165. package/scripts/k3s-node-setup.sh +124 -0
  166. package/scripts/kubeadm-node-setup.sh +317 -0
  167. package/scripts/link-local-underpost-cli.sh +6 -0
  168. package/scripts/lxd-vm-setup.sh +208 -0
  169. package/scripts/maas-nat-firewalld.sh +145 -0
  170. package/scripts/maas-setup.sh +135 -0
  171. package/scripts/maas-upload-boot-resource.sh +183 -0
  172. package/scripts/nat-iptables.sh +111 -0
  173. package/scripts/nvim.sh +91 -0
  174. package/scripts/packer-init-vars-file.sh +40 -0
  175. package/scripts/packer-setup.sh +289 -0
  176. package/scripts/ports-ls.sh +33 -0
  177. package/scripts/quick-tftp.sh +19 -0
  178. package/scripts/rhel-grpc-setup.sh +56 -0
  179. package/scripts/rocky-kickstart.sh +986 -0
  180. package/scripts/rocky-pwa.sh +200 -0
  181. package/scripts/rocky-setup.sh +106 -0
  182. package/scripts/rpmfusion-ffmpeg-setup.sh +32 -0
  183. package/scripts/ssl.sh +170 -0
  184. package/scripts/test-monitor.sh +248 -0
  185. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +30 -0
  186. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +155 -0
  187. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +39 -0
  188. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +382 -0
  189. package/src/api/core/core.controller.js +8 -0
  190. package/src/api/core/core.model.js +11 -0
  191. package/src/api/core/core.router.js +23 -0
  192. package/src/api/core/core.service.js +30 -0
  193. package/src/api/crypto/crypto.controller.js +10 -0
  194. package/src/api/crypto/crypto.model.js +23 -0
  195. package/src/api/crypto/crypto.router.js +23 -0
  196. package/src/api/crypto/crypto.service.js +64 -0
  197. package/src/api/cyberia-action/cyberia-action.controller.js +8 -0
  198. package/src/api/cyberia-action/cyberia-action.model.js +79 -0
  199. package/src/api/cyberia-action/cyberia-action.router.js +21 -0
  200. package/src/api/cyberia-action/cyberia-action.service.js +58 -0
  201. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +27 -0
  202. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +100 -0
  203. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +70 -0
  204. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +152 -0
  205. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +8 -0
  206. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
  207. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +20 -0
  208. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +57 -0
  209. package/src/api/cyberia-entity/cyberia-entity.controller.js +6 -0
  210. package/src/api/cyberia-entity/cyberia-entity.model.js +25 -0
  211. package/src/api/cyberia-entity/cyberia-entity.router.js +17 -0
  212. package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
  213. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +6 -0
  214. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +67 -0
  215. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +17 -0
  216. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +46 -0
  217. package/src/api/cyberia-instance/cyberia-fallback-world.js +337 -0
  218. package/src/api/cyberia-instance/cyberia-instance-boot.service.js +57 -0
  219. package/src/api/cyberia-instance/cyberia-instance-map.service.js +583 -0
  220. package/src/api/cyberia-instance/cyberia-instance.controller.js +42 -0
  221. package/src/api/cyberia-instance/cyberia-instance.model.js +117 -0
  222. package/src/api/cyberia-instance/cyberia-instance.router.js +75 -0
  223. package/src/api/cyberia-instance/cyberia-instance.service.js +190 -0
  224. package/src/api/cyberia-instance/cyberia-portal-connector.js +260 -0
  225. package/src/api/cyberia-instance/cyberia-world-generator.js +618 -0
  226. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +6 -0
  227. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +200 -0
  228. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +17 -0
  229. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +46 -0
  230. package/src/api/cyberia-map/cyberia-map.controller.js +6 -0
  231. package/src/api/cyberia-map/cyberia-map.model.js +33 -0
  232. package/src/api/cyberia-map/cyberia-map.router.js +19 -0
  233. package/src/api/cyberia-map/cyberia-map.service.js +76 -0
  234. package/src/api/cyberia-quest/cyberia-quest.controller.js +9 -0
  235. package/src/api/cyberia-quest/cyberia-quest.model.js +67 -0
  236. package/src/api/cyberia-quest/cyberia-quest.router.js +26 -0
  237. package/src/api/cyberia-quest/cyberia-quest.service.js +97 -0
  238. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +6 -0
  239. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +49 -0
  240. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +21 -0
  241. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +42 -0
  242. package/src/api/cyberia-saga/cyberia-saga.controller.js +6 -0
  243. package/src/api/cyberia-saga/cyberia-saga.model.js +59 -0
  244. package/src/api/cyberia-saga/cyberia-saga.router.js +17 -0
  245. package/src/api/cyberia-saga/cyberia-saga.service.js +42 -0
  246. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +1076 -0
  247. package/src/api/cyberia-skill/cyberia-skill.controller.js +6 -0
  248. package/src/api/cyberia-skill/cyberia-skill.model.js +50 -0
  249. package/src/api/cyberia-skill/cyberia-skill.router.js +17 -0
  250. package/src/api/cyberia-skill/cyberia-skill.service.js +42 -0
  251. package/src/api/default/default.controller.js +6 -0
  252. package/src/api/default/default.model.js +20 -0
  253. package/src/api/default/default.router.js +21 -0
  254. package/src/api/default/default.service.js +42 -0
  255. package/src/api/document/document.controller.js +9 -0
  256. package/src/api/document/document.model.js +95 -0
  257. package/src/api/document/document.router.js +32 -0
  258. package/src/api/document/document.service.js +633 -0
  259. package/src/api/file/file.controller.js +15 -0
  260. package/src/api/file/file.model.js +127 -0
  261. package/src/api/file/file.ref.json +39 -0
  262. package/src/api/file/file.router.js +36 -0
  263. package/src/api/file/file.service.js +499 -0
  264. package/src/api/instance/instance.controller.js +8 -0
  265. package/src/api/instance/instance.model.js +34 -0
  266. package/src/api/instance/instance.router.js +27 -0
  267. package/src/api/instance/instance.service.js +75 -0
  268. package/src/api/ipfs/ipfs.controller.js +8 -0
  269. package/src/api/ipfs/ipfs.model.js +77 -0
  270. package/src/api/ipfs/ipfs.router.js +26 -0
  271. package/src/api/ipfs/ipfs.service.js +145 -0
  272. package/src/api/object-layer/object-layer.controller.js +18 -0
  273. package/src/api/object-layer/object-layer.model.js +200 -0
  274. package/src/api/object-layer/object-layer.router.js +729 -0
  275. package/src/api/object-layer/object-layer.service.js +894 -0
  276. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +6 -0
  277. package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +93 -0
  278. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +17 -0
  279. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +46 -0
  280. package/src/api/test/test.controller.js +14 -0
  281. package/src/api/test/test.model.js +14 -0
  282. package/src/api/test/test.router.js +23 -0
  283. package/src/api/test/test.service.js +35 -0
  284. package/src/api/types.js +24 -0
  285. package/src/api/user/guest.service.js +100 -0
  286. package/src/api/user/postman_collection.json +216 -0
  287. package/src/api/user/user.build.js +16 -0
  288. package/src/api/user/user.controller.js +35 -0
  289. package/src/api/user/user.model.js +142 -0
  290. package/src/api/user/user.router.js +367 -0
  291. package/src/api/user/user.service.js +582 -0
  292. package/src/api.js +23 -0
  293. package/src/cli/baremetal.js +3947 -0
  294. package/src/cli/cloud-init.js +673 -0
  295. package/src/cli/cluster.js +1395 -0
  296. package/src/cli/db.js +1533 -0
  297. package/src/cli/deploy.js +1542 -0
  298. package/src/cli/docker-compose.js +802 -0
  299. package/src/cli/env.js +177 -0
  300. package/src/cli/fs.js +380 -0
  301. package/src/cli/image.js +389 -0
  302. package/src/cli/index.js +1059 -0
  303. package/src/cli/ipfs.js +182 -0
  304. package/src/cli/kickstart.js +271 -0
  305. package/src/cli/kubectl.js +214 -0
  306. package/src/cli/lxd.js +1232 -0
  307. package/src/cli/monitor.js +659 -0
  308. package/src/cli/release.js +595 -0
  309. package/src/cli/repository.js +1969 -0
  310. package/src/cli/run.js +3326 -0
  311. package/src/cli/secrets.js +151 -0
  312. package/src/cli/ssh.js +975 -0
  313. package/src/cli/static.js +653 -0
  314. package/src/cli/system.js +332 -0
  315. package/src/cli/test.js +176 -0
  316. package/src/client/Cryptokoyn.index.js +30 -0
  317. package/src/client/CyberiaPortal.index.js +31 -0
  318. package/src/client/Default.index.js +77 -0
  319. package/src/client/Itemledger.index.js +35 -0
  320. package/src/client/Underpost.index.js +31 -0
  321. package/src/client/components/core/404.js +20 -0
  322. package/src/client/components/core/500.js +20 -0
  323. package/src/client/components/core/Account.js +630 -0
  324. package/src/client/components/core/AgGrid.js +238 -0
  325. package/src/client/components/core/Alert.js +76 -0
  326. package/src/client/components/core/AppStore.js +69 -0
  327. package/src/client/components/core/Auth.js +353 -0
  328. package/src/client/components/core/Badge.js +26 -0
  329. package/src/client/components/core/Blockchain.js +41 -0
  330. package/src/client/components/core/Blog.js +9 -0
  331. package/src/client/components/core/BtnIcon.js +109 -0
  332. package/src/client/components/core/CalendarCore.js +437 -0
  333. package/src/client/components/core/Chat.js +62 -0
  334. package/src/client/components/core/ClientEvents.js +163 -0
  335. package/src/client/components/core/ColorPaletteElement.js +309 -0
  336. package/src/client/components/core/CommonJs.js +1014 -0
  337. package/src/client/components/core/Content.js +349 -0
  338. package/src/client/components/core/Css.js +1134 -0
  339. package/src/client/components/core/CssCore.js +881 -0
  340. package/src/client/components/core/D3Chart.js +44 -0
  341. package/src/client/components/core/Docs.js +478 -0
  342. package/src/client/components/core/DropDown.js +321 -0
  343. package/src/client/components/core/EventBus.js +96 -0
  344. package/src/client/components/core/EventsUI.js +130 -0
  345. package/src/client/components/core/FileExplorer.js +1406 -0
  346. package/src/client/components/core/FullScreen.js +201 -0
  347. package/src/client/components/core/Input.js +537 -0
  348. package/src/client/components/core/Keyboard.js +80 -0
  349. package/src/client/components/core/KeyboardAvoidance.js +145 -0
  350. package/src/client/components/core/LoadingAnimation.js +152 -0
  351. package/src/client/components/core/LogIn.js +212 -0
  352. package/src/client/components/core/LogOut.js +72 -0
  353. package/src/client/components/core/Logger.js +22 -0
  354. package/src/client/components/core/Modal.js +2956 -0
  355. package/src/client/components/core/NotificationManager.js +80 -0
  356. package/src/client/components/core/Pagination.js +252 -0
  357. package/src/client/components/core/Panel.js +1308 -0
  358. package/src/client/components/core/PanelForm.js +915 -0
  359. package/src/client/components/core/Polyhedron.js +947 -0
  360. package/src/client/components/core/PublicProfile.js +895 -0
  361. package/src/client/components/core/Recover.js +211 -0
  362. package/src/client/components/core/Responsive.js +146 -0
  363. package/src/client/components/core/RichText.js +33 -0
  364. package/src/client/components/core/Router.js +523 -0
  365. package/src/client/components/core/Scroll.js +76 -0
  366. package/src/client/components/core/SearchBox.js +1007 -0
  367. package/src/client/components/core/SignUp.js +153 -0
  368. package/src/client/components/core/SocketIo.js +163 -0
  369. package/src/client/components/core/SocketIoHandler.js +75 -0
  370. package/src/client/components/core/Stream.js +161 -0
  371. package/src/client/components/core/ToggleSwitch.js +89 -0
  372. package/src/client/components/core/ToolTip.js +78 -0
  373. package/src/client/components/core/Translate.js +694 -0
  374. package/src/client/components/core/Validator.js +140 -0
  375. package/src/client/components/core/VanillaJs.js +485 -0
  376. package/src/client/components/core/Wallet.js +95 -0
  377. package/src/client/components/core/WebComponent.js +44 -0
  378. package/src/client/components/core/Webhook.js +58 -0
  379. package/src/client/components/core/Worker.js +313 -0
  380. package/src/client/components/core/windowGetDimensions.js +269 -0
  381. package/src/client/components/cryptokoyn/AppShellCryptokoyn.js +352 -0
  382. package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
  383. package/src/client/components/cryptokoyn/CssCryptokoyn.js +212 -0
  384. package/src/client/components/cryptokoyn/LogInCryptokoyn.js +16 -0
  385. package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +12 -0
  386. package/src/client/components/cryptokoyn/RouterCryptokoyn.js +37 -0
  387. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +16 -0
  388. package/src/client/components/cryptokoyn/SignUpCryptokoyn.js +11 -0
  389. package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +6 -0
  390. package/src/client/components/cyberia/ActionEngineCyberia.js +1867 -0
  391. package/src/client/components/cyberia/EntityEngineCyberia.js +585 -0
  392. package/src/client/components/cyberia/InstanceEngineCyberia.js +1088 -0
  393. package/src/client/components/cyberia/InstanceSelectionView.js +900 -0
  394. package/src/client/components/cyberia/MapEngineCyberia.js +1976 -0
  395. package/src/client/components/cyberia/ObjectLayerEngine.js +1540 -0
  396. package/src/client/components/cyberia/ObjectLayerEngineModal.js +2420 -0
  397. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +1522 -0
  398. package/src/client/components/cyberia/SharedDefaultsCyberia.js +528 -0
  399. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +772 -0
  400. package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
  401. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +254 -0
  402. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +21 -0
  403. package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +16 -0
  404. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +518 -0
  405. package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +72 -0
  406. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +16 -0
  407. package/src/client/components/cyberia-portal/SignUpCyberiaPortal.js +13 -0
  408. package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +6 -0
  409. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +48 -0
  410. package/src/client/components/default/AppShellDefault.js +765 -0
  411. package/src/client/components/default/AppStoreDefault.js +5 -0
  412. package/src/client/components/default/CommonDefault.js +29 -0
  413. package/src/client/components/default/CssDefault.js +27 -0
  414. package/src/client/components/default/LogInDefault.js +16 -0
  415. package/src/client/components/default/LogOutDefault.js +12 -0
  416. package/src/client/components/default/RouterDefault.js +47 -0
  417. package/src/client/components/default/SettingsDefault.js +16 -0
  418. package/src/client/components/default/SignUpDefault.js +11 -0
  419. package/src/client/components/default/SocketIoDefault.js +6 -0
  420. package/src/client/components/default/TranslateDefault.js +7 -0
  421. package/src/client/components/itemledger/AppShellItemledger.js +353 -0
  422. package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
  423. package/src/client/components/itemledger/CssItemledger.js +212 -0
  424. package/src/client/components/itemledger/LogInItemledger.js +17 -0
  425. package/src/client/components/itemledger/LogOutItemledger.js +12 -0
  426. package/src/client/components/itemledger/RouterItemledger.js +38 -0
  427. package/src/client/components/itemledger/SettingsItemledger.js +16 -0
  428. package/src/client/components/itemledger/SignUpItemledger.js +11 -0
  429. package/src/client/components/itemledger/SocketIoItemledger.js +6 -0
  430. package/src/client/components/itemledger/TranslateItemledger.js +7 -0
  431. package/src/client/components/underpost/AppShellUnderpost.js +691 -0
  432. package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
  433. package/src/client/components/underpost/CssUnderpost.js +281 -0
  434. package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +879 -0
  435. package/src/client/components/underpost/DocumentSearchProvider.js +448 -0
  436. package/src/client/components/underpost/LabGalleryUnderpost.js +79 -0
  437. package/src/client/components/underpost/LogInUnderpost.js +25 -0
  438. package/src/client/components/underpost/LogOutUnderpost.js +17 -0
  439. package/src/client/components/underpost/RouterUnderpost.js +45 -0
  440. package/src/client/components/underpost/SettingsUnderpost.js +16 -0
  441. package/src/client/components/underpost/SignUpUnderpost.js +11 -0
  442. package/src/client/components/underpost/SocketIoUnderpost.js +6 -0
  443. package/src/client/components/underpost/TranslateUnderpost.js +10 -0
  444. package/src/client/public/cryptokoyn/assets/banner/koyn-social.png +0 -0
  445. package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
  446. package/src/client/public/cryptokoyn/assets/logo/cryptokoyn.png +0 -0
  447. package/src/client/public/cryptokoyn/assets/splash/android-chrome-144x144.png +0 -0
  448. package/src/client/public/cryptokoyn/assets/splash/android-chrome-192x192.png +0 -0
  449. package/src/client/public/cryptokoyn/assets/splash/android-chrome-256x256.png +0 -0
  450. package/src/client/public/cryptokoyn/assets/splash/android-chrome-36x36.png +0 -0
  451. package/src/client/public/cryptokoyn/assets/splash/android-chrome-48x48.png +0 -0
  452. package/src/client/public/cryptokoyn/assets/splash/android-chrome-72x72.png +0 -0
  453. package/src/client/public/cryptokoyn/assets/splash/android-chrome-96x96.png +0 -0
  454. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-114x114-precomposed.png +0 -0
  455. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-114x114.png +0 -0
  456. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-120x120-precomposed.png +0 -0
  457. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-120x120.png +0 -0
  458. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-144x144-precomposed.png +0 -0
  459. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-144x144.png +0 -0
  460. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-152x152-precomposed.png +0 -0
  461. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-152x152.png +0 -0
  462. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-180x180-precomposed.png +0 -0
  463. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-180x180.png +0 -0
  464. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-57x57-precomposed.png +0 -0
  465. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-57x57.png +0 -0
  466. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-60x60-precomposed.png +0 -0
  467. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-60x60.png +0 -0
  468. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-72x72-precomposed.png +0 -0
  469. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-72x72.png +0 -0
  470. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-76x76-precomposed.png +0 -0
  471. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-76x76.png +0 -0
  472. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-precomposed.png +0 -0
  473. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon.png +0 -0
  474. package/src/client/public/cryptokoyn/assets/splash/favicon-16x16.png +0 -0
  475. package/src/client/public/cryptokoyn/assets/splash/favicon-32x32.png +0 -0
  476. package/src/client/public/cryptokoyn/assets/splash/mstile-144x144.png +0 -0
  477. package/src/client/public/cryptokoyn/assets/splash/mstile-150x150.png +0 -0
  478. package/src/client/public/cryptokoyn/assets/splash/mstile-310x150.png +0 -0
  479. package/src/client/public/cryptokoyn/assets/splash/mstile-310x310.png +0 -0
  480. package/src/client/public/cryptokoyn/assets/splash/mstile-70x70.png +0 -0
  481. package/src/client/public/cryptokoyn/assets/splash/safari-pinned-tab.svg +42 -0
  482. package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
  483. package/src/client/public/cryptokoyn/favicon.ico +0 -0
  484. package/src/client/public/cryptokoyn/microdata.json +85 -0
  485. package/src/client/public/cryptokoyn/site.webmanifest +57 -0
  486. package/src/client/public/cryptokoyn/sitemap +148 -0
  487. package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +307 -0
  488. package/src/client/public/cyberia-docs/ARCHITECTURE.md +309 -0
  489. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +204 -0
  490. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +341 -0
  491. package/src/client/public/cyberia-docs/CYBERIA-LORE.md +84 -0
  492. package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +394 -0
  493. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +294 -0
  494. package/src/client/public/cyberia-docs/CYBERIA.md +259 -0
  495. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +242 -0
  496. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +300 -0
  497. package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +309 -0
  498. package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +228 -0
  499. package/src/client/public/cyberia-docs/ROADMAP.md +240 -0
  500. package/src/client/public/cyberia-docs/UNDERPOST-PLATFORM.md +106 -0
  501. package/src/client/public/cyberia-docs/WHITE-PAPER.md +740 -0
  502. package/src/client/public/default/android-chrome-144x144.png +0 -0
  503. package/src/client/public/default/android-chrome-192x192.png +0 -0
  504. package/src/client/public/default/android-chrome-256x256.png +0 -0
  505. package/src/client/public/default/android-chrome-36x36.png +0 -0
  506. package/src/client/public/default/android-chrome-384x384.png +0 -0
  507. package/src/client/public/default/android-chrome-48x48.png +0 -0
  508. package/src/client/public/default/android-chrome-512x512.png +0 -0
  509. package/src/client/public/default/android-chrome-72x72.png +0 -0
  510. package/src/client/public/default/android-chrome-96x96.png +0 -0
  511. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  512. package/src/client/public/default/apple-touch-icon-114x114-precomposed.png +0 -0
  513. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  514. package/src/client/public/default/apple-touch-icon-120x120-precomposed.png +0 -0
  515. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  516. package/src/client/public/default/apple-touch-icon-144x144-precomposed.png +0 -0
  517. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  518. package/src/client/public/default/apple-touch-icon-152x152-precomposed.png +0 -0
  519. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  520. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  521. package/src/client/public/default/apple-touch-icon-180x180-precomposed.png +0 -0
  522. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  523. package/src/client/public/default/apple-touch-icon-57x57-precomposed.png +0 -0
  524. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  525. package/src/client/public/default/apple-touch-icon-60x60-precomposed.png +0 -0
  526. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  527. package/src/client/public/default/apple-touch-icon-72x72-precomposed.png +0 -0
  528. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  529. package/src/client/public/default/apple-touch-icon-76x76-precomposed.png +0 -0
  530. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  531. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  532. package/src/client/public/default/apple-touch-icon.png +0 -0
  533. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  534. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  535. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  536. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  537. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  538. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  539. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  540. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  541. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  542. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  543. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  544. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  545. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  546. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  547. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  548. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  549. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  550. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  551. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  552. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  553. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  554. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  555. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  556. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  557. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  558. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  559. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  560. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  561. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  562. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  563. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  564. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  565. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  566. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  567. package/src/client/public/default/assets/background/dark.jpg +0 -0
  568. package/src/client/public/default/assets/background/dark.svg +557 -0
  569. package/src/client/public/default/assets/background/white.jpg +0 -0
  570. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  571. package/src/client/public/default/assets/background/white0.jpg +0 -0
  572. package/src/client/public/default/assets/logo/base-icon.png +0 -0
  573. package/src/client/public/default/assets/logo/underpost.gif +0 -0
  574. package/src/client/public/default/assets/mailer/api-user-check.png +0 -0
  575. package/src/client/public/default/assets/mailer/api-user-default-avatar.png +0 -0
  576. package/src/client/public/default/assets/mailer/api-user-invalid-token.png +0 -0
  577. package/src/client/public/default/assets/mailer/api-user-recover.png +0 -0
  578. package/src/client/public/default/browserconfig.xml +12 -0
  579. package/src/client/public/default/favicon-16x16.png +0 -0
  580. package/src/client/public/default/favicon-32x32.png +0 -0
  581. package/src/client/public/default/favicon-48x48.png +0 -0
  582. package/src/client/public/default/favicon.ico +0 -0
  583. package/src/client/public/default/manifest.webmanifest +69 -0
  584. package/src/client/public/default/mstile-144x144.png +0 -0
  585. package/src/client/public/default/mstile-150x150.png +0 -0
  586. package/src/client/public/default/mstile-310x150.png +0 -0
  587. package/src/client/public/default/mstile-310x310.png +0 -0
  588. package/src/client/public/default/mstile-70x70.png +0 -0
  589. package/src/client/public/default/safari-pinned-tab.svg +24 -0
  590. package/src/client/public/default/site.webmanifest +69 -0
  591. package/src/client/public/default/sitemap +148 -0
  592. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  593. package/src/client/public/default/yandex-browser-manifest.json +9 -0
  594. package/src/client/public/doc/favicon.ico +0 -0
  595. package/src/client/public/doc/sitemap +148 -0
  596. package/src/client/public/itemledger/android-chrome-144x144.png +0 -0
  597. package/src/client/public/itemledger/android-chrome-192x192.png +0 -0
  598. package/src/client/public/itemledger/android-chrome-256x256.png +0 -0
  599. package/src/client/public/itemledger/android-chrome-36x36.png +0 -0
  600. package/src/client/public/itemledger/android-chrome-384x384.png +0 -0
  601. package/src/client/public/itemledger/android-chrome-48x48.png +0 -0
  602. package/src/client/public/itemledger/android-chrome-512x512.png +0 -0
  603. package/src/client/public/itemledger/android-chrome-72x72.png +0 -0
  604. package/src/client/public/itemledger/android-chrome-96x96.png +0 -0
  605. package/src/client/public/itemledger/apple-touch-icon-1024x1024.png +0 -0
  606. package/src/client/public/itemledger/apple-touch-icon-114x114.png +0 -0
  607. package/src/client/public/itemledger/apple-touch-icon-120x120.png +0 -0
  608. package/src/client/public/itemledger/apple-touch-icon-144x144.png +0 -0
  609. package/src/client/public/itemledger/apple-touch-icon-152x152.png +0 -0
  610. package/src/client/public/itemledger/apple-touch-icon-167x167.png +0 -0
  611. package/src/client/public/itemledger/apple-touch-icon-180x180.png +0 -0
  612. package/src/client/public/itemledger/apple-touch-icon-57x57.png +0 -0
  613. package/src/client/public/itemledger/apple-touch-icon-60x60.png +0 -0
  614. package/src/client/public/itemledger/apple-touch-icon-72x72.png +0 -0
  615. package/src/client/public/itemledger/apple-touch-icon-76x76.png +0 -0
  616. package/src/client/public/itemledger/apple-touch-icon-precomposed.png +0 -0
  617. package/src/client/public/itemledger/apple-touch-icon.png +0 -0
  618. package/src/client/public/itemledger/apple-touch-startup-image-1125x2436.png +0 -0
  619. package/src/client/public/itemledger/apple-touch-startup-image-1136x640.png +0 -0
  620. package/src/client/public/itemledger/apple-touch-startup-image-1170x2532.png +0 -0
  621. package/src/client/public/itemledger/apple-touch-startup-image-1179x2556.png +0 -0
  622. package/src/client/public/itemledger/apple-touch-startup-image-1242x2208.png +0 -0
  623. package/src/client/public/itemledger/apple-touch-startup-image-1242x2688.png +0 -0
  624. package/src/client/public/itemledger/apple-touch-startup-image-1284x2778.png +0 -0
  625. package/src/client/public/itemledger/apple-touch-startup-image-1290x2796.png +0 -0
  626. package/src/client/public/itemledger/apple-touch-startup-image-1334x750.png +0 -0
  627. package/src/client/public/itemledger/apple-touch-startup-image-1488x2266.png +0 -0
  628. package/src/client/public/itemledger/apple-touch-startup-image-1536x2048.png +0 -0
  629. package/src/client/public/itemledger/apple-touch-startup-image-1620x2160.png +0 -0
  630. package/src/client/public/itemledger/apple-touch-startup-image-1640x2160.png +0 -0
  631. package/src/client/public/itemledger/apple-touch-startup-image-1668x2224.png +0 -0
  632. package/src/client/public/itemledger/apple-touch-startup-image-1668x2388.png +0 -0
  633. package/src/client/public/itemledger/apple-touch-startup-image-1792x828.png +0 -0
  634. package/src/client/public/itemledger/apple-touch-startup-image-2048x1536.png +0 -0
  635. package/src/client/public/itemledger/apple-touch-startup-image-2048x2732.png +0 -0
  636. package/src/client/public/itemledger/apple-touch-startup-image-2160x1620.png +0 -0
  637. package/src/client/public/itemledger/apple-touch-startup-image-2160x1640.png +0 -0
  638. package/src/client/public/itemledger/apple-touch-startup-image-2208x1242.png +0 -0
  639. package/src/client/public/itemledger/apple-touch-startup-image-2224x1668.png +0 -0
  640. package/src/client/public/itemledger/apple-touch-startup-image-2266x1488.png +0 -0
  641. package/src/client/public/itemledger/apple-touch-startup-image-2388x1668.png +0 -0
  642. package/src/client/public/itemledger/apple-touch-startup-image-2436x1125.png +0 -0
  643. package/src/client/public/itemledger/apple-touch-startup-image-2532x1170.png +0 -0
  644. package/src/client/public/itemledger/apple-touch-startup-image-2556x1179.png +0 -0
  645. package/src/client/public/itemledger/apple-touch-startup-image-2688x1242.png +0 -0
  646. package/src/client/public/itemledger/apple-touch-startup-image-2732x2048.png +0 -0
  647. package/src/client/public/itemledger/apple-touch-startup-image-2778x1284.png +0 -0
  648. package/src/client/public/itemledger/apple-touch-startup-image-2796x1290.png +0 -0
  649. package/src/client/public/itemledger/apple-touch-startup-image-640x1136.png +0 -0
  650. package/src/client/public/itemledger/apple-touch-startup-image-750x1334.png +0 -0
  651. package/src/client/public/itemledger/apple-touch-startup-image-828x1792.png +0 -0
  652. package/src/client/public/itemledger/assets/logo/base-icon.png +0 -0
  653. package/src/client/public/itemledger/browserconfig.xml +12 -0
  654. package/src/client/public/itemledger/favicon-16x16.png +0 -0
  655. package/src/client/public/itemledger/favicon-32x32.png +0 -0
  656. package/src/client/public/itemledger/favicon-48x48.png +0 -0
  657. package/src/client/public/itemledger/favicon.ico +0 -0
  658. package/src/client/public/itemledger/manifest.webmanifest +69 -0
  659. package/src/client/public/itemledger/microdata.json +71 -0
  660. package/src/client/public/itemledger/mstile-144x144.png +0 -0
  661. package/src/client/public/itemledger/mstile-150x150.png +0 -0
  662. package/src/client/public/itemledger/mstile-310x150.png +0 -0
  663. package/src/client/public/itemledger/mstile-310x310.png +0 -0
  664. package/src/client/public/itemledger/mstile-70x70.png +0 -0
  665. package/src/client/public/itemledger/sitemap +148 -0
  666. package/src/client/public/itemledger/yandex-browser-50x50.png +0 -0
  667. package/src/client/public/itemledger/yandex-browser-manifest.json +9 -0
  668. package/src/client/public/test/favicon.ico +0 -0
  669. package/src/client/public/test/sitemap +148 -0
  670. package/src/client/services/atlas-sprite-sheet/atlas-sprite-sheet.service.js +137 -0
  671. package/src/client/services/core/core.service.js +309 -0
  672. package/src/client/services/crypto/crypto.service.js +68 -0
  673. package/src/client/services/cyberia-action/cyberia-action.service.js +99 -0
  674. package/src/client/services/cyberia-client-hints/cyberia-client-hints.service.js +99 -0
  675. package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +99 -0
  676. package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
  677. package/src/client/services/cyberia-entity/cyberia-entity.service.js +99 -0
  678. package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +99 -0
  679. package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
  680. package/src/client/services/cyberia-instance/cyberia-instance.service.js +137 -0
  681. package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +99 -0
  682. package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
  683. package/src/client/services/cyberia-map/cyberia-map.service.js +120 -0
  684. package/src/client/services/cyberia-quest/cyberia-quest.service.js +99 -0
  685. package/src/client/services/cyberia-quest-progress/cyberia-quest-progress.service.js +99 -0
  686. package/src/client/services/cyberia-saga/cyberia-saga.service.js +99 -0
  687. package/src/client/services/cyberia-skill/cyberia-skill.service.js +99 -0
  688. package/src/client/services/default/default.management.js +1015 -0
  689. package/src/client/services/default/default.service.js +99 -0
  690. package/src/client/services/document/document.service.js +134 -0
  691. package/src/client/services/file/file.service.js +94 -0
  692. package/src/client/services/instance/instance.management.js +78 -0
  693. package/src/client/services/instance/instance.service.js +107 -0
  694. package/src/client/services/ipfs/ipfs.service.js +118 -0
  695. package/src/client/services/object-layer/object-layer.management.js +414 -0
  696. package/src/client/services/object-layer/object-layer.service.js +208 -0
  697. package/src/client/services/object-layer-render-frames/object-layer-render-frames.service.js +99 -0
  698. package/src/client/services/test/test.service.js +68 -0
  699. package/src/client/services/user/guest.service.js +86 -0
  700. package/src/client/services/user/user.management.js +51 -0
  701. package/src/client/services/user/user.service.js +106 -0
  702. package/src/client/ssr/RootDocument.js +237 -0
  703. package/src/client/ssr/body/404.js +77 -0
  704. package/src/client/ssr/body/500.js +76 -0
  705. package/src/client/ssr/body/CacheControl.js +117 -0
  706. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +97 -0
  707. package/src/client/ssr/body/DefaultSplashScreen.js +97 -0
  708. package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
  709. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +90 -0
  710. package/src/client/ssr/head/CryptokoynScripts.js +4 -0
  711. package/src/client/ssr/head/Css.js +241 -0
  712. package/src/client/ssr/head/CyberiaPortalScripts.js +6 -0
  713. package/src/client/ssr/head/DefaultScripts.js +6 -0
  714. package/src/client/ssr/head/ItemledgerScripts.js +4 -0
  715. package/src/client/ssr/head/Microdata.js +11 -0
  716. package/src/client/ssr/head/Production.js +1 -0
  717. package/src/client/ssr/head/Pwa.js +146 -0
  718. package/src/client/ssr/head/PwaItemledger.js +197 -0
  719. package/src/client/ssr/head/Seo.js +15 -0
  720. package/src/client/ssr/head/UnderpostScripts.js +6 -0
  721. package/src/client/ssr/mailer/DefaultRecoverEmail.js +20 -0
  722. package/src/client/ssr/mailer/DefaultVerifyEmail.js +16 -0
  723. package/src/client/ssr/views/Cyberia404.js +328 -0
  724. package/src/client/ssr/views/CyberiaServerMetrics.js +1070 -0
  725. package/src/client/ssr/views/Maintenance.js +64 -0
  726. package/src/client/ssr/views/NoNetworkConnection.js +68 -0
  727. package/src/client/ssr/views/Test.js +199 -0
  728. package/src/client/sw/core.sw.js +274 -0
  729. package/src/client-builder/client-build-docs.js +493 -0
  730. package/src/client-builder/client-build-live.js +100 -0
  731. package/src/client-builder/client-build.js +1092 -0
  732. package/src/client-builder/client-dev-server.js +88 -0
  733. package/src/client-builder/client-formatted.js +170 -0
  734. package/src/client-builder/client-icons.js +108 -0
  735. package/src/client-builder/ssr.js +124 -0
  736. package/src/client.build.js +17 -0
  737. package/src/client.dev.js +21 -0
  738. package/src/db/DataBaseProvider.js +213 -0
  739. package/src/db/mariadb/MariaDB.js +72 -0
  740. package/src/db/mongo/MongoBootstrap.js +657 -0
  741. package/src/db/mongo/MongooseDB.js +199 -0
  742. package/src/grpc/cyberia/grpc-server.js +162 -0
  743. package/src/index.js +357 -0
  744. package/src/mailer/EmailRender.js +116 -0
  745. package/src/mailer/MailerProvider.js +213 -0
  746. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +413 -0
  747. package/src/projects/cyberia/besu-genesis-generator.js +1630 -0
  748. package/src/projects/cyberia/catalog-cyberia.js +90 -0
  749. package/src/projects/cyberia/gemini-client.js +175 -0
  750. package/src/projects/cyberia/generate-saga.js +2137 -0
  751. package/src/projects/cyberia/hot-reload-trigger.js +163 -0
  752. package/src/projects/cyberia/instance-data.js +719 -0
  753. package/src/projects/cyberia/ipfs-client.js +599 -0
  754. package/src/projects/cyberia/map-preview-generator.js +304 -0
  755. package/src/projects/cyberia/object-layer.js +978 -0
  756. package/src/projects/cyberia/semantic-layer-generator-floor.js +319 -0
  757. package/src/projects/cyberia/semantic-layer-generator-resource.js +259 -0
  758. package/src/projects/cyberia/semantic-layer-generator-skin.js +1164 -0
  759. package/src/projects/cyberia/semantic-layer-generator.js +753 -0
  760. package/src/projects/cyberia/shape-generator.js +1060 -0
  761. package/src/projects/underpost/catalog-underpost.js +60 -0
  762. package/src/proxy.js +19 -0
  763. package/src/runtime/cyberia-client/Dockerfile +49 -0
  764. package/src/runtime/cyberia-client/Dockerfile.dev +75 -0
  765. package/src/runtime/cyberia-server/Dockerfile +43 -0
  766. package/src/runtime/cyberia-server/Dockerfile.dev +56 -0
  767. package/src/runtime/engine-cyberia/Dockerfile +161 -0
  768. package/src/runtime/engine-cyberia/Dockerfile.dev +161 -0
  769. package/src/runtime/engine-cyberia/Dockerfile.test +165 -0
  770. package/src/runtime/engine-cyberia/compose.env +144 -0
  771. package/src/runtime/engine-cyberia/docker-compose.yml +434 -0
  772. package/src/runtime/engine-cyberia/ipfs/configure-ipfs.sh +13 -0
  773. package/src/runtime/engine-cyberia/mongodb/entrypoint.sh +76 -0
  774. package/src/runtime/engine-cyberia/nginx.conf +128 -0
  775. package/src/runtime/express/Dockerfile +45 -0
  776. package/src/runtime/express/Express.js +285 -0
  777. package/src/runtime/lampp/Dockerfile +62 -0
  778. package/src/runtime/lampp/Lampp.js +359 -0
  779. package/src/runtime/nginx/Nginx.js +250 -0
  780. package/src/runtime/wp/Dockerfile +62 -0
  781. package/src/runtime/wp/Wp.js +642 -0
  782. package/src/server/auth.js +713 -0
  783. package/src/server/backup.js +102 -0
  784. package/src/server/catalog.js +72 -0
  785. package/src/server/conf.js +2316 -0
  786. package/src/server/cron.js +476 -0
  787. package/src/server/crypto.js +210 -0
  788. package/src/server/data-query.js +461 -0
  789. package/src/server/dns.js +553 -0
  790. package/src/server/downloader.js +73 -0
  791. package/src/server/logger.js +229 -0
  792. package/src/server/middlewares.js +152 -0
  793. package/src/server/peer.js +75 -0
  794. package/src/server/process.js +299 -0
  795. package/src/server/proxy.js +139 -0
  796. package/src/server/runtime-status.js +252 -0
  797. package/src/server/runtime.js +183 -0
  798. package/src/server/start.js +272 -0
  799. package/src/server/tls.js +254 -0
  800. package/src/server/valkey.js +201 -0
  801. package/src/server.js +25 -0
  802. package/src/ws/IoInterface.js +129 -0
  803. package/src/ws/IoServer.js +68 -0
  804. package/src/ws/core/channels/core.ws.chat.js +68 -0
  805. package/src/ws/core/channels/core.ws.mailer.js +116 -0
  806. package/src/ws/core/channels/core.ws.stream.js +90 -0
  807. package/src/ws/core/core.ws.connection.js +41 -0
  808. package/src/ws/core/core.ws.emit.js +37 -0
  809. package/src/ws/core/core.ws.server.js +44 -0
  810. package/src/ws/default/channels/default.ws.main.js +57 -0
  811. package/src/ws/default/default.ws.connection.js +35 -0
  812. package/src/ws/default/default.ws.emit.js +14 -0
  813. package/src/ws/default/default.ws.server.js +39 -0
  814. package/test/api.test.js +53 -0
  815. package/test/crypto.test.js +117 -0
  816. package/test/cyberia-instance-conf-defaults.test.js +140 -0
  817. package/test/deploy-monitor.test.js +267 -0
  818. package/test/shape-generator.test.js +463 -0
  819. package/tsconfig.docs.json +15 -0
  820. package/typedoc.dd-cyberia.json +31 -0
  821. package/typedoc.json +31 -0
@@ -0,0 +1,1976 @@
1
+ import { BtnIcon } from '../core/BtnIcon.js';
2
+ import { Input, InputFile, getFileFromBlobEndpoint } from '../core/Input.js';
3
+ import { htmls, s } from '../core/VanillaJs.js';
4
+ import { commonModeratorGuard } from '../core/CommonJs.js';
5
+ import { NotificationManager } from '../core/NotificationManager.js';
6
+ import { Translate } from '../core/Translate.js';
7
+ import { darkTheme, dynamicCol, ThemeEvents } from '../core/Css.js';
8
+ import { DropDown } from '../core/DropDown.js';
9
+ import { ToggleSwitch } from '../core/ToggleSwitch.js';
10
+ import { CyberiaMapManagement } from '../../services/cyberia-map/cyberia-map.management.js';
11
+ import { CyberiaMapService } from '../../services/cyberia-map/cyberia-map.service.js';
12
+ import { FileService } from '../../services/file/file.service.js';
13
+ import { DefaultManagement } from '../../services/default/default.management.js';
14
+ import { getApiBaseUrl } from '../../services/core/core.service.js';
15
+ import { ObjectLayerService } from '../../services/object-layer/object-layer.service.js';
16
+ import { getProxyPath } from '../core/Router.js';
17
+ import { ENTITY_TYPES, getDefaultCyberiaItemById } from './SharedDefaultsCyberia.js';
18
+ import '../core/ColorPaletteElement.js';
19
+
20
+ const DEFAULT_ENTITY_TYPE = ENTITY_TYPES.floor;
21
+ const dropdownValueKey = (value = '') => String(value).trim().replaceAll(' ', '-');
22
+ const createDropdownOption = (value, onClick = () => {}, display = value, data = value) => ({
23
+ value,
24
+ display,
25
+ data,
26
+ onClick,
27
+ });
28
+
29
+ class MapEngineCyberia {
30
+ static entities = [];
31
+ static currentMapId = null;
32
+ static currentThumbnailId = null;
33
+ static thumbnailDirty = false;
34
+ static currentPreviewId = null;
35
+ static loadMap = null;
36
+ static showGridBorders = true;
37
+ static addOnClick = true;
38
+ static removeOnClick = false;
39
+ static showObjectLayers = false;
40
+ static enableRandomFactors = false;
41
+ static captureObjLayerThumbnail = true;
42
+ static imageCache = {};
43
+ static entityUndoStack = [];
44
+ static entityRedoStack = [];
45
+ static maxEntityHistory = 200;
46
+ static entityHistorySync = null;
47
+ static entityHistoryHotkeyHandler = null;
48
+ static entityTypeDropdownId = 'map-engine-entity-type';
49
+ static objectLayerDropdownId = 'map-engine-obj-layer-dropdown';
50
+ static objectLayerDropdownHostId = 'map-engine-obj-layer-dropdown-host';
51
+ static renameSourceObjectLayerInputId = 'map-engine-rename-source-object-layer-item-id';
52
+ static renameTargetObjectLayerInputId = 'map-engine-rename-target-object-layer-item-id';
53
+
54
+ static getSelectedDropdownValue(dropdownId, fallback = '') {
55
+ return DropDown.Tokens[dropdownId]?.value || s(`.${dropdownId}`)?.value || fallback;
56
+ }
57
+
58
+ static getSelectedEntityType() {
59
+ return MapEngineCyberia.getSelectedDropdownValue(MapEngineCyberia.entityTypeDropdownId, DEFAULT_ENTITY_TYPE);
60
+ }
61
+
62
+ static getSelectedObjectLayerItemIds() {
63
+ return DropDown.Tokens[MapEngineCyberia.objectLayerDropdownId]?.value
64
+ ? [...DropDown.Tokens[MapEngineCyberia.objectLayerDropdownId].value]
65
+ : [];
66
+ }
67
+
68
+ static getRenameObjectLayerItemIds() {
69
+ return {
70
+ source: s(`.${MapEngineCyberia.renameSourceObjectLayerInputId}`)?.value?.trim() || '',
71
+ target: s(`.${MapEngineCyberia.renameTargetObjectLayerInputId}`)?.value?.trim() || '',
72
+ };
73
+ }
74
+
75
+ static setDropdownValue(dropdownId, value) {
76
+ if (!value || !DropDown.Tokens[dropdownId]) return;
77
+ DropDown.Tokens[dropdownId].value = value;
78
+ if (s(`.${dropdownId}`)) s(`.${dropdownId}`).value = value;
79
+ htmls(`.dropdown-current-${dropdownId}`, value);
80
+ }
81
+
82
+ static getEntityTypeDropdownOptions() {
83
+ return Object.values(ENTITY_TYPES).map((entityType) => createDropdownOption(entityType));
84
+ }
85
+
86
+ static syncObjectLayerDropdownSelection(itemIds = []) {
87
+ const dropdownId = MapEngineCyberia.objectLayerDropdownId;
88
+ if (!DropDown.Tokens[dropdownId]) return;
89
+
90
+ DropDown.Tokens[dropdownId].oncheckvalues = {};
91
+ for (const itemId of itemIds) {
92
+ const key = dropdownValueKey(itemId);
93
+ DropDown.Tokens[dropdownId].oncheckvalues[key] = {
94
+ data: itemId,
95
+ display: itemId,
96
+ value: itemId,
97
+ };
98
+ }
99
+ DropDown.Tokens[dropdownId].value = [...itemIds];
100
+ if (s(`.${dropdownId}`)) s(`.${dropdownId}`).value = [...itemIds];
101
+ DropDown.Tokens[dropdownId]._renderSelectedBadges?.();
102
+ }
103
+
104
+ static async buildObjectLayerDropdown() {
105
+ return await DropDown.instance({
106
+ id: MapEngineCyberia.objectLayerDropdownId,
107
+ label: html`Object Layers`,
108
+ data: [],
109
+ type: 'checkbox',
110
+ containerClass: 'inl',
111
+ excludeSelected: true,
112
+ serviceProvider: async (q) => {
113
+ const result = await ObjectLayerService.searchItemIds({ q });
114
+ if (result.status === 'success' && result.data?.itemIds) {
115
+ return result.data.itemIds.map((itemId) => createDropdownOption(itemId));
116
+ }
117
+ return [];
118
+ },
119
+ });
120
+ }
121
+
122
+ static async renderObjectLayerDropdown({ selectedItemIds = [] } = {}) {
123
+ const hostId = MapEngineCyberia.objectLayerDropdownHostId;
124
+ if (!s(`.${hostId}`)) return;
125
+
126
+ htmls(`.${hostId}`, await MapEngineCyberia.buildObjectLayerDropdown());
127
+ MapEngineCyberia.syncObjectLayerDropdownSelection(selectedItemIds);
128
+ }
129
+
130
+ static renameFilteredObjectLayerItemId() {
131
+ const { source, target } = MapEngineCyberia.getRenameObjectLayerItemIds();
132
+ if (!source || !target) {
133
+ NotificationManager.Push({
134
+ html: 'Source and target ItemId are required.',
135
+ status: 'error',
136
+ });
137
+ return false;
138
+ }
139
+
140
+ if (source === target) {
141
+ NotificationManager.Push({
142
+ html: 'Source and target ItemId must be different.',
143
+ status: 'error',
144
+ });
145
+ return false;
146
+ }
147
+
148
+ const filtered = MapEngineCyberia.getFilteredEntities();
149
+ if (!filtered.length) {
150
+ NotificationManager.Push({
151
+ html: 'No filtered entities available for ItemId rename.',
152
+ status: 'error',
153
+ });
154
+ return false;
155
+ }
156
+
157
+ // Collect indices of filtered entities that have the source itemId
158
+ const eligible = [];
159
+ for (const { i } of filtered) {
160
+ const entity = MapEngineCyberia.entities[i];
161
+ if (Array.isArray(entity?.objectLayerItemIds) && entity.objectLayerItemIds.includes(source)) {
162
+ eligible.push(i);
163
+ }
164
+ }
165
+
166
+ if (!eligible.length) {
167
+ NotificationManager.Push({
168
+ html: `No exact ItemId matches for "${source}" were found in the current filtered entities.`,
169
+ status: 'error',
170
+ });
171
+ return false;
172
+ }
173
+
174
+ // When enableRandomFactors is active, each matching entity independently rolls
175
+ // a random probability check in [fMin, fMax]. If the roll passes, it gets renamed;
176
+ // otherwise it stays unchanged. This produces an intermediate intensity between
177
+ // "almost everyone" (factors near/above 1.0) and "almost no one" (factors near 0).
178
+ let matchedEntities = 0;
179
+ let renamedReferences = 0;
180
+ const changed = MapEngineCyberia.commitEntityMutation(() => {
181
+ for (const i of eligible) {
182
+ if (MapEngineCyberia.enableRandomFactors) {
183
+ const rawA = parseFloat(s('.map-engine-factor-a')?.value);
184
+ const rawB = parseFloat(s('.map-engine-factor-b')?.value);
185
+ const minF = Number.isFinite(rawA) ? rawA : 0.5;
186
+ const maxF = Number.isFinite(rawB) ? rawB : 1.5;
187
+ const fMin = Math.min(minF, maxF);
188
+ const fMax = Math.max(minF, maxF);
189
+ const roll = fMin + Math.random() * (fMax - fMin);
190
+ // If the roll is >= 1.0, always rename; otherwise compare against Math.random()
191
+ if (roll < 1.0 && Math.random() > roll) continue;
192
+ }
193
+ const entity = MapEngineCyberia.entities[i];
194
+ let entityChanged = false;
195
+ entity.objectLayerItemIds = entity.objectLayerItemIds.map((itemId) => {
196
+ if (itemId !== source) return itemId;
197
+ entityChanged = true;
198
+ renamedReferences += 1;
199
+ return target;
200
+ });
201
+ if (entityChanged) matchedEntities += 1;
202
+ }
203
+ });
204
+
205
+ if (!changed) {
206
+ NotificationManager.Push({
207
+ html: `No exact ItemId matches for "${source}" were found in the current filtered entities.`,
208
+ status: 'error',
209
+ });
210
+ return false;
211
+ }
212
+
213
+ NotificationManager.Push({
214
+ html: `Renamed ${renamedReferences} object layer reference${renamedReferences === 1 ? '' : 's'} across ${matchedEntities} filtered entit${matchedEntities === 1 ? 'y' : 'ies'}.`,
215
+ status: 'success',
216
+ });
217
+ return true;
218
+ }
219
+
220
+ static cloneEntity(entity) {
221
+ return {
222
+ ...entity,
223
+ objectLayerItemIds: Array.isArray(entity?.objectLayerItemIds) ? [...entity.objectLayerItemIds] : [],
224
+ };
225
+ }
226
+
227
+ static cloneEntities(entities = MapEngineCyberia.entities) {
228
+ return (entities || []).map((entity) => MapEngineCyberia.cloneEntity(entity));
229
+ }
230
+
231
+ static entitySnapshotsEqual(left, right) {
232
+ if (left === right) return true;
233
+ if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) return false;
234
+
235
+ for (let i = 0; i < left.length; i++) {
236
+ const a = left[i] || {};
237
+ const b = right[i] || {};
238
+ const aKeys = Object.keys(a);
239
+ const bKeys = Object.keys(b);
240
+ if (aKeys.length !== bKeys.length) return false;
241
+
242
+ for (const key of aKeys) {
243
+ const aValue = a[key];
244
+ const bValue = b[key];
245
+
246
+ if (Array.isArray(aValue) || Array.isArray(bValue)) {
247
+ if (!Array.isArray(aValue) || !Array.isArray(bValue) || aValue.length !== bValue.length) return false;
248
+ for (let j = 0; j < aValue.length; j++) {
249
+ if (aValue[j] !== bValue[j]) return false;
250
+ }
251
+ continue;
252
+ }
253
+
254
+ if (aValue !== bValue) return false;
255
+ }
256
+ }
257
+
258
+ return true;
259
+ }
260
+
261
+ static pushEntityHistory(stack, snapshot) {
262
+ stack.push(snapshot);
263
+ if (stack.length > MapEngineCyberia.maxEntityHistory) stack.shift();
264
+ }
265
+
266
+ static setEntityHistorySync(callback) {
267
+ MapEngineCyberia.entityHistorySync = callback;
268
+ }
269
+
270
+ static preloadEntityObjectLayers(onLoad = null) {
271
+ for (const entity of MapEngineCyberia.entities) {
272
+ for (const itemId of entity.objectLayerItemIds || []) {
273
+ MapEngineCyberia.loadObjectLayerImage(itemId, onLoad);
274
+ }
275
+ }
276
+ }
277
+
278
+ static refreshEntityEditor() {
279
+ const callback = MapEngineCyberia.entityHistorySync;
280
+ if (typeof callback !== 'function') return;
281
+ MapEngineCyberia.preloadEntityObjectLayers(callback);
282
+ callback();
283
+ }
284
+
285
+ static clearEntityHistory() {
286
+ MapEngineCyberia.entityUndoStack.length = 0;
287
+ MapEngineCyberia.entityRedoStack.length = 0;
288
+ }
289
+
290
+ static setEntities(entities, { clearHistory = false } = {}) {
291
+ MapEngineCyberia.entities = MapEngineCyberia.cloneEntities(entities);
292
+ if (clearHistory) MapEngineCyberia.clearEntityHistory();
293
+ MapEngineCyberia.refreshEntityEditor();
294
+ }
295
+
296
+ static commitEntityMutation(mutate) {
297
+ if (typeof mutate !== 'function') return false;
298
+
299
+ const before = MapEngineCyberia.cloneEntities();
300
+ mutate();
301
+ const after = MapEngineCyberia.cloneEntities();
302
+
303
+ if (MapEngineCyberia.entitySnapshotsEqual(before, after)) return false;
304
+
305
+ MapEngineCyberia.pushEntityHistory(MapEngineCyberia.entityUndoStack, before);
306
+ MapEngineCyberia.entityRedoStack.length = 0;
307
+ MapEngineCyberia.refreshEntityEditor();
308
+ return true;
309
+ }
310
+
311
+ static undoEntityMutation() {
312
+ if (!MapEngineCyberia.entityUndoStack.length) return false;
313
+
314
+ const previous = MapEngineCyberia.entityUndoStack.pop();
315
+ MapEngineCyberia.pushEntityHistory(MapEngineCyberia.entityRedoStack, MapEngineCyberia.cloneEntities());
316
+ MapEngineCyberia.setEntities(previous);
317
+ return true;
318
+ }
319
+
320
+ static redoEntityMutation() {
321
+ if (!MapEngineCyberia.entityRedoStack.length) return false;
322
+
323
+ const next = MapEngineCyberia.entityRedoStack.pop();
324
+ MapEngineCyberia.pushEntityHistory(MapEngineCyberia.entityUndoStack, MapEngineCyberia.cloneEntities());
325
+ MapEngineCyberia.setEntities(next);
326
+ return true;
327
+ }
328
+
329
+ static isEditableTarget(target) {
330
+ if (!target) return false;
331
+ const tagName = target.tagName?.toUpperCase();
332
+ return target.isContentEditable || tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT';
333
+ }
334
+
335
+ static isEntityHistoryActive() {
336
+ const container = s('.map-engine-container');
337
+ return !!container && container.isConnected && container.getClientRects().length > 0;
338
+ }
339
+
340
+ static bindEntityHistoryHotkeys() {
341
+ if (MapEngineCyberia.entityHistoryHotkeyHandler) {
342
+ window.removeEventListener('keydown', MapEngineCyberia.entityHistoryHotkeyHandler);
343
+ }
344
+
345
+ MapEngineCyberia.entityHistoryHotkeyHandler = (event) => {
346
+ if (
347
+ event.defaultPrevented ||
348
+ event.altKey ||
349
+ !MapEngineCyberia.isEntityHistoryActive() ||
350
+ MapEngineCyberia.isEditableTarget(event.target)
351
+ ) {
352
+ return;
353
+ }
354
+
355
+ const isModifierPressed = event.ctrlKey || event.metaKey;
356
+ if (!isModifierPressed) return;
357
+
358
+ if (event.key === 'z' || event.key === 'Z') {
359
+ const handled = event.shiftKey ? MapEngineCyberia.redoEntityMutation() : MapEngineCyberia.undoEntityMutation();
360
+ if (handled) event.preventDefault();
361
+ return;
362
+ }
363
+
364
+ if (event.key === 'y' || event.key === 'Y') {
365
+ if (MapEngineCyberia.redoEntityMutation()) event.preventDefault();
366
+ }
367
+ };
368
+
369
+ window.addEventListener('keydown', MapEngineCyberia.entityHistoryHotkeyHandler);
370
+ }
371
+
372
+ static getEntityFilters() {
373
+ return {
374
+ filterType: s('.map-engine-filter-entity-type')?.value?.trim().toLowerCase() || '',
375
+ filterX: s('.map-engine-filter-init-x')?.value?.trim() || '',
376
+ filterY: s('.map-engine-filter-init-y')?.value?.trim() || '',
377
+ };
378
+ }
379
+
380
+ static getFilteredEntities() {
381
+ const { filterType, filterX, filterY } = MapEngineCyberia.getEntityFilters();
382
+
383
+ return MapEngineCyberia.entities.reduce((acc, entity, i) => {
384
+ if (filterType && !(entity.entityType || '').toLowerCase().includes(filterType)) return acc;
385
+ if (filterX !== '' && String(entity.initCellX) !== filterX) return acc;
386
+ if (filterY !== '' && String(entity.initCellY) !== filterY) return acc;
387
+ acc.push({ entity, i });
388
+ return acc;
389
+ }, []);
390
+ }
391
+
392
+ static loadObjectLayerImage(itemId, onLoad) {
393
+ if (MapEngineCyberia.imageCache[itemId]) return;
394
+ MapEngineCyberia.imageCache[itemId] = { img: null, loaded: false, error: false };
395
+
396
+ const loadImage = (type, id) => {
397
+ const img = new Image();
398
+ img.onload = () => {
399
+ MapEngineCyberia.imageCache[itemId].img = img;
400
+ MapEngineCyberia.imageCache[itemId].loaded = true;
401
+ if (onLoad) onLoad();
402
+ };
403
+ img.onerror = () => {
404
+ MapEngineCyberia.imageCache[itemId].error = true;
405
+ };
406
+ img.src = `${getProxyPath()}assets/${type}/${id}/08/0.png`;
407
+ };
408
+
409
+ const sharedItem = getDefaultCyberiaItemById(itemId)?.item;
410
+ if (sharedItem?.type && sharedItem?.id) {
411
+ loadImage(sharedItem.type, sharedItem.id);
412
+ return;
413
+ }
414
+
415
+ ObjectLayerService.get({
416
+ limit: 1,
417
+ filterModel: { 'data.item.id': { filterType: 'text', type: 'equals', filter: itemId } },
418
+ })
419
+ .then((res) => {
420
+ const doc = res?.data?.data?.[0];
421
+ if (!doc || !doc.data?.item?.type || !doc.data?.item?.id) {
422
+ MapEngineCyberia.imageCache[itemId].error = true;
423
+ return;
424
+ }
425
+ const { type, id } = doc.data.item;
426
+ loadImage(type, id);
427
+ })
428
+ .catch(() => {
429
+ MapEngineCyberia.imageCache[itemId].error = true;
430
+ });
431
+ }
432
+
433
+ static renderGrid(canvas, cols, rows, cellW, cellH, showGrid = true) {
434
+ canvas.width = cols * cellW;
435
+ canvas.height = rows * cellH;
436
+ const ctx = canvas.getContext('2d');
437
+
438
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
439
+
440
+ // Draw entities
441
+ for (const entity of MapEngineCyberia.entities) {
442
+ const x = entity.initCellX * cellW;
443
+ const y = entity.initCellY * cellH;
444
+ const w = entity.dimX * cellW;
445
+ const h = entity.dimY * cellH;
446
+
447
+ if (MapEngineCyberia.showObjectLayers && entity.objectLayerItemIds?.length) {
448
+ for (const itemId of entity.objectLayerItemIds) {
449
+ const cached = MapEngineCyberia.imageCache[itemId];
450
+ if (cached?.loaded && cached.img) {
451
+ ctx.drawImage(cached.img, x, y, w, h);
452
+ }
453
+ }
454
+ } else {
455
+ ctx.fillStyle = entity.color;
456
+ ctx.fillRect(x, y, w, h);
457
+ }
458
+ }
459
+
460
+ // Draw grid lines on top
461
+ if (showGrid) {
462
+ ctx.strokeStyle = '#aaa';
463
+ ctx.lineWidth = 1;
464
+
465
+ for (let r = 0; r < rows; r++) {
466
+ for (let c = 0; c < cols; c++) {
467
+ ctx.strokeRect(c * cellW, r * cellH, cellW, cellH);
468
+ }
469
+ }
470
+ }
471
+ }
472
+
473
+ static renderToOffscreenCanvas(cols, rows, cellW, cellH, { forceObjectLayers = false } = {}) {
474
+ const offscreen = document.createElement('canvas');
475
+ offscreen.width = cols * cellW;
476
+ offscreen.height = rows * cellH;
477
+ const ctx = offscreen.getContext('2d');
478
+ ctx.clearRect(0, 0, offscreen.width, offscreen.height);
479
+ const useObjectLayers = forceObjectLayers || MapEngineCyberia.showObjectLayers;
480
+ for (const entity of MapEngineCyberia.entities) {
481
+ const x = entity.initCellX * cellW;
482
+ const y = entity.initCellY * cellH;
483
+ const w = entity.dimX * cellW;
484
+ const h = entity.dimY * cellH;
485
+
486
+ if (useObjectLayers && entity.objectLayerItemIds?.length) {
487
+ for (const itemId of entity.objectLayerItemIds) {
488
+ const cached = MapEngineCyberia.imageCache[itemId];
489
+ if (cached?.loaded && cached.img) {
490
+ ctx.drawImage(cached.img, x, y, w, h);
491
+ }
492
+ }
493
+ } else {
494
+ ctx.fillStyle = entity.color;
495
+ ctx.fillRect(x, y, w, h);
496
+ }
497
+ }
498
+ return offscreen;
499
+ }
500
+
501
+ static renderEntityList(containerId) {
502
+ const container = s(`.${containerId}`);
503
+ if (!container) return;
504
+
505
+ const filtered = MapEngineCyberia.getFilteredEntities();
506
+ const counter = s('.map-engine-entity-filter-count');
507
+ if (counter) {
508
+ const total = MapEngineCyberia.entities.length;
509
+ const visible = filtered.length;
510
+ counter.innerHTML = `Showing ${visible} of ${total} entities`;
511
+ }
512
+
513
+ let html = '';
514
+ filtered.forEach(({ entity, i }) => {
515
+ const layerTags = (entity.objectLayerItemIds || [])
516
+ .map(
517
+ (id) =>
518
+ html`<div
519
+ class="badge inl"
520
+ style="background:${darkTheme ? '#335' : '#cde'};color:${darkTheme
521
+ ? '#adf'
522
+ : '#246'};border-radius:4px;font-size:11px;height:auto;min-width:auto;margin:1px 2px;"
523
+ >
524
+ <div class="badge-text"><i class="fa-solid fa-tag" style="margin-right:3px;font-size:9px;"></i>${id}</div>
525
+ </div>`,
526
+ )
527
+ .join('');
528
+ html += html`<div class="fl" style="border-bottom:1px solid #444; padding:4px 0; align-items:center;">
529
+ <div
530
+ class="in fll"
531
+ style="width:20px;height:20px;background:${entity.color};border:1px solid #888;margin-right:6px;"
532
+ ></div>
533
+ <div class="in fll" style="flex:1;font-size:12px;font-family:monospace;">
534
+ ${entity.entityType} (${entity.initCellX},${entity.initCellY}) ${entity.dimX}x${entity.dimY}
535
+ ${layerTags ? html`<div style="margin-top:2px;">${layerTags}</div>` : ''}
536
+ </div>
537
+ <div class="in fll" style="display:flex;gap:3px;">
538
+ <button
539
+ class="btn-map-engine-load-entity-values"
540
+ data-index="${i}"
541
+ style="cursor:pointer;background:#36a;color:#fff;border:none;padding:2px 8px;font-size:12px;"
542
+ >
543
+ <i class="fa-solid fa-clone"></i>
544
+ </button>
545
+ <button
546
+ class="btn-map-engine-remove-entity"
547
+ data-index="${i}"
548
+ style="cursor:pointer;background:#a00;color:#fff;border:none;padding:2px 8px;font-size:12px;"
549
+ >
550
+ <i class="fa-solid fa-trash"></i>
551
+ </button>
552
+ </div>
553
+ </div>`;
554
+ });
555
+ if (!html)
556
+ html = `<div style="color:#888;font-size:13px;">${MapEngineCyberia.entities.length > 0 ? 'No matching entities.' : 'No entities added yet.'}</div>`;
557
+ htmls(`.${containerId}`, html);
558
+
559
+ container.querySelectorAll('.btn-map-engine-remove-entity').forEach((btn) => {
560
+ btn.onclick = () => {
561
+ const idx = parseInt(btn.dataset.index, 10);
562
+ MapEngineCyberia.commitEntityMutation(() => {
563
+ MapEngineCyberia.entities.splice(idx, 1);
564
+ });
565
+ };
566
+ });
567
+
568
+ container.querySelectorAll('.btn-map-engine-load-entity-values').forEach((btn) => {
569
+ btn.onclick = () => {
570
+ const idx = parseInt(btn.dataset.index);
571
+ const entity = MapEngineCyberia.entities[idx];
572
+ if (!entity) return;
573
+
574
+ const entityType = entity.entityType || DEFAULT_ENTITY_TYPE;
575
+ const itemIds = entity.objectLayerItemIds || [];
576
+
577
+ MapEngineCyberia.setDropdownValue(MapEngineCyberia.entityTypeDropdownId, entityType);
578
+ if (s('.map-engine-init-cell-x')) s('.map-engine-init-cell-x').value = entity.initCellX || 0;
579
+ if (s('.map-engine-init-cell-y')) s('.map-engine-init-cell-y').value = entity.initCellY || 0;
580
+ if (s('.map-engine-dim-x')) s('.map-engine-dim-x').value = entity.dimX || 1;
581
+ if (s('.map-engine-dim-y')) s('.map-engine-dim-y').value = entity.dimY || 1;
582
+
583
+ // Parse rgba color back to hex + alpha
584
+ const rgbaMatch = (entity.color || '').match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\)/);
585
+ if (rgbaMatch) {
586
+ const r = parseInt(rgbaMatch[1]).toString(16).padStart(2, '0');
587
+ const g = parseInt(rgbaMatch[2]).toString(16).padStart(2, '0');
588
+ const b = parseInt(rgbaMatch[3]).toString(16).padStart(2, '0');
589
+ const alpha = rgbaMatch[4] !== undefined ? parseFloat(rgbaMatch[4]) : 1;
590
+ if (s('.map-engine-color')) s('.map-engine-color').value = `#${r}${g}${b}`;
591
+ if (s('.map-engine-alpha')) {
592
+ s('.map-engine-alpha').value = alpha;
593
+ s('.map-engine-alpha').dispatchEvent(new Event('input'));
594
+ }
595
+ if (s('.map-engine-color')) s('.map-engine-color').dispatchEvent(new Event('input'));
596
+ }
597
+
598
+ MapEngineCyberia.syncObjectLayerDropdownSelection(itemIds);
599
+ };
600
+ });
601
+ }
602
+
603
+ static async render(options = {}) {
604
+ const { appStore } = options;
605
+ const role = appStore?.Data?.user?.main?.model?.user?.role || 'guest';
606
+ const canMutate = commonModeratorGuard(role);
607
+ const idCode = 'map-engine-input-code';
608
+ const idName = 'map-engine-input-name';
609
+ const idDescription = 'map-engine-input-description';
610
+ const idTags = 'map-engine-input-tags';
611
+ const idStatus = 'map-engine-input-status';
612
+ const idThumbnail = 'map-engine-input-thumbnail';
613
+ const idCreator = 'map-engine-input-creator';
614
+
615
+ const idX = 'map-engine-input-x';
616
+ const idY = 'map-engine-input-y';
617
+ const idCellW = 'map-engine-input-cell-w';
618
+ const idCellH = 'map-engine-input-cell-h';
619
+ const canvasId = 'map-engine-canvas';
620
+
621
+ const idEntityType = MapEngineCyberia.entityTypeDropdownId;
622
+ const idInitCellX = 'map-engine-init-cell-x';
623
+ const idInitCellY = 'map-engine-init-cell-y';
624
+ const idDimX = 'map-engine-dim-x';
625
+ const idDimY = 'map-engine-dim-y';
626
+ const idColor = 'map-engine-color';
627
+ const idColorPalette = 'map-engine-color-palette';
628
+ const idAlpha = 'map-engine-alpha';
629
+ const idFactorA = 'map-engine-factor-a';
630
+ const idFactorB = 'map-engine-factor-b';
631
+ const idVariationPreserve = 'map-engine-variation-preserve';
632
+ const rgbaDisplayId = 'map-engine-rgba-display';
633
+ const entityListId = 'map-engine-entity-list';
634
+ const idObjLayerDropdown = MapEngineCyberia.objectLayerDropdownId;
635
+ const idObjLayerDropdownHost = MapEngineCyberia.objectLayerDropdownHostId;
636
+ const idRenameSourceObjectLayer = MapEngineCyberia.renameSourceObjectLayerInputId;
637
+ const idRenameTargetObjectLayer = MapEngineCyberia.renameTargetObjectLayerInputId;
638
+ const managementId = 'modal-cyberia-map-engine';
639
+
640
+ MapEngineCyberia.setEntities([], { clearHistory: true });
641
+ MapEngineCyberia.currentMapId = null;
642
+ MapEngineCyberia.currentThumbnailId = null;
643
+ MapEngineCyberia.currentPreviewId = null;
644
+
645
+ const hexToRgba = (hex, alpha) => {
646
+ const r = parseInt(hex.slice(1, 3), 16);
647
+ const g = parseInt(hex.slice(3, 5), 16);
648
+ const b = parseInt(hex.slice(5, 7), 16);
649
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
650
+ };
651
+
652
+ const getCanvasParams = () => ({
653
+ cols: parseInt(s(`.${idX}`)?.value) || 16,
654
+ rows: parseInt(s(`.${idY}`)?.value) || 16,
655
+ cellW: parseInt(s(`.${idCellW}`)?.value) || 32,
656
+ cellH: parseInt(s(`.${idCellH}`)?.value) || 32,
657
+ });
658
+
659
+ const getFactorRange = () => {
660
+ const rawA = parseFloat(s(`.${idFactorA}`)?.value);
661
+ const rawB = parseFloat(s(`.${idFactorB}`)?.value);
662
+ const safeA = Number.isFinite(rawA) ? rawA : 0.5;
663
+ const safeB = Number.isFinite(rawB) ? rawB : 1.5;
664
+ return {
665
+ min: Math.min(safeA, safeB),
666
+ max: Math.max(safeA, safeB),
667
+ };
668
+ };
669
+
670
+ const getPreserveSet = () => {
671
+ const preserveRaw = s(`.${idVariationPreserve}`)?.value || '';
672
+ return new Set(
673
+ preserveRaw
674
+ .split(',')
675
+ .map((t) => t.trim().toLowerCase())
676
+ .filter((t) => t),
677
+ );
678
+ };
679
+
680
+ const getPreserveIndices = () => {
681
+ const preserveSet = getPreserveSet();
682
+ return MapEngineCyberia.entities.reduce((acc, entity, index) => {
683
+ if (preserveSet.has((entity.entityType || '').toLowerCase())) acc.push(index);
684
+ return acc;
685
+ }, []);
686
+ };
687
+
688
+ const getAffectedEntityCount = (total) => {
689
+ if (total <= 0) return 0;
690
+ if (!MapEngineCyberia.enableRandomFactors) return Math.max(1, Math.round(total / 2));
691
+
692
+ const { min, max } = getFactorRange();
693
+ const factor = min + Math.random() * (max - min);
694
+ return Math.max(1, Math.min(total, Math.round(total * factor)));
695
+ };
696
+
697
+ const rerenderCanvas = () => {
698
+ const canvas = s(`.${canvasId}`);
699
+ if (!canvas) return;
700
+ const { cols, rows, cellW, cellH } = getCanvasParams();
701
+ MapEngineCyberia.renderGrid(canvas, cols, rows, cellW, cellH, MapEngineCyberia.showGridBorders);
702
+ };
703
+
704
+ const getEntityParams = () => {
705
+ const hex = s(`.${idColor}`)?.value || '#ff0000';
706
+ const alpha = parseFloat(s(`.${idAlpha}`)?.value);
707
+ return {
708
+ entityType: MapEngineCyberia.getSelectedEntityType(),
709
+ initCellX: parseInt(s(`.${idInitCellX}`)?.value) || 0,
710
+ initCellY: parseInt(s(`.${idInitCellY}`)?.value) || 0,
711
+ dimX: parseInt(s(`.${idDimX}`)?.value) || 1,
712
+ dimY: parseInt(s(`.${idDimY}`)?.value) || 1,
713
+ color: hexToRgba(hex, alpha),
714
+ };
715
+ };
716
+
717
+ const applyRandomFactorsToDimensions = (ep) => {
718
+ if (!MapEngineCyberia.enableRandomFactors) return;
719
+ const { min, max } = getFactorRange();
720
+ const factor = min + Math.random() * (max - min);
721
+ ep.dimX = Math.max(1, Math.round(ep.dimX * factor));
722
+ ep.dimY = Math.max(1, Math.round(ep.dimY * factor));
723
+ };
724
+
725
+ const addEntityLocally = () => {
726
+ const ep = getEntityParams();
727
+ ep.objectLayerItemIds = DropDown.Tokens[idObjLayerDropdown]?.value
728
+ ? [...DropDown.Tokens[idObjLayerDropdown].value]
729
+ : [];
730
+ applyRandomFactorsToDimensions(ep);
731
+ MapEngineCyberia.commitEntityMutation(() => {
732
+ MapEngineCyberia.entities.push(ep);
733
+ });
734
+ };
735
+
736
+ const fillMapWithEntity = () => {
737
+ const ep = getEntityParams();
738
+ ep.objectLayerItemIds = DropDown.Tokens[idObjLayerDropdown]?.value
739
+ ? [...DropDown.Tokens[idObjLayerDropdown].value]
740
+ : [];
741
+ const { cols, rows } = getCanvasParams();
742
+ const dimX = ep.dimX || 1;
743
+ const dimY = ep.dimY || 1;
744
+ MapEngineCyberia.commitEntityMutation(() => {
745
+ for (let r = 0; r < rows; r += dimY) {
746
+ for (let c = 0; c < cols; c += dimX) {
747
+ const tile = {
748
+ ...ep,
749
+ initCellX: c,
750
+ initCellY: r,
751
+ objectLayerItemIds: [...ep.objectLayerItemIds],
752
+ };
753
+ applyRandomFactorsToDimensions(tile);
754
+ MapEngineCyberia.entities.push(tile);
755
+ }
756
+ }
757
+ });
758
+ };
759
+
760
+ const generateVariation = () => {
761
+ const { min, max } = getFactorRange();
762
+ const preserveSet = getPreserveSet();
763
+ const { cols, rows } = getCanvasParams();
764
+ MapEngineCyberia.commitEntityMutation(() => {
765
+ for (const entity of MapEngineCyberia.entities) {
766
+ if (preserveSet.has((entity.entityType || '').toLowerCase())) continue;
767
+ const dimFactor = min + Math.random() * (max - min);
768
+ entity.dimX = Math.max(1, Math.round(entity.dimX * dimFactor));
769
+ entity.dimY = Math.max(1, Math.round(entity.dimY * dimFactor));
770
+ const posFactor = min + Math.random() * (max - min);
771
+ entity.initCellX = Math.max(0, Math.min(cols - 1, Math.round(entity.initCellX * posFactor)));
772
+ entity.initCellY = Math.max(0, Math.min(rows - 1, Math.round(entity.initCellY * posFactor)));
773
+ }
774
+ });
775
+ };
776
+
777
+ const clearAllEntities = () => {
778
+ MapEngineCyberia.commitEntityMutation(() => {
779
+ MapEngineCyberia.entities = [];
780
+ });
781
+ };
782
+
783
+ const randomSwapPreserveEntities = () => {
784
+ const preserveIndices = getPreserveIndices();
785
+ if (preserveIndices.length < 2) return;
786
+
787
+ const selectedCount = getAffectedEntityCount(preserveIndices.length);
788
+ const shuffled = [...preserveIndices].sort(() => Math.random() - 0.5).slice(0, selectedCount);
789
+ const swapCount = Math.max(1, Math.floor(shuffled.length / 2));
790
+
791
+ MapEngineCyberia.commitEntityMutation(() => {
792
+ for (let i = 0; i < swapCount * 2; i += 2) {
793
+ const firstIndex = shuffled[i];
794
+ const secondIndex = shuffled[i + 1];
795
+ if (firstIndex === undefined || secondIndex === undefined) continue;
796
+
797
+ const first = MapEngineCyberia.entities[firstIndex];
798
+ const second = MapEngineCyberia.entities[secondIndex];
799
+ const firstPos = { initCellX: first.initCellX, initCellY: first.initCellY };
800
+
801
+ first.initCellX = second.initCellX;
802
+ first.initCellY = second.initCellY;
803
+ second.initCellX = firstPos.initCellX;
804
+ second.initCellY = firstPos.initCellY;
805
+ }
806
+ });
807
+ };
808
+
809
+ const replacePreserveEntitiesWithCurrentConfig = () => {
810
+ const preserveIndices = getPreserveIndices();
811
+ if (preserveIndices.length === 0) return;
812
+
813
+ const selectedCount = getAffectedEntityCount(preserveIndices.length);
814
+ const selected = [...preserveIndices].sort(() => Math.random() - 0.5).slice(0, selectedCount);
815
+ const template = getEntityParams();
816
+ template.objectLayerItemIds = DropDown.Tokens[idObjLayerDropdown]?.value
817
+ ? [...DropDown.Tokens[idObjLayerDropdown].value]
818
+ : [];
819
+
820
+ MapEngineCyberia.commitEntityMutation(() => {
821
+ for (const index of selected) {
822
+ const target = MapEngineCyberia.entities[index];
823
+ const replacement = {
824
+ ...target,
825
+ entityType: template.entityType,
826
+ dimX: template.dimX,
827
+ dimY: template.dimY,
828
+ color: template.color,
829
+ objectLayerItemIds: [...template.objectLayerItemIds],
830
+ };
831
+ applyRandomFactorsToDimensions(replacement);
832
+ MapEngineCyberia.entities[index] = replacement;
833
+ }
834
+ });
835
+ };
836
+
837
+ const flipHorizontal = () => {
838
+ const { cols } = getCanvasParams();
839
+ MapEngineCyberia.commitEntityMutation(() => {
840
+ for (const entity of MapEngineCyberia.entities) {
841
+ entity.initCellX = cols - entity.initCellX - entity.dimX;
842
+ }
843
+ });
844
+ };
845
+
846
+ const flipVertical = () => {
847
+ const { rows } = getCanvasParams();
848
+ MapEngineCyberia.commitEntityMutation(() => {
849
+ for (const entity of MapEngineCyberia.entities) {
850
+ entity.initCellY = rows - entity.initCellY - entity.dimY;
851
+ }
852
+ });
853
+ };
854
+
855
+ const getMapPayload = () => {
856
+ const tagsRaw = s(`.${idTags}`)?.value || '';
857
+ const tags = tagsRaw
858
+ .split(',')
859
+ .map((t) => t.trim())
860
+ .filter((t) => t);
861
+ const { cols, rows, cellW, cellH } = getCanvasParams();
862
+ const payload = {
863
+ code: s(`.${idCode}`)?.value || '',
864
+ name: s(`.${idName}`)?.value || '',
865
+ description: s(`.${idDescription}`)?.value || '',
866
+ tags,
867
+ status: DropDown.Tokens[idStatus]?.value || 'unlisted',
868
+ entities: MapEngineCyberia.entities,
869
+ gridX: cols,
870
+ gridY: rows,
871
+ cellWidth: cellW,
872
+ cellHeight: cellH,
873
+ };
874
+ if (MapEngineCyberia.currentThumbnailId) payload.thumbnail = MapEngineCyberia.currentThumbnailId;
875
+ return payload;
876
+ };
877
+
878
+ // Render the current auto-captured Instance Map preview image (or an
879
+ // empty-state hint) into the Instance Map Preview section.
880
+ const renderPreviewImage = () => {
881
+ const el = s('.map-engine-preview-image');
882
+ if (!el) return;
883
+ const rawId = MapEngineCyberia.currentPreviewId;
884
+ const previewId = rawId && typeof rawId === 'object' ? rawId._id : rawId;
885
+ el.innerHTML = previewId
886
+ ? html`<img
887
+ src="${getApiBaseUrl({ id: previewId, endpoint: 'file/blob' })}"
888
+ class="in"
889
+ style="max-width:300px;height:auto;border:1px solid #555;margin:auto"
890
+ onerror="this.style.display='none';"
891
+ />`
892
+ : html`<span style="color:#888;font-size:12px;">No preview captured yet — save the map to generate it.</span>`;
893
+ };
894
+
895
+ // Capture the Object Layer canvas render and upload it as a File.
896
+ // Returns the uploaded file id, or null when capture/upload failed.
897
+ const captureObjectLayerUpload = async (filename) => {
898
+ const { cols, rows, cellW, cellH } = getCanvasParams();
899
+ const offscreen = MapEngineCyberia.renderToOffscreenCanvas(cols, rows, cellW, cellH, {
900
+ forceObjectLayers: true,
901
+ });
902
+ const blob = await new Promise((resolve) => offscreen.toBlob(resolve, 'image/png'));
903
+ if (!blob) return null;
904
+ const file = new File([blob], filename, { type: 'image/png' });
905
+ const formData = new FormData();
906
+ formData.append('file', file);
907
+ const uploadResult = await FileService.post({ body: formData });
908
+ if (uploadResult.status === 'success' && uploadResult.data?.length > 0) {
909
+ return uploadResult.data[0]._id;
910
+ }
911
+ return null;
912
+ };
913
+
914
+ const saveMap = async () => {
915
+ // Thumbnail: a user-selected custom image always wins; the Object
916
+ // Layer canvas capture is the checkbox-gated fallback when no custom
917
+ // image was set.
918
+ const thumbnailInput = s(`.${idThumbnail}`);
919
+ const hasCustomThumbnail =
920
+ MapEngineCyberia.thumbnailDirty &&
921
+ thumbnailInput &&
922
+ thumbnailInput.files &&
923
+ thumbnailInput.files.length > 0;
924
+ if (hasCustomThumbnail) {
925
+ const formData = new FormData();
926
+ formData.append('file', thumbnailInput.files[0]);
927
+ const uploadResult = await FileService.post({ body: formData });
928
+ if (uploadResult.status === 'success' && uploadResult.data && uploadResult.data.length > 0) {
929
+ MapEngineCyberia.currentThumbnailId = uploadResult.data[0]._id;
930
+ } else {
931
+ NotificationManager.Push({
932
+ html: uploadResult.message || 'Failed to upload thumbnail',
933
+ status: 'error',
934
+ });
935
+ return;
936
+ }
937
+ } else if (MapEngineCyberia.captureObjLayerThumbnail) {
938
+ const thumbId = await captureObjectLayerUpload('map-thumbnail.png');
939
+ if (thumbId) MapEngineCyberia.currentThumbnailId = thumbId;
940
+ }
941
+
942
+ // Preview is always a fresh automatic Object Layer capture — the node
943
+ // background for the client's Instance Map. Independent of the
944
+ // thumbnail checkbox and never user-managed.
945
+ const previewId = await captureObjectLayerUpload('map-preview.png');
946
+ if (previewId) MapEngineCyberia.currentPreviewId = previewId;
947
+
948
+ const body = getMapPayload();
949
+ if (previewId) body.preview = previewId;
950
+ let result;
951
+ if (MapEngineCyberia.currentMapId) {
952
+ result = await CyberiaMapService.put({ id: MapEngineCyberia.currentMapId, body });
953
+ } else {
954
+ result = await CyberiaMapService.post({ body });
955
+ }
956
+ NotificationManager.Push({
957
+ html:
958
+ result.status === 'error'
959
+ ? result.message
960
+ : MapEngineCyberia.currentMapId
961
+ ? Translate.instance('success-update-item')
962
+ : Translate.instance('success-create-item'),
963
+ status: result.status,
964
+ });
965
+ if (result.status === 'success') {
966
+ if (result.data?._id) MapEngineCyberia.currentMapId = result.data._id;
967
+ renderPreviewImage();
968
+ await DefaultManagement.loadTable(managementId, { force: true, reload: true });
969
+ }
970
+ };
971
+
972
+ const cloneMap = async () => {
973
+ if (!MapEngineCyberia.currentMapId) return;
974
+
975
+ let cloneThumbnailId = null;
976
+
977
+ // Same precedence as saveMap: a user-selected custom image wins; the
978
+ // Object Layer capture is the checkbox-gated fallback. The clone never
979
+ // reuses the source map's thumbnail file (it would be double-owned).
980
+ const thumbnailInput = s(`.${idThumbnail}`);
981
+ if (thumbnailInput && thumbnailInput.files && thumbnailInput.files.length > 0) {
982
+ const formData = new FormData();
983
+ formData.append('file', thumbnailInput.files[0]);
984
+ const uploadResult = await FileService.post({ body: formData });
985
+ if (uploadResult.status === 'success' && uploadResult.data && uploadResult.data.length > 0) {
986
+ cloneThumbnailId = uploadResult.data[0]._id;
987
+ } else {
988
+ NotificationManager.Push({
989
+ html: uploadResult.message || 'Failed to upload thumbnail',
990
+ status: 'error',
991
+ });
992
+ return;
993
+ }
994
+ } else if (MapEngineCyberia.captureObjLayerThumbnail) {
995
+ cloneThumbnailId = await captureObjectLayerUpload('map-thumbnail.png');
996
+ }
997
+
998
+ // The clone always gets its own automatic Object Layer preview capture.
999
+ const clonePreviewId = await captureObjectLayerUpload('map-preview.png');
1000
+
1001
+ const body = getMapPayload();
1002
+ if (cloneThumbnailId) body.thumbnail = cloneThumbnailId;
1003
+ if (clonePreviewId) body.preview = clonePreviewId;
1004
+ const result = await CyberiaMapService.post({ body });
1005
+ NotificationManager.Push({
1006
+ html: result.status === 'error' ? result.message : Translate.instance('success-create-item'),
1007
+ status: result.status,
1008
+ });
1009
+ if (result.status === 'success') {
1010
+ if (result.data?._id) MapEngineCyberia.currentMapId = result.data._id;
1011
+ if (cloneThumbnailId) MapEngineCyberia.currentThumbnailId = cloneThumbnailId;
1012
+ if (clonePreviewId) MapEngineCyberia.currentPreviewId = clonePreviewId;
1013
+ renderPreviewImage();
1014
+ await DefaultManagement.loadTable(managementId, { force: true, reload: true });
1015
+ }
1016
+ };
1017
+
1018
+ const loadMap = async (mapData) => {
1019
+ MapEngineCyberia.currentMapId = mapData._id || null;
1020
+ if (s(`.${idCode}`)) s(`.${idCode}`).value = mapData.code || '';
1021
+ if (s(`.${idName}`)) s(`.${idName}`).value = mapData.name || '';
1022
+ if (s(`.${idDescription}`)) s(`.${idDescription}`).value = mapData.description || '';
1023
+ if (s(`.${idTags}`)) s(`.${idTags}`).value = (mapData.tags || []).join(', ');
1024
+
1025
+ // Restore grid dimensions
1026
+ if (s(`.${idX}`)) s(`.${idX}`).value = mapData.gridX || 16;
1027
+ if (s(`.${idY}`)) s(`.${idY}`).value = mapData.gridY || 16;
1028
+ if (s(`.${idCellW}`)) s(`.${idCellW}`).value = mapData.cellWidth || 32;
1029
+ if (s(`.${idCellH}`)) s(`.${idCellH}`).value = mapData.cellHeight || 32;
1030
+ const statusValue = mapData.status || 'unlisted';
1031
+ if (DropDown.Tokens[idStatus]) {
1032
+ const statusIndex = statusOptions.findIndex((opt) => opt.value === statusValue);
1033
+ if (statusIndex > -1) s(`.dropdown-option-${idStatus}-${statusIndex}`).click();
1034
+ }
1035
+
1036
+ // Thumbnail
1037
+ MapEngineCyberia.currentThumbnailId = mapData.thumbnail || null;
1038
+ MapEngineCyberia.currentPreviewId = mapData.preview || null;
1039
+ renderPreviewImage();
1040
+ const thumbnailPreview = s(`.map-engine-thumbnail-preview`);
1041
+ if (MapEngineCyberia.currentThumbnailId) {
1042
+ const thumbId =
1043
+ typeof MapEngineCyberia.currentThumbnailId === 'object'
1044
+ ? MapEngineCyberia.currentThumbnailId._id
1045
+ : MapEngineCyberia.currentThumbnailId;
1046
+
1047
+ // Set preview image
1048
+ if (thumbnailPreview) {
1049
+ thumbnailPreview.innerHTML = html`<img
1050
+ src="${getApiBaseUrl({ id: thumbId, endpoint: 'file/blob' })}"
1051
+ style="max-width:120px;max-height:120px;border:1px solid #555;"
1052
+ onerror="this.style.display='none';"
1053
+ />`;
1054
+ }
1055
+
1056
+ // Populate InputFile with the actual file from server
1057
+ if (s(`.${idThumbnail}`)) {
1058
+ const fileData = await getFileFromBlobEndpoint({ _id: thumbId, mimetype: 'image/png' });
1059
+ if (fileData) {
1060
+ const dataTransfer = new DataTransfer();
1061
+ dataTransfer.items.add(fileData);
1062
+ s(`.${idThumbnail}`).files = dataTransfer.files;
1063
+ s(`.${idThumbnail}`).onchange({ target: s(`.${idThumbnail}`) });
1064
+ }
1065
+ }
1066
+ MapEngineCyberia.thumbnailDirty = false;
1067
+ } else {
1068
+ if (thumbnailPreview) thumbnailPreview.innerHTML = '';
1069
+ // Clear InputFile
1070
+ if (s(`.${idThumbnail}`)) {
1071
+ s(`.${idThumbnail}`).value = '';
1072
+ s(`.${idThumbnail}`).onchange({ target: s(`.${idThumbnail}`) });
1073
+ }
1074
+ }
1075
+
1076
+ // Creator display
1077
+ const creatorDisplay = s(`.map-engine-creator-display`);
1078
+ if (creatorDisplay) {
1079
+ if (mapData.creator) {
1080
+ const creatorUsername =
1081
+ typeof mapData.creator === 'object' ? mapData.creator.username || mapData.creator._id : mapData.creator;
1082
+ creatorDisplay.innerHTML = html`<span style="font-family:monospace;font-size:12px;"
1083
+ >${creatorUsername}</span
1084
+ >`;
1085
+ } else {
1086
+ creatorDisplay.innerHTML = html`<span style="color:#888;font-size:12px;">—</span>`;
1087
+ }
1088
+ }
1089
+
1090
+ const nextEntities = (mapData.entities || []).map((e) => ({
1091
+ entityType: e.entityType,
1092
+ initCellX: e.initCellX,
1093
+ initCellY: e.initCellY,
1094
+ dimX: e.dimX,
1095
+ dimY: e.dimY,
1096
+ color: e.color,
1097
+ objectLayerItemIds: e.objectLayerItemIds || [],
1098
+ }));
1099
+ MapEngineCyberia.setEntities(nextEntities, { clearHistory: true });
1100
+ };
1101
+
1102
+ MapEngineCyberia.loadMap = loadMap;
1103
+
1104
+ const resetForm = () => {
1105
+ MapEngineCyberia.currentMapId = null;
1106
+ MapEngineCyberia.currentThumbnailId = null;
1107
+ MapEngineCyberia.currentPreviewId = null;
1108
+ MapEngineCyberia.thumbnailDirty = false;
1109
+ if (s(`.${idCode}`)) s(`.${idCode}`).value = '';
1110
+ if (s(`.${idName}`)) s(`.${idName}`).value = '';
1111
+ if (s(`.${idDescription}`)) s(`.${idDescription}`).value = '';
1112
+ if (s(`.${idTags}`)) s(`.${idTags}`).value = '';
1113
+ if (DropDown.Tokens[idStatus]) {
1114
+ const resetIndex = statusOptions.findIndex((opt) => opt.value === 'unlisted');
1115
+ if (resetIndex > -1) s(`.dropdown-option-${idStatus}-${resetIndex}`).click();
1116
+ }
1117
+ const thumbnailPreview = s(`.map-engine-thumbnail-preview`);
1118
+ if (thumbnailPreview) thumbnailPreview.innerHTML = '';
1119
+ renderPreviewImage();
1120
+ if (s(`.${idThumbnail}`)) {
1121
+ s(`.${idThumbnail}`).value = '';
1122
+ s(`.${idThumbnail}`).onchange({ target: s(`.${idThumbnail}`) });
1123
+ }
1124
+ const creatorDisplay = s(`.map-engine-creator-display`);
1125
+ if (creatorDisplay) creatorDisplay.innerHTML = '<span style="color:#888;font-size:12px;">—</span>';
1126
+ if (s(`.${idX}`)) s(`.${idX}`).value = 16;
1127
+ if (s(`.${idY}`)) s(`.${idY}`).value = 16;
1128
+ if (s(`.${idCellW}`)) s(`.${idCellW}`).value = 32;
1129
+ if (s(`.${idCellH}`)) s(`.${idCellH}`).value = 32;
1130
+ if (s(`.${idVariationPreserve}`)) s(`.${idVariationPreserve}`).value = '';
1131
+ if (s(`.${idRenameSourceObjectLayer}`)) s(`.${idRenameSourceObjectLayer}`).value = '';
1132
+ if (s(`.${idRenameTargetObjectLayer}`)) s(`.${idRenameTargetObjectLayer}`).value = '';
1133
+ MapEngineCyberia.setEntities([], { clearHistory: true });
1134
+ MapEngineCyberia.setDropdownValue(idEntityType, DEFAULT_ENTITY_TYPE);
1135
+ if (DropDown.Tokens[idObjLayerDropdown]) {
1136
+ DropDown.Tokens[idObjLayerDropdown].oncheckvalues = {};
1137
+ DropDown.Tokens[idObjLayerDropdown].value = [];
1138
+ htmls(`.dropdown-current-${idObjLayerDropdown}`, '');
1139
+ htmls(`.${idObjLayerDropdown}-render-container`, '');
1140
+ }
1141
+ };
1142
+
1143
+ setTimeout(() => {
1144
+ const canvas = s(`.${canvasId}`);
1145
+ if (!canvas) return;
1146
+
1147
+ MapEngineCyberia.setEntityHistorySync(() => {
1148
+ MapEngineCyberia.renderEntityList(entityListId);
1149
+ rerenderCanvas();
1150
+ });
1151
+ MapEngineCyberia.bindEntityHistoryHotkeys();
1152
+
1153
+ const syncPaletteFromColorInput = () => {
1154
+ const colorPalette = s(`.${idColorPalette}`);
1155
+ const hex = (s(`.${idColor}`)?.value || '#ff0000').toUpperCase();
1156
+ if (colorPalette && colorPalette.value !== hex) {
1157
+ colorPalette.value = hex;
1158
+ }
1159
+ };
1160
+
1161
+ const updateRgbaDisplay = () => {
1162
+ const hex = s(`.${idColor}`)?.value || '#ff0000';
1163
+ const alpha = parseFloat(s(`.${idAlpha}`)?.value);
1164
+ const rgba = hexToRgba(hex, alpha);
1165
+ if (s(`.${rgbaDisplayId}`))
1166
+ htmls(
1167
+ `.${rgbaDisplayId}`,
1168
+ `<span style="display:inline-block;width:16px;height:16px;background:${rgba};border:1px solid #888;vertical-align:middle;margin-right:6px;"></span>${rgba}`,
1169
+ );
1170
+ syncPaletteFromColorInput();
1171
+ };
1172
+
1173
+ if (s(`.${idColor}`)) s(`.${idColor}`).addEventListener('input', updateRgbaDisplay);
1174
+ if (s(`.${idAlpha}`)) s(`.${idAlpha}`).addEventListener('input', updateRgbaDisplay);
1175
+ if (s(`.${idColorPalette}`)) {
1176
+ s(`.${idColorPalette}`).addEventListener('colorchange', (event) => {
1177
+ const nextHex = (event.detail?.value || event.detail?.hex || '#ff0000').toLowerCase();
1178
+ if (s(`.${idColor}`) && s(`.${idColor}`).value !== nextHex) {
1179
+ s(`.${idColor}`).value = nextHex;
1180
+ s(`.${idColor}`).dispatchEvent(new Event('input'));
1181
+ }
1182
+ });
1183
+ }
1184
+ updateRgbaDisplay();
1185
+
1186
+ const params = getCanvasParams();
1187
+ MapEngineCyberia.renderGrid(
1188
+ canvas,
1189
+ params.cols,
1190
+ params.rows,
1191
+ params.cellW,
1192
+ params.cellH,
1193
+ MapEngineCyberia.showGridBorders,
1194
+ );
1195
+ MapEngineCyberia.refreshEntityEditor();
1196
+
1197
+ canvas.onclick = (e) => {
1198
+ const rect = canvas.getBoundingClientRect();
1199
+ const { cellW, cellH } = getCanvasParams();
1200
+ const col = Math.floor(((e.clientX - rect.left) * (canvas.width / rect.width)) / cellW);
1201
+ const row = Math.floor(((e.clientY - rect.top) * (canvas.height / rect.height)) / cellH);
1202
+ console.log(`Cell clicked: (${col}, ${row})`);
1203
+
1204
+ if (s('.map-engine-cell-coords')) htmls('.map-engine-cell-coords', `Cell: (${col}, ${row})`);
1205
+
1206
+ if (s(`.${idInitCellX}`)) s(`.${idInitCellX}`).value = col;
1207
+ if (s(`.${idInitCellY}`)) s(`.${idInitCellY}`).value = row;
1208
+
1209
+ if (MapEngineCyberia.addOnClick) {
1210
+ addEntityLocally();
1211
+ } else if (MapEngineCyberia.removeOnClick) {
1212
+ MapEngineCyberia.commitEntityMutation(() => {
1213
+ MapEngineCyberia.entities = MapEngineCyberia.entities.filter(
1214
+ (entity) => !(entity.initCellX === col && entity.initCellY === row),
1215
+ );
1216
+ });
1217
+ }
1218
+ };
1219
+
1220
+ if (s(`.btn-map-engine-add-entity`)) s(`.btn-map-engine-add-entity`).onclick = () => addEntityLocally();
1221
+
1222
+ if (s(`.btn-map-engine-fill-map`)) s(`.btn-map-engine-fill-map`).onclick = () => fillMapWithEntity();
1223
+
1224
+ if (s(`.btn-map-engine-generate-variation`))
1225
+ s(`.btn-map-engine-generate-variation`).onclick = () => generateVariation();
1226
+
1227
+ if (s(`.btn-map-engine-swap-preserve-entities`))
1228
+ s(`.btn-map-engine-swap-preserve-entities`).onclick = () => randomSwapPreserveEntities();
1229
+
1230
+ if (s(`.btn-map-engine-replace-preserve-entities`))
1231
+ s(`.btn-map-engine-replace-preserve-entities`).onclick = () => replacePreserveEntitiesWithCurrentConfig();
1232
+
1233
+ if (s(`.btn-map-engine-flip-horizontal`)) s(`.btn-map-engine-flip-horizontal`).onclick = () => flipHorizontal();
1234
+
1235
+ if (s(`.btn-map-engine-flip-vertical`)) s(`.btn-map-engine-flip-vertical`).onclick = () => flipVertical();
1236
+
1237
+ if (s(`.btn-map-engine-generate`))
1238
+ s(`.btn-map-engine-generate`).onclick = () => {
1239
+ rerenderCanvas();
1240
+ };
1241
+
1242
+ if (s(`.btn-map-engine-save-map`)) s(`.btn-map-engine-save-map`).onclick = () => saveMap();
1243
+
1244
+ if (s(`.btn-map-engine-clone-map`))
1245
+ s(`.btn-map-engine-clone-map`).onclick = () => {
1246
+ if (!MapEngineCyberia.currentMapId) return;
1247
+ cloneMap();
1248
+ };
1249
+
1250
+ if (s(`.btn-map-engine-new-map`)) s(`.btn-map-engine-new-map`).onclick = () => resetForm();
1251
+
1252
+ ThemeEvents['map-engine-theme'] = () => {
1253
+ MapEngineCyberia.renderEntityList(entityListId);
1254
+ };
1255
+
1256
+ if (s(`.btn-map-engine-capture-thumbnail`))
1257
+ s(`.btn-map-engine-capture-thumbnail`).onclick = () => {
1258
+ const { cols, rows, cellW, cellH } = getCanvasParams();
1259
+ const offscreen = MapEngineCyberia.renderToOffscreenCanvas(cols, rows, cellW, cellH);
1260
+ offscreen.toBlob((blob) => {
1261
+ if (!blob) return;
1262
+ const file = new File([blob], 'map-thumbnail.png', { type: 'image/png' });
1263
+ const dataTransfer = new DataTransfer();
1264
+ dataTransfer.items.add(file);
1265
+ const thumbnailInput = s(`.${idThumbnail}`);
1266
+ if (thumbnailInput) {
1267
+ thumbnailInput.files = dataTransfer.files;
1268
+ thumbnailInput.onchange({ target: thumbnailInput });
1269
+ }
1270
+ MapEngineCyberia.thumbnailDirty = true;
1271
+ }, 'image/png');
1272
+ };
1273
+
1274
+ if (s(`.btn-map-engine-toggle-thumbnail`))
1275
+ s(`.btn-map-engine-toggle-thumbnail`).onclick = () => {
1276
+ const body = s(`.map-engine-thumbnail-body`);
1277
+ const caret = s(`.map-engine-thumbnail-caret`);
1278
+ if (body) body.classList.toggle('hide');
1279
+ if (caret) {
1280
+ caret.classList.toggle('fa-caret-right');
1281
+ caret.classList.toggle('fa-caret-down');
1282
+ }
1283
+ };
1284
+
1285
+ if (s(`.btn-map-engine-toggle-preview`))
1286
+ s(`.btn-map-engine-toggle-preview`).onclick = () => {
1287
+ const body = s(`.map-engine-preview-body`);
1288
+ const caret = s(`.map-engine-preview-caret`);
1289
+ if (body) body.classList.toggle('hide');
1290
+ if (caret) {
1291
+ caret.classList.toggle('fa-caret-right');
1292
+ caret.classList.toggle('fa-caret-down');
1293
+ }
1294
+ };
1295
+
1296
+ if (s('.btn-map-engine-toggle-entity-filter'))
1297
+ s('.btn-map-engine-toggle-entity-filter').onclick = () => {
1298
+ const body = s('.map-engine-entity-filter-body');
1299
+ const caret = s('.map-engine-entity-filter-caret');
1300
+ if (body) body.classList.toggle('hide');
1301
+ if (caret) {
1302
+ caret.classList.toggle('fa-caret-right');
1303
+ caret.classList.toggle('fa-caret-down');
1304
+ }
1305
+ };
1306
+
1307
+ let entityFilterTimeout = null;
1308
+ const applyEntityFilter = () => {
1309
+ clearTimeout(entityFilterTimeout);
1310
+ entityFilterTimeout = setTimeout(() => {
1311
+ MapEngineCyberia.renderEntityList(entityListId);
1312
+ }, 300);
1313
+ };
1314
+ [idFilterEntityType, idFilterInitX, idFilterInitY].forEach((cls) => {
1315
+ if (s(`.${cls}`)) s(`.${cls}`).addEventListener('input', applyEntityFilter);
1316
+ });
1317
+
1318
+ if (s('.btn-map-engine-clear-entity-filter'))
1319
+ s('.btn-map-engine-clear-entity-filter').onclick = () => {
1320
+ [idFilterEntityType, idFilterInitX, idFilterInitY].forEach((cls) => {
1321
+ if (s(`.${cls}`)) s(`.${cls}`).value = '';
1322
+ });
1323
+ MapEngineCyberia.renderEntityList(entityListId);
1324
+ };
1325
+
1326
+ if (s('.btn-map-engine-clear-all-entities'))
1327
+ s('.btn-map-engine-clear-all-entities').onclick = () => clearAllEntities();
1328
+
1329
+ if (s('.btn-map-engine-rename-filtered-object-layer-item-id'))
1330
+ s('.btn-map-engine-rename-filtered-object-layer-item-id').onclick = () => {
1331
+ MapEngineCyberia.renameFilteredObjectLayerItemId();
1332
+ };
1333
+ });
1334
+
1335
+ const statusOptions = [
1336
+ { value: 'unlisted', display: 'unlisted', data: 'unlisted', onClick: () => {} },
1337
+ { value: 'draft', display: 'draft', data: 'draft', onClick: () => {} },
1338
+ { value: 'published', display: 'published', data: 'published', onClick: () => {} },
1339
+ { value: 'archived', display: 'archived', data: 'archived', onClick: () => {} },
1340
+ ];
1341
+
1342
+ const managementTableHtml = await CyberiaMapManagement.instance({
1343
+ idModal: managementId,
1344
+ loadMapCallback: loadMap,
1345
+ appStore,
1346
+ readyRowDataEvent: {
1347
+ 'map-engine-check-deleted': (rowData) => {
1348
+ if (MapEngineCyberia.currentMapId) {
1349
+ const stillExists = rowData.some((row) => row._id === MapEngineCyberia.currentMapId);
1350
+ if (!stillExists) MapEngineCyberia.currentMapId = null;
1351
+ }
1352
+ },
1353
+ },
1354
+ });
1355
+
1356
+ const dcMapFields = 'map-engine-dc-fields';
1357
+ const dcMetaFields = 'map-engine-dc-meta';
1358
+ const dcGridSize = 'map-engine-dc-grid-size';
1359
+ const dcCellSize = 'map-engine-dc-cell-size';
1360
+ const dcEntityType = 'map-engine-dc-entity-type';
1361
+ const dcAlpha = 'map-engine-dc-alpha';
1362
+ const dcCellPos = 'map-engine-dc-cell-pos';
1363
+ const dcDim = 'map-engine-dc-dim';
1364
+ const dcFactors = 'map-engine-dc-factors';
1365
+ const dcSaveNew = 'map-engine-dc-save-new';
1366
+ const dcEntityFilter = 'map-engine-dc-entity-filter';
1367
+ const dcCanvasOpts = 'map-engine-dc-canvas-opts';
1368
+ const idFilterEntityType = 'map-engine-filter-entity-type';
1369
+ const idFilterInitX = 'map-engine-filter-init-x';
1370
+ const idFilterInitY = 'map-engine-filter-init-y';
1371
+
1372
+ return html`<div class="in section-mp map-engine-container">
1373
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcMapFields, type: 'search-inputs' })}
1374
+ <div class="fl">
1375
+ <div class="in fll ${dcMapFields}-col-a">
1376
+ ${await Input.instance({
1377
+ id: idCode,
1378
+ label: html`Code`,
1379
+ containerClass: 'inl',
1380
+ type: 'text',
1381
+ })}
1382
+ </div>
1383
+ <div class="in fll ${dcMapFields}-col-b">
1384
+ ${await Input.instance({
1385
+ id: idName,
1386
+ label: html`Name`,
1387
+ containerClass: 'inl',
1388
+ type: 'text',
1389
+ })}
1390
+ </div>
1391
+ <div class="in fll ${dcMapFields}-col-c">
1392
+ ${await Input.instance({
1393
+ id: idDescription,
1394
+ label: html`Description`,
1395
+ containerClass: 'inl',
1396
+ type: 'text',
1397
+ })}
1398
+ </div>
1399
+ </div>
1400
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcMetaFields, type: 'search-inputs' })}
1401
+ <div class="fl">
1402
+ <div class="in fll ${dcMetaFields}-col-a">
1403
+ ${await Input.instance({
1404
+ id: idTags,
1405
+ label: html`Tags (comma separated)`,
1406
+ containerClass: 'inl',
1407
+ type: 'text',
1408
+ })}
1409
+ </div>
1410
+ <div class="in fll ${dcMetaFields}-col-b">
1411
+ ${await DropDown.instance({
1412
+ id: idStatus,
1413
+ label: html`Status`,
1414
+ data: statusOptions.map((opt) => ({ ...opt })),
1415
+ value: 'unlisted',
1416
+ containerClass: 'inl',
1417
+ })}
1418
+ </div>
1419
+ <div class="in fll ${dcMetaFields}-col-c">
1420
+ <div class="inl">
1421
+ <div class="in input-label">Creator</div>
1422
+ <div class="in map-engine-creator-display">
1423
+ <span style="color:#888;font-size:12px;">—</span>
1424
+ </div>
1425
+ </div>
1426
+ </div>
1427
+ </div>
1428
+ <div class="in section-mp" style="margin-top: 5px;">
1429
+ <div class="in map-engine-thumbnail-preview" style="margin-bottom: 5px;"></div>
1430
+ ${await BtnIcon.instance({
1431
+ class: 'wfa btn-map-engine-capture-thumbnail',
1432
+ label: html`<i class="fa-solid fa-camera"></i> Capture Thumbnail`,
1433
+ })}
1434
+ <div class="fl" style="align-items: center; gap: 8px; font-size: 20px; text-align: left; margin: 5px 0;">
1435
+ ${await ToggleSwitch.instance({
1436
+ id: 'map-engine-capture-obj-layer-thumb',
1437
+ type: 'checkbox',
1438
+ displayMode: 'checkbox',
1439
+ containerClass: 'in fll',
1440
+ checked: true,
1441
+ on: {
1442
+ checked: () => {
1443
+ MapEngineCyberia.captureObjLayerThumbnail = true;
1444
+ },
1445
+ unchecked: () => {
1446
+ MapEngineCyberia.captureObjLayerThumbnail = false;
1447
+ },
1448
+ },
1449
+ })}
1450
+ <div class="section-mp">&nbsp &nbsp Capture Object Layer Map Thumbnail on Save/Update/Clone</div>
1451
+ </div>
1452
+ ${await BtnIcon.instance({
1453
+ class: 'wfa btn-map-engine-toggle-thumbnail',
1454
+ label: html`<i class="fa-solid fa-caret-right map-engine-thumbnail-caret"></i> Thumbnail`,
1455
+ })}
1456
+ <div class="in map-engine-thumbnail-body hide">
1457
+ ${await InputFile.instance(
1458
+ {
1459
+ id: idThumbnail,
1460
+ multiple: false,
1461
+ extensionsAccept: ['image/png', 'image/jpeg'],
1462
+ },
1463
+ {
1464
+ change: (e) => {
1465
+ const file = e.target.files[0];
1466
+ if (file) {
1467
+ MapEngineCyberia.thumbnailDirty = true;
1468
+ const url = URL.createObjectURL(file);
1469
+ const preview = s('.map-engine-thumbnail-preview');
1470
+ if (preview)
1471
+ preview.innerHTML = html`<img
1472
+ src="${url}"
1473
+ class="in"
1474
+ style="max-width:300px;height:auto;border:1px solid #555;margin:auto"
1475
+ />`;
1476
+ }
1477
+ },
1478
+ clear: () => {
1479
+ MapEngineCyberia.thumbnailDirty = true;
1480
+ MapEngineCyberia.currentThumbnailId = null;
1481
+ const preview = s('.map-engine-thumbnail-preview');
1482
+ if (preview) preview.innerHTML = '';
1483
+ },
1484
+ },
1485
+ )}
1486
+ </div>
1487
+ ${await BtnIcon.instance({
1488
+ class: 'wfa btn-map-engine-toggle-preview',
1489
+ label: html`<i class="fa-solid fa-caret-right map-engine-preview-caret"></i> Instance Map Preview`,
1490
+ })}
1491
+ <div class="in map-engine-preview-body hide">
1492
+ <div class="in map-engine-preview-image" style="margin: 5px 0; text-align: center;"></div>
1493
+ <div class="in" style="color:#888;font-size:12px;">
1494
+ Auto-captured Object Layer render on Save/Update/Clone — used as this map's node background in the
1495
+ Instance Map.
1496
+ </div>
1497
+ </div>
1498
+ </div>
1499
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcGridSize, type: 'a-50-b-50' })}
1500
+ <div class="fl">
1501
+ <div class="in fll ${dcGridSize}-col-a">
1502
+ ${await Input.instance({
1503
+ id: idX,
1504
+ label: html`X`,
1505
+ containerClass: 'inl',
1506
+ type: 'number',
1507
+ min: 1,
1508
+ value: 16,
1509
+ })}
1510
+ </div>
1511
+ <div class="in fll ${dcGridSize}-col-b">
1512
+ ${await Input.instance({
1513
+ id: idY,
1514
+ label: html`Y`,
1515
+ containerClass: 'inl',
1516
+ type: 'number',
1517
+ min: 1,
1518
+ value: 16,
1519
+ })}
1520
+ </div>
1521
+ </div>
1522
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcCellSize, type: 'a-50-b-50' })}
1523
+ <div class="fl">
1524
+ <div class="in fll ${dcCellSize}-col-a">
1525
+ ${await Input.instance({
1526
+ id: idCellW,
1527
+ label: html`Cell Width (px)`,
1528
+ containerClass: 'inl',
1529
+ type: 'number',
1530
+ min: 1,
1531
+ value: 32,
1532
+ })}
1533
+ </div>
1534
+ <div class="in fll ${dcCellSize}-col-b">
1535
+ ${await Input.instance({
1536
+ id: idCellH,
1537
+ label: html`Cell Height (px)`,
1538
+ containerClass: 'inl',
1539
+ type: 'number',
1540
+ min: 1,
1541
+ value: 32,
1542
+ })}
1543
+ </div>
1544
+ </div>
1545
+ <div class="fl">
1546
+ <div class="in wfa" style="padding: 10px; max-width: 200px; margin: auto;">
1547
+ ${await BtnIcon.instance({
1548
+ class: 'wfa btn-map-engine-generate',
1549
+ label: html`<i class="fa-solid fa-arrows-rotate"></i> Generate`,
1550
+ })}
1551
+ </div>
1552
+ </div>
1553
+ <div class="in" style="text-align: center; margin-top: 10px;">
1554
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcCanvasOpts, type: 'search-inputs' })}
1555
+ <div class="fl" style="margin-bottom: 5px;">
1556
+ <div class="in fll ${dcCanvasOpts}-col-a">
1557
+ <div class="in section-mp-border" style="padding: 10px;">
1558
+ <div class="in input-label" style="margin-bottom: 6px; font-size: 14px;">Click Action</div>
1559
+ <div class="fl" style="align-items: center; gap: 8px; font-size: 20px; text-align: left;">
1560
+ ${await ToggleSwitch.instance({
1561
+ id: 'map-engine-add-on-click',
1562
+ type: 'checkbox',
1563
+ displayMode: 'checkbox',
1564
+ containerClass: 'in fll',
1565
+ checked: true,
1566
+ on: {
1567
+ checked: () => {
1568
+ MapEngineCyberia.addOnClick = true;
1569
+ MapEngineCyberia.removeOnClick = false;
1570
+ const removeToken = ToggleSwitch.Tokens['map-engine-remove-on-click'];
1571
+ if (removeToken) {
1572
+ const removeCheckbox = s('.map-engine-remove-on-click-checkbox');
1573
+ if (removeCheckbox && removeCheckbox.checked) removeToken.click();
1574
+ }
1575
+ },
1576
+ unchecked: () => {
1577
+ MapEngineCyberia.addOnClick = false;
1578
+ },
1579
+ },
1580
+ })}
1581
+ <div class="section-mp">&nbsp &nbsp Add on Click</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-remove-on-click',
1589
+ type: 'checkbox',
1590
+ displayMode: 'checkbox',
1591
+ containerClass: 'in fll',
1592
+ checked: false,
1593
+ on: {
1594
+ checked: () => {
1595
+ MapEngineCyberia.removeOnClick = true;
1596
+ MapEngineCyberia.addOnClick = false;
1597
+ const addToken = ToggleSwitch.Tokens['map-engine-add-on-click'];
1598
+ if (addToken) {
1599
+ const addCheckbox = s('.map-engine-add-on-click-checkbox');
1600
+ if (addCheckbox && addCheckbox.checked) addToken.click();
1601
+ }
1602
+ },
1603
+ unchecked: () => {
1604
+ MapEngineCyberia.removeOnClick = false;
1605
+ },
1606
+ },
1607
+ })}
1608
+ <div class="section-mp">&nbsp &nbsp Remove on Click</div>
1609
+ </div>
1610
+ </div>
1611
+ </div>
1612
+ <div class="in fll ${dcCanvasOpts}-col-b">
1613
+ <div class="in section-mp-border" style="padding: 10px;">
1614
+ <div class="in input-label" style="margin-bottom: 6px; font-size: 14px;">View Options</div>
1615
+ <div class="fl" style="align-items: center; gap: 8px; font-size: 20px; text-align: left;">
1616
+ ${await ToggleSwitch.instance({
1617
+ id: 'map-engine-show-grid',
1618
+ type: 'checkbox',
1619
+ displayMode: 'checkbox',
1620
+ containerClass: 'in fll',
1621
+ checked: true,
1622
+ on: {
1623
+ checked: () => {
1624
+ MapEngineCyberia.showGridBorders = true;
1625
+ rerenderCanvas();
1626
+ },
1627
+ unchecked: () => {
1628
+ MapEngineCyberia.showGridBorders = false;
1629
+ rerenderCanvas();
1630
+ },
1631
+ },
1632
+ })}
1633
+ <div class="section-mp">&nbsp &nbsp Show Grid</div>
1634
+ </div>
1635
+ <div
1636
+ class="fl"
1637
+ style="align-items: center; gap: 8px; font-size: 20px; text-align: left; margin-top: 4px;"
1638
+ >
1639
+ ${await ToggleSwitch.instance({
1640
+ id: 'map-engine-show-object-layers',
1641
+ type: 'checkbox',
1642
+ displayMode: 'checkbox',
1643
+ containerClass: 'in fll',
1644
+ checked: false,
1645
+ on: {
1646
+ checked: () => {
1647
+ MapEngineCyberia.showObjectLayers = true;
1648
+ rerenderCanvas();
1649
+ },
1650
+ unchecked: () => {
1651
+ MapEngineCyberia.showObjectLayers = false;
1652
+ rerenderCanvas();
1653
+ },
1654
+ },
1655
+ })}
1656
+ <div class="section-mp">&nbsp &nbsp Object Layers</div>
1657
+ </div>
1658
+ </div>
1659
+ </div>
1660
+ </div>
1661
+ <canvas class="${canvasId}" width="512" height="512" style="border: 1px solid #555;"></canvas>
1662
+ <div class="in map-engine-cell-coords" style="font-family:monospace;font-size:13px;color:#888;margin-top:4px;">
1663
+ Cell: (0, 0)
1664
+ </div>
1665
+ </div>
1666
+ <div class="in section-mp" style="margin-top: 10px;">
1667
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcEntityType, type: 'a-50-b-50' })}
1668
+ <div class="fl">
1669
+ <div class="in fll ${dcEntityType}-col-a">
1670
+ ${await DropDown.instance({
1671
+ id: idEntityType,
1672
+ label: html`Entity Type`,
1673
+ data: MapEngineCyberia.getEntityTypeDropdownOptions(),
1674
+ value: DEFAULT_ENTITY_TYPE,
1675
+ containerClass: 'inl',
1676
+ })}
1677
+ </div>
1678
+ <div class="in fll ${dcEntityType}-col-b">
1679
+ ${await Input.instance({
1680
+ id: idColor,
1681
+ label: html`Color`,
1682
+ containerClass: 'inl',
1683
+ type: 'color',
1684
+ value: '#ff0000',
1685
+ })}
1686
+ </div>
1687
+ </div>
1688
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcAlpha, type: 'a-50-b-50' })}
1689
+ <div class="fl">
1690
+ <div class="in fll ${dcAlpha}-col-a">
1691
+ <div class="inl input-container-${idAlpha}">
1692
+ <div class="in">
1693
+ <div class="in input-label">Alpha</div>
1694
+ <label for="${idAlpha}-name">
1695
+ <span class="hide">Alpha</span>
1696
+ <input
1697
+ type="range"
1698
+ class="in wfa ${idAlpha}"
1699
+ min="0"
1700
+ max="1"
1701
+ step="0.01"
1702
+ value="1"
1703
+ name="${idAlpha}-name"
1704
+ id="${idAlpha}-name"
1705
+ />
1706
+ </label>
1707
+ </div>
1708
+ </div>
1709
+ </div>
1710
+ <div class="in fll ${dcAlpha}-col-b" style="line-height: 40px;">
1711
+ <div class="in input-label">RGBA</div>
1712
+ <div class="in ${rgbaDisplayId}" style="font-family: monospace; font-size: 13px;"></div>
1713
+ </div>
1714
+ </div>
1715
+ <div class="in section-mp-border" style="margin-top: 10px;">
1716
+ <div class="in input-label">Color Palette</div>
1717
+ <color-palette class="${idColorPalette}" value="#FF0000"></color-palette>
1718
+ </div>
1719
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcCellPos, type: 'a-50-b-50' })}
1720
+ <div class="fl">
1721
+ <div class="in fll ${dcCellPos}-col-a">
1722
+ ${await Input.instance({
1723
+ id: idInitCellX,
1724
+ label: html`initCellX`,
1725
+ containerClass: 'inl',
1726
+ type: 'number',
1727
+ min: 0,
1728
+ value: 0,
1729
+ })}
1730
+ </div>
1731
+ <div class="in fll ${dcCellPos}-col-b">
1732
+ ${await Input.instance({
1733
+ id: idInitCellY,
1734
+ label: html`initCellY`,
1735
+ containerClass: 'inl',
1736
+ type: 'number',
1737
+ min: 0,
1738
+ value: 0,
1739
+ })}
1740
+ </div>
1741
+ </div>
1742
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcDim, type: 'a-50-b-50' })}
1743
+ <div class="fl">
1744
+ <div class="in fll ${dcDim}-col-a">
1745
+ ${await Input.instance({
1746
+ id: idDimX,
1747
+ label: html`dimX`,
1748
+ containerClass: 'inl',
1749
+ type: 'number',
1750
+ min: 1,
1751
+ value: 1,
1752
+ })}
1753
+ </div>
1754
+ <div class="in fll ${dcDim}-col-b">
1755
+ ${await Input.instance({
1756
+ id: idDimY,
1757
+ label: html`dimY`,
1758
+ containerClass: 'inl',
1759
+ type: 'number',
1760
+ min: 1,
1761
+ value: 1,
1762
+ })}
1763
+ </div>
1764
+ </div>
1765
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcFactors, type: 'a-50-b-50' })}
1766
+ <div class="fl">
1767
+ <div class="in fll ${dcFactors}-col-a">
1768
+ ${await Input.instance({
1769
+ id: idFactorA,
1770
+ label: html`factorA`,
1771
+ containerClass: 'inl',
1772
+ type: 'number',
1773
+ step: 0.01,
1774
+ value: 0.5,
1775
+ })}
1776
+ </div>
1777
+ <div class="in fll ${dcFactors}-col-b">
1778
+ ${await Input.instance({
1779
+ id: idFactorB,
1780
+ label: html`factorB`,
1781
+ containerClass: 'inl',
1782
+ type: 'number',
1783
+ step: 0.01,
1784
+ value: 1.5,
1785
+ })}
1786
+ </div>
1787
+ </div>
1788
+ ${await Input.instance({
1789
+ id: idVariationPreserve,
1790
+ label: html`Variation Preserve List`,
1791
+ containerClass: 'inl',
1792
+ type: 'text',
1793
+ placeholder: true,
1794
+ })}
1795
+ <div class="fl" style="align-items: center; gap: 8px; font-size: 20px; text-align: left; margin: 5px 0;">
1796
+ ${await ToggleSwitch.instance({
1797
+ id: 'map-engine-random-dim',
1798
+ type: 'checkbox',
1799
+ displayMode: 'checkbox',
1800
+ containerClass: 'in fll',
1801
+ checked: false,
1802
+ on: {
1803
+ checked: () => {
1804
+ MapEngineCyberia.enableRandomFactors = true;
1805
+ },
1806
+ unchecked: () => {
1807
+ MapEngineCyberia.enableRandomFactors = false;
1808
+ },
1809
+ },
1810
+ })}
1811
+ <div class="section-mp">&nbsp &nbsp Enable Random Factors</div>
1812
+ </div>
1813
+ <div class="in" style="margin: 10px;">
1814
+ <div class="${idObjLayerDropdownHost}">${await MapEngineCyberia.buildObjectLayerDropdown()}</div>
1815
+ </div>
1816
+ <div class="in section-mp-border" style="margin: 10px; padding: 10px;">
1817
+ <div class="in input-label">Rename Object Layer ItemId on Filtered Entities</div>
1818
+ <div class="in" style="font-size:12px;color:#888;margin-bottom:8px;">
1819
+ Replaces only exact source ItemId matches inside entities currently visible through the filters.
1820
+ </div>
1821
+ <div class="fl">
1822
+ <div class="in fll" style="flex:1;padding-right:5px;">
1823
+ ${await Input.instance({
1824
+ id: idRenameSourceObjectLayer,
1825
+ label: html`Source ItemId`,
1826
+ containerClass: 'inl',
1827
+ type: 'text',
1828
+ placeholder: true,
1829
+ })}
1830
+ </div>
1831
+ <div class="in fll" style="flex:1;padding-left:5px;">
1832
+ ${await Input.instance({
1833
+ id: idRenameTargetObjectLayer,
1834
+ label: html`Target ItemId`,
1835
+ containerClass: 'inl',
1836
+ type: 'text',
1837
+ placeholder: true,
1838
+ })}
1839
+ </div>
1840
+ </div>
1841
+ <div class="in" style="margin-top: 5px;">
1842
+ ${await BtnIcon.instance({
1843
+ class: 'wfa btn-map-engine-rename-filtered-object-layer-item-id',
1844
+ label: html`<i class="fa-solid fa-arrow-right-arrow-left"></i> Rename Filtered ItemId`,
1845
+ })}
1846
+ </div>
1847
+ </div>
1848
+ <div class="in">
1849
+ ${await BtnIcon.instance({
1850
+ class: 'wfa btn-map-engine-add-entity',
1851
+ label: html`<i class="fa-solid fa-plus"></i> Add Entity`,
1852
+ })}
1853
+ </div>
1854
+ <div class="in" style="margin-top: 5px;">
1855
+ ${await BtnIcon.instance({
1856
+ class: 'wfa btn-map-engine-fill-map',
1857
+ label: html`<i class="fa-solid fa-fill-drip"></i> Map Fill`,
1858
+ })}
1859
+ </div>
1860
+ <div class="in" style="margin-top: 5px;">
1861
+ ${await BtnIcon.instance({
1862
+ class: 'wfa btn-map-engine-generate-variation',
1863
+ label: html`<i class="fa-solid fa-shuffle"></i> Generate Variation`,
1864
+ })}
1865
+ </div>
1866
+ <div class="in" style="margin-top: 5px;">
1867
+ ${await BtnIcon.instance({
1868
+ class: 'wfa btn-map-engine-swap-preserve-entities',
1869
+ label: html`<i class="fa-solid fa-arrows-rotate"></i> Swap Preserve Positions`,
1870
+ })}
1871
+ </div>
1872
+ <div class="in" style="margin-top: 5px;">
1873
+ ${await BtnIcon.instance({
1874
+ class: 'wfa btn-map-engine-replace-preserve-entities',
1875
+ label: html`<i class="fa-solid fa-wand-magic-sparkles"></i> Replace Preserve Entities`,
1876
+ })}
1877
+ </div>
1878
+ <div class="in" style="margin-top: 5px;">
1879
+ ${await BtnIcon.instance({
1880
+ class: 'wfa btn-map-engine-flip-horizontal',
1881
+ label: html`<i class="fa-solid fa-arrows-left-right"></i> Flip Horizontal`,
1882
+ })}
1883
+ </div>
1884
+ <div class="in" style="margin-top: 5px;">
1885
+ ${await BtnIcon.instance({
1886
+ class: 'wfa btn-map-engine-flip-vertical',
1887
+ label: html`<i class="fa-solid fa-arrows-up-down"></i> Flip Vertical`,
1888
+ })}
1889
+ </div>
1890
+ <div class="in" style="margin-top: 10px;">
1891
+ ${await BtnIcon.instance({
1892
+ class: 'wfa btn-map-engine-toggle-entity-filter',
1893
+ label: html`<i class="fa-solid fa-caret-right map-engine-entity-filter-caret"></i> Filters`,
1894
+ })}
1895
+ <div class="in map-engine-entity-filter-body hide">
1896
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcEntityFilter, type: 'search-inputs' })}
1897
+ <div class="fl">
1898
+ <div class="in fll ${dcEntityFilter}-col-a">
1899
+ ${await Input.instance({
1900
+ id: idFilterEntityType,
1901
+ label: html`Entity Type`,
1902
+ containerClass: 'inl',
1903
+ type: 'text',
1904
+ placeholder: true,
1905
+ })}
1906
+ </div>
1907
+ <div class="in fll ${dcEntityFilter}-col-b">
1908
+ ${await Input.instance({
1909
+ id: idFilterInitX,
1910
+ label: html`initCellX`,
1911
+ containerClass: 'inl',
1912
+ type: 'text',
1913
+ placeholder: true,
1914
+ })}
1915
+ </div>
1916
+ <div class="in fll ${dcEntityFilter}-col-c">
1917
+ ${await Input.instance({
1918
+ id: idFilterInitY,
1919
+ label: html`initCellY`,
1920
+ containerClass: 'inl',
1921
+ type: 'text',
1922
+ placeholder: true,
1923
+ })}
1924
+ </div>
1925
+ </div>
1926
+ <div
1927
+ class="in map-engine-entity-filter-count"
1928
+ style="margin-top:5px;font-size:12px;color:#888;font-family:monospace;"
1929
+ >
1930
+ Showing 0 of 0 entities
1931
+ </div>
1932
+ <div class="in" style="margin-top:5px;">
1933
+ ${await BtnIcon.instance({
1934
+ class: 'wfa btn-map-engine-clear-entity-filter',
1935
+ label: html`<i class="fa-solid fa-broom"></i> Clear Filters`,
1936
+ })}
1937
+ </div>
1938
+ <div class="in" style="margin-top:5px;">
1939
+ ${await BtnIcon.instance({
1940
+ class: 'wfa btn-map-engine-clear-all-entities',
1941
+ label: html`<i class="fa-solid fa-trash-can"></i> Delete All Entities`,
1942
+ })}
1943
+ </div>
1944
+ </div>
1945
+ </div>
1946
+ <div class="in ${entityListId}" style="margin-top: 10px; max-height: 200px; overflow-y: auto;"></div>
1947
+ ${dynamicCol({ containerSelector: 'map-engine-container', id: dcSaveNew, type: 'search-inputs' })}
1948
+ <div class="fl" style="margin-top: 10px;">
1949
+ ${canMutate
1950
+ ? html`<div class="in fll ${dcSaveNew}-col-a" style="padding: 5px;">
1951
+ ${await BtnIcon.instance({
1952
+ class: 'wfa btn-map-engine-save-map',
1953
+ label: html`<i class="fa-solid fa-floppy-disk"></i> Save Map`,
1954
+ })}
1955
+ </div>
1956
+ <div class="in fll ${dcSaveNew}-col-b" style="padding: 5px;">
1957
+ ${await BtnIcon.instance({
1958
+ class: 'wfa btn-map-engine-clone-map',
1959
+ label: html`<i class="fa-solid fa-clone"></i> Clone Map`,
1960
+ })}
1961
+ </div>`
1962
+ : ''}
1963
+ <div class="in fll ${dcSaveNew}-col-c" style="padding: 5px;">
1964
+ ${await BtnIcon.instance({
1965
+ class: 'wfa btn-map-engine-new-map',
1966
+ label: html`<i class="fa-solid fa-file"></i> New Map`,
1967
+ })}
1968
+ </div>
1969
+ </div>
1970
+ <div class="in" style="margin-top: 10px;">${managementTableHtml}</div>
1971
+ </div>
1972
+ </div>`;
1973
+ }
1974
+ }
1975
+
1976
+ export { MapEngineCyberia };