cyberia 3.0.2 → 3.1.3

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 (182) hide show
  1. package/{.env.production → .env.example} +20 -2
  2. package/.github/workflows/engine-cyberia.cd.yml +41 -10
  3. package/.github/workflows/engine-cyberia.ci.yml +53 -14
  4. package/.github/workflows/ghpkg.ci.yml +1 -1
  5. package/.github/workflows/gitlab.ci.yml +1 -1
  6. package/.github/workflows/hardhat.ci.yml +82 -0
  7. package/.github/workflows/npmpkg.ci.yml +37 -8
  8. package/.github/workflows/publish.ci.yml +5 -5
  9. package/.github/workflows/publish.cyberia.ci.yml +5 -5
  10. package/.github/workflows/pwa-microservices-template-page.cd.yml +3 -3
  11. package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
  12. package/.github/workflows/release.cd.yml +3 -2
  13. package/.vscode/extensions.json +9 -8
  14. package/.vscode/settings.json +3 -2
  15. package/CHANGELOG.md +533 -290
  16. package/CLI-HELP.md +79 -53
  17. package/WHITE-PAPER.md +1540 -0
  18. package/bin/build.js +16 -11
  19. package/bin/cyberia.js +959 -8
  20. package/bin/deploy.js +103 -270
  21. package/bin/file.js +2 -1
  22. package/bin/index.js +959 -8
  23. package/bin/vs.js +3 -3
  24. package/conf.js +277 -77
  25. package/deployment.yaml +218 -4
  26. package/hardhat/.env.example +31 -0
  27. package/hardhat/README.md +531 -0
  28. package/hardhat/WHITE-PAPER.md +1540 -0
  29. package/hardhat/contracts/ObjectLayerToken.sol +391 -0
  30. package/hardhat/deployments/.gitkeep +0 -0
  31. package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
  32. package/hardhat/hardhat.config.js +136 -0
  33. package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
  34. package/hardhat/networks/besu-object-layer.network.json +138 -0
  35. package/hardhat/package-lock.json +7628 -0
  36. package/hardhat/package.json +45 -0
  37. package/hardhat/scripts/deployObjectLayerToken.js +98 -0
  38. package/hardhat/test/ObjectLayerToken.js +590 -0
  39. package/jsdoc.dd-cyberia.json +59 -0
  40. package/jsdoc.json +20 -13
  41. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  42. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  43. package/manifests/deployment/dd-cyberia-development/deployment.yaml +490 -0
  44. package/manifests/deployment/dd-cyberia-development/proxy.yaml +261 -0
  45. package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +132 -0
  46. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  47. package/manifests/deployment/dd-test-development/deployment.yaml +52 -52
  48. package/manifests/deployment/dd-test-development/proxy.yaml +4 -4
  49. package/manifests/pv-pvc-dd.yaml +1 -1
  50. package/package.json +60 -50
  51. package/proxy.yaml +128 -9
  52. package/pv-pvc.yaml +132 -0
  53. package/scripts/k3s-node-setup.sh +1 -1
  54. package/scripts/ports-ls.sh +2 -0
  55. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +3 -1
  56. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +1 -2
  57. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +40 -7
  58. package/src/api/document/document.service.js +1 -1
  59. package/src/api/file/file.controller.js +3 -1
  60. package/src/api/file/file.service.js +28 -5
  61. package/src/api/ipfs/ipfs.service.js +2 -2
  62. package/src/api/object-layer/object-layer.controller.js +6 -2
  63. package/src/api/object-layer/object-layer.model.js +67 -21
  64. package/src/api/object-layer/object-layer.router.js +668 -42
  65. package/src/api/object-layer/object-layer.service.js +10 -16
  66. package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +1 -2
  67. package/src/api/user/user.router.js +10 -5
  68. package/src/api/user/user.service.js +7 -7
  69. package/src/cli/baremetal.js +6 -10
  70. package/src/cli/cloud-init.js +0 -3
  71. package/src/cli/db.js +54 -71
  72. package/src/cli/deploy.js +64 -12
  73. package/src/cli/env.js +5 -5
  74. package/src/cli/fs.js +0 -2
  75. package/src/cli/image.js +0 -3
  76. package/src/cli/index.js +41 -13
  77. package/src/cli/monitor.js +5 -6
  78. package/src/cli/repository.js +329 -46
  79. package/src/cli/run.js +210 -122
  80. package/src/cli/secrets.js +1 -3
  81. package/src/cli/ssh.js +1 -1
  82. package/src/client/Itemledger.index.js +1 -959
  83. package/src/client/Underpost.index.js +36 -0
  84. package/src/client/components/core/AgGrid.js +20 -5
  85. package/src/client/components/core/Alert.js +2 -2
  86. package/src/client/components/core/Content.js +22 -3
  87. package/src/client/components/core/Docs.js +30 -6
  88. package/src/client/components/core/FileExplorer.js +71 -4
  89. package/src/client/components/core/Input.js +1 -1
  90. package/src/client/components/core/Modal.js +22 -6
  91. package/src/client/components/core/PublicProfile.js +3 -3
  92. package/src/client/components/core/RichText.js +1 -2
  93. package/src/client/components/core/Router.js +34 -1
  94. package/src/client/components/core/Worker.js +1 -1
  95. package/src/client/components/cryptokoyn/CssCryptokoyn.js +63 -1
  96. package/src/client/components/cyberia/ObjectLayerEngineModal.js +145 -119
  97. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +64 -6
  98. package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +1 -0
  99. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +44 -2
  100. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +0 -1
  101. package/src/client/components/cyberia-portal/MenuCyberiaPortal.js +64 -2
  102. package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +1 -0
  103. package/src/client/components/itemledger/CssItemledger.js +62 -0
  104. package/src/client/components/underpost/CommonUnderpost.js +29 -0
  105. package/src/client/components/underpost/CssUnderpost.js +281 -0
  106. package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +879 -0
  107. package/src/client/components/underpost/DocumentSearchProvider.js +448 -0
  108. package/src/client/components/underpost/ElementsUnderpost.js +38 -0
  109. package/src/client/components/underpost/LabGalleryUnderpost.js +82 -0
  110. package/src/client/components/underpost/LogInUnderpost.js +23 -0
  111. package/src/client/components/underpost/LogOutUnderpost.js +15 -0
  112. package/src/client/components/underpost/MenuUnderpost.js +691 -0
  113. package/src/client/components/underpost/RoutesUnderpost.js +47 -0
  114. package/src/client/components/underpost/SettingsUnderpost.js +16 -0
  115. package/src/client/components/underpost/SignUpUnderpost.js +9 -0
  116. package/src/client/components/underpost/SocketIoUnderpost.js +54 -0
  117. package/src/client/components/underpost/TranslateUnderpost.js +10 -0
  118. package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
  119. package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
  120. package/src/client/public/cryptokoyn/microdata.json +85 -0
  121. package/src/client/public/cryptokoyn/site.webmanifest +57 -0
  122. package/src/client/public/cryptokoyn/sitemap +3 -3
  123. package/src/client/public/default/sitemap +3 -3
  124. package/src/client/public/itemledger/browserconfig.xml +2 -2
  125. package/src/client/public/itemledger/manifest.webmanifest +4 -4
  126. package/src/client/public/itemledger/microdata.json +71 -0
  127. package/src/client/public/itemledger/sitemap +3 -3
  128. package/src/client/public/itemledger/yandex-browser-manifest.json +2 -2
  129. package/src/client/public/test/sitemap +3 -3
  130. package/src/client/services/object-layer/object-layer.management.js +23 -4
  131. package/src/client/ssr/body/404.js +15 -11
  132. package/src/client/ssr/body/500.js +15 -11
  133. package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
  134. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +83 -0
  135. package/src/client/ssr/head/PwaItemledger.js +60 -0
  136. package/src/client/ssr/head/UnderpostScripts.js +6 -0
  137. package/src/client/ssr/offline/NoNetworkConnection.js +11 -10
  138. package/src/client/ssr/pages/Test.js +11 -10
  139. package/src/client.build.js +0 -3
  140. package/src/client.dev.js +0 -3
  141. package/src/db/DataBaseProvider.js +17 -2
  142. package/src/db/mariadb/MariaDB.js +14 -9
  143. package/src/db/mongo/MongooseDB.js +17 -1
  144. package/src/index.js +1 -1
  145. package/src/proxy.js +0 -3
  146. package/src/runtime/express/Express.js +15 -9
  147. package/src/runtime/lampp/Lampp.js +6 -13
  148. package/src/server/auth.js +12 -14
  149. package/src/server/backup.js +2 -3
  150. package/src/server/besu-genesis-generator.js +1630 -0
  151. package/src/server/client-build-docs.js +126 -17
  152. package/src/server/client-build-live.js +9 -18
  153. package/src/server/client-build.js +203 -75
  154. package/src/server/client-dev-server.js +14 -13
  155. package/src/server/conf.js +376 -164
  156. package/src/server/cron.js +2 -1
  157. package/src/server/dns.js +28 -12
  158. package/src/server/downloader.js +0 -2
  159. package/src/server/logger.js +27 -9
  160. package/src/server/object-layer.js +92 -16
  161. package/src/server/peer.js +0 -2
  162. package/src/server/process.js +1 -50
  163. package/src/server/proxy.js +4 -8
  164. package/src/server/runtime.js +5 -8
  165. package/src/server/semantic-layer-generator.js +1 -0
  166. package/src/server/ssr.js +0 -3
  167. package/src/server/start.js +19 -12
  168. package/src/server/tls.js +0 -2
  169. package/src/server.js +0 -4
  170. package/.env.development +0 -43
  171. package/.env.test +0 -43
  172. package/hardhat/contracts/CryptoKoyn.sol +0 -59
  173. package/hardhat/contracts/ItemLedger.sol +0 -73
  174. package/hardhat/contracts/Lock.sol +0 -34
  175. package/hardhat/hardhat.config.cjs +0 -45
  176. package/hardhat/ignition/modules/Lock.js +0 -18
  177. package/hardhat/networks/cryptokoyn-itemledger.network.json +0 -29
  178. package/hardhat/scripts/deployCryptokoyn.cjs +0 -25
  179. package/hardhat/scripts/deployItemledger.cjs +0 -25
  180. package/hardhat/test/Lock.js +0 -126
  181. package/hardhat/white-paper.md +0 -581
  182. package/white-paper.md +0 -581
@@ -192,6 +192,16 @@ const ObjectLayerEngineModal = {
192
192
  const { Elements } = options;
193
193
 
194
194
  const directionCodes = ['08', '18', '02', '12', '04', '14', '06', '16'];
195
+ const directionCodeLabels = {
196
+ '08': 'Down Idle',
197
+ 18: 'Down Walk',
198
+ '02': 'Up Idle',
199
+ 12: 'Up Walk',
200
+ '04': 'Left Idle',
201
+ 14: 'Left Walk',
202
+ '06': 'Right Idle',
203
+ 16: 'Right Walk',
204
+ };
195
205
  const itemTypes = ['skin', 'weapon', 'armor', 'artifact', 'floor'];
196
206
  const statTypes = ['effect', 'resistance', 'agility', 'range', 'intelligence', 'utility'];
197
207
 
@@ -355,7 +365,7 @@ const ObjectLayerEngineModal = {
355
365
  const capturedDirectionCode = directionCode;
356
366
 
357
367
  if (!s(`.frames-${capturedDirectionCode}`)) {
358
- logger.warn(`Frames container for direction code ${capturedDirectionCode} not found`);
368
+ console.warn(`Frames container for direction code ${capturedDirectionCode} not found`);
359
369
  return;
360
370
  }
361
371
 
@@ -481,7 +491,7 @@ const ObjectLayerEngineModal = {
481
491
  let loader = s('object-layer-png-loader');
482
492
 
483
493
  if (!ole || !loader) {
484
- logger.warn('object-layer-engine or object-layer-png-loader component not found after retries');
494
+ console.warn('object-layer-engine or object-layer-png-loader component not found after retries');
485
495
  return;
486
496
  }
487
497
 
@@ -516,7 +526,7 @@ const ObjectLayerEngineModal = {
516
526
  <div class="in section-mp-border">
517
527
  <div class="fl">
518
528
  <div class="in fll">
519
- <div class="in direction-code-bar-frames-title">${directionCode}</div>
529
+ <div class="in direction-code-bar-frames-title">${directionCodeLabels[directionCode]}</div>
520
530
  <div class="in direction-code-bar-frames-btn">
521
531
  ${await BtnIcon.Render({
522
532
  label: html`
@@ -564,139 +574,153 @@ const ObjectLayerEngineModal = {
564
574
  }
565
575
 
566
576
  setTimeout(async () => {
577
+ let loadFramesInProgress = false;
567
578
  const loadFrames = async () => {
568
- showFrameLoading();
569
-
570
- // Clear all frames and data at the start to prevent duplication from multiple calls
571
- // This must happen BEFORE any async operations to avoid race conditions
572
- for (const directionCode of directionCodes) {
573
- // Clear DOM frames for this direction code
574
- const framesContainer = s(`.frames-${directionCode}`);
575
- if (framesContainer) {
576
- framesContainer.innerHTML = '';
577
- }
578
- // Clear data for this direction code
579
- ObjectLayerEngineModal.ObjectLayerData[directionCode] = [];
579
+ // Concurrency guard: skip if already loading to prevent duplicate frames
580
+ if (loadFramesInProgress) {
581
+ console.warn('loadFrames already in progress, skipping duplicate call');
582
+ return;
580
583
  }
584
+ loadFramesInProgress = true;
585
+
586
+ try {
587
+ showFrameLoading();
588
+
589
+ // Clear all frames and data at the start to prevent duplication from multiple calls
590
+ // This must happen BEFORE any async operations to avoid race conditions
591
+ for (const directionCode of directionCodes) {
592
+ // Clear DOM frames for this direction code
593
+ const framesContainer = s(`.frames-${directionCode}`);
594
+ if (framesContainer) {
595
+ framesContainer.innerHTML = '';
596
+ }
597
+ // Clear data for this direction code
598
+ ObjectLayerEngineModal.ObjectLayerData[directionCode] = [];
599
+ }
581
600
 
582
- for (const directionCode of directionCodes) {
583
- // Use IIFE to properly capture directionCode and handle async operations
584
- await (async (currentDirectionCode) => {
585
- // Register frame add button handler after DOM is ready
586
- // Wait longer to ensure all direction bars are rendered
587
-
588
- if (loadedData && loadedData.metadata && loadedData.metadata.data && currentDirectionCode) {
589
- // Show loading animation only once on first direction that has frames
590
-
591
- const { type, id } = loadedData.metadata.data.item;
592
- const directions = ObjectLayerEngineModal.getDirectionsFromDirectionCode(currentDirectionCode);
593
-
594
- console.log(`Loading frames for direction code: ${currentDirectionCode}, directions:`, directions);
595
-
596
- // Check if frames exist for any direction mapped to this direction code
597
- const { frames } = loadedData.objectLayerRenderFramesId;
598
- for (const direction of directions) {
599
- if (frames[direction] && frames[direction].length > 0) {
600
- // Track this direction code as having original data
601
- if (!ObjectLayerEngineModal.originalDirectionCodes.includes(currentDirectionCode)) {
602
- ObjectLayerEngineModal.originalDirectionCodes.push(currentDirectionCode);
603
- }
604
- // Load frames from static PNG URLs sequentially to avoid race conditions
605
- const frameCount = frames[direction].length;
606
- console.log(`Found ${frameCount} frames for direction: ${direction} (code: ${currentDirectionCode})`);
607
- for (let frameIndex = 0; frameIndex < frameCount; frameIndex++) {
608
- const pngUrl = `${getProxyPath()}assets/${type}/${id}/${currentDirectionCode}/${frameIndex}.png`;
601
+ for (const directionCode of directionCodes) {
602
+ // Use IIFE to properly capture directionCode and handle async operations
603
+ await (async (currentDirectionCode) => {
604
+ // Register frame add button handler after DOM is ready
605
+ // Wait longer to ensure all direction bars are rendered
606
+
607
+ if (loadedData && loadedData.metadata && loadedData.metadata.data && currentDirectionCode) {
608
+ // Show loading animation only once on first direction that has frames
609
+
610
+ const { type, id } = loadedData.metadata.data.item;
611
+ const directions = ObjectLayerEngineModal.getDirectionsFromDirectionCode(currentDirectionCode);
612
+
613
+ console.log(`Loading frames for direction code: ${currentDirectionCode}, directions:`, directions);
614
+
615
+ // Check if frames exist for any direction mapped to this direction code
616
+ const { frames } = loadedData.objectLayerRenderFramesId;
617
+ for (const direction of directions) {
618
+ if (frames[direction] && frames[direction].length > 0) {
619
+ // Track this direction code as having original data
620
+ if (!ObjectLayerEngineModal.originalDirectionCodes.includes(currentDirectionCode)) {
621
+ ObjectLayerEngineModal.originalDirectionCodes.push(currentDirectionCode);
622
+ }
623
+ // Load frames from static PNG URLs sequentially to avoid race conditions
624
+ const frameCount = frames[direction].length;
609
625
  console.log(
610
- `Loading frame ${frameIndex} for direction code ${currentDirectionCode} from: ${pngUrl}`,
626
+ `Found ${frameCount} frames for direction: ${direction} (code: ${currentDirectionCode})`,
611
627
  );
612
- await processAndAddFrameFromPngUrl(currentDirectionCode, pngUrl);
628
+ for (let frameIndex = 0; frameIndex < frameCount; frameIndex++) {
629
+ const pngUrl = `${getProxyPath()}assets/${type}/${id}/${currentDirectionCode}/${frameIndex}.png`;
630
+ console.log(
631
+ `Loading frame ${frameIndex} for direction code ${currentDirectionCode} from: ${pngUrl}`,
632
+ );
633
+ await processAndAddFrameFromPngUrl(currentDirectionCode, pngUrl);
634
+ }
635
+ console.log(`Completed loading ${frameCount} frames for direction code: ${currentDirectionCode}`);
636
+ // Once we found frames for this direction code, we can break to avoid duplicates
637
+ break;
613
638
  }
614
- console.log(`Completed loading ${frameCount} frames for direction code: ${currentDirectionCode}`);
615
- // Once we found frames for this direction code, we can break to avoid duplicates
616
- break;
617
639
  }
618
640
  }
619
- }
620
641
 
621
- const buttonSelector = `.direction-code-bar-frames-btn-${currentDirectionCode}`;
622
- console.log(`Registering click handler for: ${buttonSelector}`);
642
+ const buttonSelector = `.direction-code-bar-frames-btn-${currentDirectionCode}`;
643
+ console.log(`Registering click handler for: ${buttonSelector}`);
623
644
 
624
- EventsUI.onClick(buttonSelector, async () => {
625
- console.log(`Add frame button clicked for direction: ${currentDirectionCode}`);
626
- const ole = s('object-layer-engine');
627
- if (!ole) {
628
- console.error('object-layer-engine not found');
629
- return;
630
- }
631
- const image = await ole.toBlob();
632
- const json = ole.exportMatrixJSON();
633
-
634
- // Check if we're in edit mode
635
- if (editingFrameId && editingDirectionCode) {
636
- // Ensure we're clicking the add button for the same direction being edited
637
- if (currentDirectionCode !== editingDirectionCode) {
638
- NotificationManager.Push({
639
- html: `<i class="fa-solid fa-exclamation-circle"></i> Please click the glowing <i class="fa-solid fa-edit"></i> button for direction <strong>${editingDirectionCode}</strong> to save changes, or click <i class="fa-solid fa-times"></i> to cancel.`,
640
- status: 'warning',
641
- });
642
- return; // Don't add a new frame
645
+ EventsUI.onClick(buttonSelector, async () => {
646
+ console.log(`Add frame button clicked for direction: ${currentDirectionCode}`);
647
+ const ole = s('object-layer-engine');
648
+ if (!ole) {
649
+ console.error('object-layer-engine not found');
650
+ return;
643
651
  }
652
+ const image = await ole.toBlob();
653
+ const json = ole.exportMatrixJSON();
654
+
655
+ // Check if we're in edit mode
656
+ if (editingFrameId && editingDirectionCode) {
657
+ // Ensure we're clicking the add button for the same direction being edited
658
+ if (currentDirectionCode !== editingDirectionCode) {
659
+ NotificationManager.Push({
660
+ html: `<i class="fa-solid fa-exclamation-circle"></i> Please click the glowing <i class="fa-solid fa-edit"></i> button for direction <strong>${editingDirectionCode}</strong> to save changes, or click <i class="fa-solid fa-times"></i> to cancel.`,
661
+ status: 'warning',
662
+ });
663
+ return; // Don't add a new frame
664
+ }
644
665
 
645
- // UPDATE existing frame
646
- console.log(`Updating frame ${editingFrameId} in direction ${editingDirectionCode}`);
647
-
648
- // Find the frame in the data array
649
- const frameArray = ObjectLayerEngineModal.ObjectLayerData[editingDirectionCode];
650
- const frameIndex = frameArray?.findIndex((frame) => frame.id === editingFrameId);
651
-
652
- if (frameIndex !== undefined && frameIndex >= 0) {
653
- // Update the frame data while preserving the ID and index
654
- frameArray[frameIndex] = {
655
- id: editingFrameId,
656
- image,
657
- json,
658
- };
659
-
660
- // Update the visual representation
661
- const imgElement = s(`.direction-code-bar-frames-img-${editingFrameId}`);
662
- if (imgElement) {
663
- imgElement.src = URL.createObjectURL(image);
666
+ // UPDATE existing frame
667
+ console.log(`Updating frame ${editingFrameId} in direction ${editingDirectionCode}`);
668
+
669
+ // Find the frame in the data array
670
+ const frameArray = ObjectLayerEngineModal.ObjectLayerData[editingDirectionCode];
671
+ const frameIndex = frameArray?.findIndex((frame) => frame.id === editingFrameId);
672
+
673
+ if (frameIndex !== undefined && frameIndex >= 0) {
674
+ // Update the frame data while preserving the ID and index
675
+ frameArray[frameIndex] = {
676
+ id: editingFrameId,
677
+ image,
678
+ json,
679
+ };
680
+
681
+ // Update the visual representation
682
+ const imgElement = s(`.direction-code-bar-frames-img-${editingFrameId}`);
683
+ if (imgElement) {
684
+ imgElement.src = URL.createObjectURL(image);
685
+ }
686
+
687
+ console.log(`Frame ${editingFrameId} updated successfully at index ${frameIndex}`);
688
+ NotificationManager.Push({
689
+ html: `<i class="fa-solid fa-check-circle"></i> Frame updated successfully at position ${frameIndex + 1}!`,
690
+ status: 'success',
691
+ });
692
+ } else {
693
+ console.error(`Could not find frame ${editingFrameId} in direction ${editingDirectionCode}`);
694
+ NotificationManager.Push({
695
+ html: `<i class="fa-solid fa-exclamation-triangle"></i> Error: Could not find frame to update`,
696
+ status: 'error',
697
+ });
664
698
  }
665
699
 
666
- console.log(`Frame ${editingFrameId} updated successfully at index ${frameIndex}`);
667
- NotificationManager.Push({
668
- html: `<i class="fa-solid fa-check-circle"></i> Frame updated successfully at position ${frameIndex + 1}!`,
669
- status: 'success',
670
- });
700
+ // Exit edit mode and restore UI
701
+ exitEditMode();
671
702
  } else {
672
- console.error(`Could not find frame ${editingFrameId} in direction ${editingDirectionCode}`);
673
- NotificationManager.Push({
674
- html: `<i class="fa-solid fa-exclamation-triangle"></i> Error: Could not find frame to update`,
675
- status: 'error',
676
- });
677
- }
703
+ // ADD new frame (existing behavior)
704
+ const id = `frame-capture-${s4()}-${s4()}`;
705
+ console.log(`Creating new frame ${id} for direction ${currentDirectionCode}`);
706
+
707
+ if (!ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode])
708
+ ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode] = [];
709
+ ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode].push({ id, image, json });
710
+ console.log(
711
+ `Stored frame ${id} in direction code ${currentDirectionCode}. Total frames:`,
712
+ ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode].length,
713
+ );
678
714
 
679
- // Exit edit mode and restore UI
680
- exitEditMode();
681
- } else {
682
- // ADD new frame (existing behavior)
683
- const id = `frame-capture-${s4()}-${s4()}`;
684
- console.log(`Creating new frame ${id} for direction ${currentDirectionCode}`);
685
-
686
- if (!ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode])
687
- ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode] = [];
688
- ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode].push({ id, image, json });
689
- console.log(
690
- `Stored frame ${id} in direction code ${currentDirectionCode}. Total frames:`,
691
- ObjectLayerEngineModal.ObjectLayerData[currentDirectionCode].length,
692
- );
693
-
694
- await addFrameToBar(currentDirectionCode, id, image, json);
695
- }
696
- });
697
- })(directionCode);
715
+ await addFrameToBar(currentDirectionCode, id, image, json);
716
+ }
717
+ });
718
+ })(directionCode);
719
+ }
720
+ hideFrameLoading();
721
+ } finally {
722
+ loadFramesInProgress = false;
698
723
  }
699
- hideFrameLoading();
700
724
  };
701
725
  RouterEvents[`router-${options.idModal}`] = loadFrames;
702
726
 
@@ -748,6 +772,7 @@ const ObjectLayerEngineModal = {
748
772
  data: {
749
773
  stats: {},
750
774
  item: {},
775
+ ledger: { type: 'OFF_CHAIN' },
751
776
  },
752
777
  };
753
778
  for (const directionCode of directionCodes) {
@@ -980,6 +1005,7 @@ const ObjectLayerEngineModal = {
980
1005
  font-weight: bold;
981
1006
  font-size: 1.2rem;
982
1007
  padding: 0.5rem;
1008
+ width: 70px;
983
1009
  }
984
1010
  .direction-code-bar-frames-img {
985
1011
  width: 100px;
@@ -225,6 +225,11 @@ const ObjectLayerEngineViewer = {
225
225
  const itemDescription = objectLayer.data.item.description || '';
226
226
  const itemActivable = objectLayer.data.item.activable || false;
227
227
 
228
+ // Get ledger data
229
+ const ledger = objectLayer.data.ledger || {};
230
+ const ledgerType = ledger.type || '';
231
+ const ledgerAddress = ledger.address || '';
232
+
228
233
  // Get stats data
229
234
  const stats = objectLayer.data.stats || {};
230
235
 
@@ -616,6 +621,33 @@ const ObjectLayerEngineViewer = {
616
621
  font-size: 13px;
617
622
  }
618
623
 
624
+ .webp-download-btn {
625
+ position: absolute;
626
+ top: 10px;
627
+ right: 10px;
628
+ background: rgba(0, 0, 0, 0.5);
629
+ color: white;
630
+ border: none;
631
+ border-radius: 6px;
632
+ padding: 6px 10px;
633
+ cursor: pointer;
634
+ font-size: 12px;
635
+ font-weight: 600;
636
+ display: flex;
637
+ align-items: center;
638
+ gap: 5px;
639
+ z-index: 5;
640
+ backdrop-filter: blur(4px);
641
+ transition: all 0.2s ease;
642
+ }
643
+ .webp-download-btn:hover {
644
+ background: rgba(0, 0, 0, 0.75);
645
+ transform: scale(1.05);
646
+ }
647
+ .webp-download-btn i {
648
+ font-size: 12px;
649
+ }
650
+
619
651
  @media (max-width: 850px) {
620
652
  .object-layer-viewer-container {
621
653
  padding: 5px;
@@ -672,11 +704,18 @@ const ObjectLayerEngineViewer = {
672
704
  <span class="ipfs-cid-value">${objectLayer.cid}</span>
673
705
  </div>`
674
706
  : ''}
675
- ${objectLayer.data.atlasSpriteSheetCid
707
+ ${objectLayer.data.render?.cid
676
708
  ? html`<div class="ipfs-cid-label">
677
709
  <i class="fa-solid fa-image"></i>
678
710
  <strong>Atlas IPFS CID:</strong>
679
- <span class="ipfs-cid-value">${objectLayer.data.atlasSpriteSheetCid}</span>
711
+ <span class="ipfs-cid-value">${objectLayer.data.render.cid}</span>
712
+ </div>`
713
+ : ''}
714
+ ${objectLayer.data.render?.metadataCid
715
+ ? html`<div class="ipfs-cid-label">
716
+ <i class="fa-solid fa-file-code"></i>
717
+ <strong>Atlas Metadata CID:</strong>
718
+ <span class="ipfs-cid-value">${objectLayer.data.render.metadataCid}</span>
680
719
  </div>`
681
720
  : ''}
682
721
  ${objectLayer.sha256
@@ -725,7 +764,30 @@ const ObjectLayerEngineViewer = {
725
764
  </div>
726
765
  </div>
727
766
 
767
+ <!-- Ledger Section -->
768
+ <div class="control-group" style="margin-bottom: 20px;">
769
+ <h4><i class="fa-solid fa-link"></i> Ledger</h4>
770
+ <div
771
+ style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; padding: 10px 0;"
772
+ >
773
+ <div style="display: flex; flex-direction: column; gap: 4px;">
774
+ <span class="item-data-key-label">Type</span>
775
+ <span style="font-weight: 600;">${ledgerType || 'N/A'}</span>
776
+ </div>
777
+ ${ledgerAddress
778
+ ? html`<div style="display: flex; flex-direction: column; gap: 4px;">
779
+ <span class="item-data-key-label">Contract Address</span>
780
+ <span style="font-weight: 600; word-break: break-all;">${ledgerAddress}</span>
781
+ </div>`
782
+ : ''}
783
+ </div>
784
+ </div>
785
+
728
786
  <div class="webp-display-area">
787
+ <button class="webp-download-btn" id="download-webp-btn">
788
+ <i class="fa-solid fa-download"></i>
789
+ <span>WebP</span>
790
+ </button>
729
791
  <div class="webp-canvas-container chess in" id="webp-canvas-container">
730
792
  ${!this.Data.webp
731
793
  ? html`
@@ -917,10 +979,6 @@ const ObjectLayerEngineViewer = {
917
979
  <i class="fa-solid fa-arrow-left"></i>
918
980
  <span>Return to List</span>
919
981
  </button>
920
- <button class="default-viewer-btn" id="download-webp-btn">
921
- <i class="fa-solid fa-download"></i>
922
- <span>Download WebP</span>
923
- </button>
924
982
  <button class="default-viewer-btn edit-btn" id="edit-object-layer-btn">
925
983
  <i class="fa-solid fa-edit"></i>
926
984
  <span>Edit</span>
@@ -31,6 +31,7 @@ const CyberiaDependencies = {
31
31
  pngjs: '^7.0.0',
32
32
  jimp: '^1.6.0',
33
33
  sharp: '^0.32.5',
34
+ ethers: '~6.16.0',
34
35
  };
35
36
 
36
37
  export { BaseElement, ModelElement, CyberiaPortalParams, CyberiaDependencies };
@@ -63,20 +63,62 @@ const CssCommonCyberia = async () => {
63
63
  text-align: center;
64
64
  }
65
65
 
66
- .landing-title,
67
66
  h1,
68
67
  h2,
69
68
  h3 {
70
69
  font-family: var(--cy-font-retro-cta);
70
+ }
71
+
72
+ p {
73
+ font-family: var(--cy-font-retro);
74
+ }
75
+
76
+ .landing-title,
77
+ .html-main-body h1,
78
+ .html-main-body h2,
79
+ .html-main-body h3 {
71
80
  font-size: 5rem;
72
81
  color: #ffcc00;
73
82
  text-shadow: 2px 2px 0px #9e7b00;
74
83
  margin-bottom: 2rem;
75
84
  }
76
85
 
77
- p {
86
+ /* Docs section retro styling */
87
+ .docs-header h1 {
88
+ font-family: var(--cy-font-retro-cta);
89
+ color: #ffcc00;
90
+ text-shadow: 2px 2px 0px #9e7b00;
91
+ }
92
+ .docs-card {
93
+ border: 2px solid #ffcc00;
94
+ transition: all 0.3s ease-in-out;
95
+ }
96
+ .docs-card:hover {
97
+ background: rgba(255, 204, 0, 0.08);
98
+ box-shadow:
99
+ 0 0 10px rgba(255, 204, 0, 0.3),
100
+ 0 0 20px rgba(255, 204, 0, 0.15);
101
+ transform: translateY(-3px);
102
+ }
103
+ .card-icon {
104
+ color: #ffcc00;
105
+ }
106
+ .card-content h3 {
107
+ font-family: var(--cy-font-retro-cta);
108
+ font-size: 1.25rem;
109
+ }
110
+ .card-content p {
111
+ font-family: var(--cy-font-retro);
112
+ }
113
+ .submenu-btn {
78
114
  font-family: var(--cy-font-retro);
79
115
  }
116
+ .submenu-btn:hover {
117
+ background: rgba(255, 204, 0, 0.1);
118
+ }
119
+ .down-arrow-submenu {
120
+ left: 102px;
121
+ }
80
122
 
81
123
  .object-layer-viewer-container {
82
124
  width: 100% !important;
@@ -10,7 +10,6 @@ const LogInCyberiaPortal = async function () {
10
10
 
11
11
  ElementsCyberiaPortal.Data.user.main.model.user = user;
12
12
 
13
- // if (user.role === 'admin' || user.role === 'moderator') s(`.main-btn-admin`).classList.remove('hide');
14
13
  await ObjectLayerManagement.Reload('viewer');
15
14
  };
16
15
  const { user } = await Auth.sessionIn();
@@ -2,14 +2,22 @@ import { Account } from '../core/Account.js';
2
2
  import { BtnIcon } from '../core/BtnIcon.js';
3
3
  import { getId, newInstance, random } from '../core/CommonJs.js';
4
4
  import { Css, ThemeEvents, Themes, darkTheme } from '../core/Css.js';
5
+ import { Docs } from '../core/Docs.js';
5
6
  import { EventsUI } from '../core/EventsUI.js';
6
7
  import { LogIn } from '../core/LogIn.js';
7
8
  import { LogOut } from '../core/LogOut.js';
8
- import { buildBadgeToolTipMenuOption, Modal, renderMenuLabel, renderViewTitle } from '../core/Modal.js';
9
+ import {
10
+ buildBadgeToolTipMenuOption,
11
+ isSubMenuOpen,
12
+ Modal,
13
+ renderMenuLabel,
14
+ renderViewTitle,
15
+ subMenuRender,
16
+ } from '../core/Modal.js';
9
17
  import { SignUp } from '../core/SignUp.js';
10
18
  import { Translate } from '../core/Translate.js';
11
19
  import { htmls, s } from '../core/VanillaJs.js';
12
- import { getProxyPath } from '../core/Router.js';
20
+ import { getProxyPath, setQueryParams } from '../core/Router.js';
13
21
  import { ElementsCyberiaPortal } from './ElementsCyberiaPortal.js';
14
22
  import Sortable from 'sortablejs';
15
23
  import { RouterCyberiaPortal, BannerAppTemplate } from './RoutesCyberiaPortal.js';
@@ -135,6 +143,27 @@ const MenuCyberiaPortal = {
135
143
  handleContainerClass: 'handle-btn-container',
136
144
  tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('chat')),
137
145
  })}
146
+ ${await BtnIcon.Render({
147
+ class: 'in wfa main-btn-menu main-btn-docs',
148
+ useMenuBtn: true,
149
+ label: html`<div class="in">
150
+ ${renderMenuLabel({
151
+ icon: html`<img class="inl cyberia-menu-icon" src="${getProxyPath()}assets/ui-icons/wiki.png" />`,
152
+ text: html`<span class="menu-label-text"
153
+ >${Translate.Render('docs')}
154
+ <i
155
+ class="fas fa-caret-down inl down-arrow-submenu down-arrow-submenu-docs"
156
+ style="rotate: 0deg; transition: 0.4s;"
157
+ ></i
158
+ ></span>`,
159
+ })}
160
+ </div> `,
161
+ attrs: `data-id="docs"`,
162
+ tabHref: `${getProxyPath()}docs`,
163
+ handleContainerClass: 'handle-btn-container',
164
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('docs')),
165
+ })}
166
+ <div class="abs menu-btn-container-children-docs"></div>
138
167
  ${await BtnIcon.Render({
139
168
  class: 'in wfa main-btn-menu main-btn-admin hide',
140
169
  useMenuBtn: true,
@@ -432,6 +461,39 @@ const MenuCyberiaPortal = {
432
461
  });
433
462
  });
434
463
 
464
+ EventsUI.onClick(`.main-btn-docs`, async (e) => {
465
+ if (!isSubMenuOpen('docs') || e.isTrusted) {
466
+ if (e.isTrusted) setQueryParams({ cid: '' });
467
+ await subMenuRender('docs');
468
+ }
469
+
470
+ const { barConfig } = await Themes[Css.currentTheme]();
471
+ await Modal.Render({
472
+ id: 'modal-docs',
473
+ route: 'docs',
474
+ barConfig,
475
+ title: renderViewTitle({
476
+ icon: html`<img class="inl cyberia-menu-icon-modal" src="${getProxyPath()}assets/ui-icons/wiki.png" />`,
477
+ text: `<span class='inl cyberia-text-title-modal'>${Translate.Render('docs')}</span>`,
478
+ }),
479
+ html: async () =>
480
+ await Docs.Init({
481
+ idModal: 'modal-docs',
482
+ subMenuIcon: (type) =>
483
+ html`<img class="inl cyberia-menu-icon" src="${getProxyPath()}assets/ui-icons/arrow-right.png" />`,
484
+ coverageUrl: () => `${getProxyPath()}docs/hardhat-coverage`,
485
+ demoUrl: () => `https://client.cyberiaonline.com/`,
486
+ lastReleaseUrl: () => `https://github.com/underpostnet/engine-cyberia.git`,
487
+ }),
488
+ handleType: 'bar',
489
+ observer: true,
490
+ maximize: true,
491
+ mode: 'view',
492
+ slideMenu: 'modal-menu',
493
+ RouterInstance,
494
+ });
495
+ });
496
+
435
497
  EventsUI.onClick(`.main-btn-server`, async () => {
436
498
  const { barConfig } = await Themes[Css.currentTheme]();
437
499
  await Modal.Render({
@@ -45,6 +45,7 @@ const RoutesCyberiaPortal = () => {
45
45
  title: 'cyberia-map-engine',
46
46
  render: () => s(`.main-btn-cyberia-map-engine`).click(),
47
47
  },
48
+ '/docs': { title: 'docs', render: () => s(`.main-btn-docs`).click() },
48
49
  };
49
50
  };
50
51