@dcl-regenesislabs/bevy-explorer-web 0.1.0-18229784557.commit-ef374b9

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 (277) hide show
  1. package/asset_loader.js +31 -0
  2. package/assets/animations/Dance_Female.glb +0 -0
  3. package/assets/animations/Dance_Male.glb +0 -0
  4. package/assets/animations/F_FistPump.glb +0 -0
  5. package/assets/animations/F_RobotDance.glb +0 -0
  6. package/assets/animations/Hands_Air.glb +0 -0
  7. package/assets/animations/M_FistPump.glb +0 -0
  8. package/assets/animations/M_RobotDance.glb +0 -0
  9. package/assets/animations/Raise_Hand.glb +0 -0
  10. package/assets/animations/Throw Money-Emote.glb +0 -0
  11. package/assets/animations/Wave_Female.glb +0 -0
  12. package/assets/animations/Wave_Male.glb +0 -0
  13. package/assets/animations/clap.glb +0 -0
  14. package/assets/animations/disco_dance.glb +0 -0
  15. package/assets/animations/dont_wanna_see.glb +0 -0
  16. package/assets/animations/f_head_explode.glb +0 -0
  17. package/assets/animations/idle.glb +0 -0
  18. package/assets/animations/jump2.glb +0 -0
  19. package/assets/animations/kiss.glb +0 -0
  20. package/assets/animations/m_head_explode.glb +0 -0
  21. package/assets/animations/mchammer-dance.glb +0 -0
  22. package/assets/animations/run.glb +0 -0
  23. package/assets/animations/shrug.glb +0 -0
  24. package/assets/animations/tektonik-dance.glb +0 -0
  25. package/assets/animations/thumbnails/clap.png +0 -0
  26. package/assets/animations/thumbnails/dance.png +0 -0
  27. package/assets/animations/thumbnails/disco.png +0 -0
  28. package/assets/animations/thumbnails/dontsee.png +0 -0
  29. package/assets/animations/thumbnails/fistpump.png +0 -0
  30. package/assets/animations/thumbnails/hammer.png +0 -0
  31. package/assets/animations/thumbnails/handsair.png +0 -0
  32. package/assets/animations/thumbnails/headexplode.png +0 -0
  33. package/assets/animations/thumbnails/kiss.png +0 -0
  34. package/assets/animations/thumbnails/money.png +0 -0
  35. package/assets/animations/thumbnails/raisehand.png +0 -0
  36. package/assets/animations/thumbnails/robot.png +0 -0
  37. package/assets/animations/thumbnails/shrug.png +0 -0
  38. package/assets/animations/thumbnails/tektonik.png +0 -0
  39. package/assets/animations/thumbnails/tik.png +0 -0
  40. package/assets/animations/thumbnails/wave.png +0 -0
  41. package/assets/animations/tik-tok-dance.glb +0 -0
  42. package/assets/animations/walk.glb +0 -0
  43. package/assets/fonts/NotoSans-Bold.ttf +0 -0
  44. package/assets/fonts/NotoSans-BoldItalic.ttf +0 -0
  45. package/assets/fonts/NotoSans-Italic.ttf +0 -0
  46. package/assets/fonts/NotoSans-Regular.ttf +0 -0
  47. package/assets/fonts/NotoSansMono-Bold.ttf +0 -0
  48. package/assets/fonts/NotoSansMono-Regular.ttf +0 -0
  49. package/assets/fonts/NotoSerif-Bold.ttf +0 -0
  50. package/assets/fonts/NotoSerif-BoldItalic.ttf +0 -0
  51. package/assets/fonts/NotoSerif-Italic.ttf +0 -0
  52. package/assets/fonts/NotoSerif-Regular.ttf +0 -0
  53. package/assets/fonts/OFL.txt +93 -0
  54. package/assets/images/FriendsIcon.png +0 -0
  55. package/assets/images/ask.png +0 -0
  56. package/assets/images/backpack/Background.jpeg +0 -0
  57. package/assets/images/backpack/empty.png +0 -0
  58. package/assets/images/backpack/item_bg.png +0 -0
  59. package/assets/images/backpack/wearable_categories/body_shape.png +0 -0
  60. package/assets/images/backpack/wearable_categories/earring.png +0 -0
  61. package/assets/images/backpack/wearable_categories/eyebrows.png +0 -0
  62. package/assets/images/backpack/wearable_categories/eyes.png +0 -0
  63. package/assets/images/backpack/wearable_categories/eyewear.png +0 -0
  64. package/assets/images/backpack/wearable_categories/facial_hair.png +0 -0
  65. package/assets/images/backpack/wearable_categories/feet.png +0 -0
  66. package/assets/images/backpack/wearable_categories/hair.png +0 -0
  67. package/assets/images/backpack/wearable_categories/hands_wear.png +0 -0
  68. package/assets/images/backpack/wearable_categories/hat.png +0 -0
  69. package/assets/images/backpack/wearable_categories/helmet.png +0 -0
  70. package/assets/images/backpack/wearable_categories/lower_body.png +0 -0
  71. package/assets/images/backpack/wearable_categories/mask.png +0 -0
  72. package/assets/images/backpack/wearable_categories/mouth.png +0 -0
  73. package/assets/images/backpack/wearable_categories/skin.png +0 -0
  74. package/assets/images/backpack/wearable_categories/tiara.png +0 -0
  75. package/assets/images/backpack/wearable_categories/top_head.png +0 -0
  76. package/assets/images/backpack/wearable_categories/upper_body.png +0 -0
  77. package/assets/images/button copy.png +0 -0
  78. package/assets/images/button.png +0 -0
  79. package/assets/images/button_base.png +0 -0
  80. package/assets/images/chat_button.png +0 -0
  81. package/assets/images/copy.png +0 -0
  82. package/assets/images/crosshair.png +0 -0
  83. package/assets/images/cursor.png +0 -0
  84. package/assets/images/dao_small.png +0 -0
  85. package/assets/images/dcl-godot-bevy.png +0 -0
  86. package/assets/images/discover/art.png +0 -0
  87. package/assets/images/discover/business.png +0 -0
  88. package/assets/images/discover/casino.png +0 -0
  89. package/assets/images/discover/crypto.png +0 -0
  90. package/assets/images/discover/education.png +0 -0
  91. package/assets/images/discover/eye.png +0 -0
  92. package/assets/images/discover/fashion.png +0 -0
  93. package/assets/images/discover/featured.png +0 -0
  94. package/assets/images/discover/game.png +0 -0
  95. package/assets/images/discover/icons.png +0 -0
  96. package/assets/images/discover/music.png +0 -0
  97. package/assets/images/discover/point of interest.png +0 -0
  98. package/assets/images/discover/shop.png +0 -0
  99. package/assets/images/discover/social.png +0 -0
  100. package/assets/images/discover/sports.png +0 -0
  101. package/assets/images/discover/thumbsup.png +0 -0
  102. package/assets/images/emote-button-background.png +0 -0
  103. package/assets/images/emote_button.png +0 -0
  104. package/assets/images/genesis_tx.png +0 -0
  105. package/assets/images/grid.png +0 -0
  106. package/assets/images/grip.png +0 -0
  107. package/assets/images/left-arrow.png +0 -0
  108. package/assets/images/line.png +0 -0
  109. package/assets/images/mic_button_inactive.png +0 -0
  110. package/assets/images/mic_button_off.png +0 -0
  111. package/assets/images/mic_button_on.png +0 -0
  112. package/assets/images/next.png +0 -0
  113. package/assets/images/person.png +0 -0
  114. package/assets/images/person_button.png +0 -0
  115. package/assets/images/profile_button.png +0 -0
  116. package/assets/images/redx.png +0 -0
  117. package/assets/images/right-arrow.png +0 -0
  118. package/assets/images/screenshots/montage.png +0 -0
  119. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_avatar_attach_1.png.png +0 -0
  120. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_avatar_attach_2.png.png +0 -0
  121. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_avatar_attach_3.png.png +0 -0
  122. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_avatar_attach_4.png.png +0 -0
  123. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_gltfcontainer_avocado.png.png +0 -0
  124. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_gltfcontainer_hev.png.png +0 -0
  125. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_01.png.png +0 -0
  126. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_02.png.png +0 -0
  127. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_03.png.png +0 -0
  128. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_04.png.png +0 -0
  129. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_05.png.png +0 -0
  130. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_06.png.png +0 -0
  131. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_07.png.png +0 -0
  132. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_08.png.png +0 -0
  133. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_09.png.png +0 -0
  134. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_10.png.png +0 -0
  135. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_11.png.png +0 -0
  136. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_12.png.png +0 -0
  137. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_13.png.png +0 -0
  138. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_material_14.png.png +0 -0
  139. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_mesh_renderer_box.png.png +0 -0
  140. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_mesh_renderer_cylinder.png.png +0 -0
  141. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_mesh_renderer_plane.png.png +0 -0
  142. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_mesh_renderer_sphere.png.png +0 -0
  143. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_text_shape_1.png.png +0 -0
  144. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_text_shape_2.png.png +0 -0
  145. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_text_shape_3.png.png +0 -0
  146. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_text_shape_4.png.png +0 -0
  147. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_text_shape_5.png.png +0 -0
  148. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_text_shape_6.png.png +0 -0
  149. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_ui_background_all_screen_green.png.png +0 -0
  150. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_ui_background_all_screen_red.png.png +0 -0
  151. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_ui_background_all_screen_rocks.png.png +0 -0
  152. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_ui_text_1.png.png +0 -0
  153. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_ui_text_2.png.png +0 -0
  154. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_video_player_1.png.png +0 -0
  155. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_video_player_2.png.png +0 -0
  156. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_video_player_3.png.png +0 -0
  157. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_video_player_4.png.png +0 -0
  158. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_visibility_false.png.png +0 -0
  159. package/assets/images/screenshots/screenshot%2Fbevy_snapshot_visibility_true.png.png +0 -0
  160. package/assets/images/skybox/skybox_cubemap.png +0 -0
  161. package/assets/images/skybox/skybox_cubemap_original.png +0 -0
  162. package/assets/images/spinner.png +0 -0
  163. package/assets/images/spinner_atlas.png +0 -0
  164. package/assets/images/tick.png +0 -0
  165. package/assets/images/toggle-off.png +0 -0
  166. package/assets/images/toggle-on.png +0 -0
  167. package/assets/images/unknown_person.png +0 -0
  168. package/assets/images/you_are_here.png +0 -0
  169. package/assets/nft_shapes/Baroque_Ornament.glb +0 -0
  170. package/assets/nft_shapes/Blocky.glb +0 -0
  171. package/assets/nft_shapes/Canvas.glb +0 -0
  172. package/assets/nft_shapes/Classic.glb +0 -0
  173. package/assets/nft_shapes/Diamond_Ornament.glb +0 -0
  174. package/assets/nft_shapes/Floor_Wood01.png +0 -0
  175. package/assets/nft_shapes/Genesis_TX.png +0 -0
  176. package/assets/nft_shapes/Gold_Carved.glb +0 -0
  177. package/assets/nft_shapes/Gold_Edges.glb +0 -0
  178. package/assets/nft_shapes/Gold_Rounded.glb +0 -0
  179. package/assets/nft_shapes/Gold_Wide.glb +0 -0
  180. package/assets/nft_shapes/Metal_Medium.glb +0 -0
  181. package/assets/nft_shapes/Metal_Rounded.glb +0 -0
  182. package/assets/nft_shapes/Metal_Slim.glb +0 -0
  183. package/assets/nft_shapes/Metal_Wide.glb +0 -0
  184. package/assets/nft_shapes/Minimal_Black.glb +0 -0
  185. package/assets/nft_shapes/Minimal_Grey.glb +0 -0
  186. package/assets/nft_shapes/Minimal_White.glb +0 -0
  187. package/assets/nft_shapes/Minimal_Wide.glb +0 -0
  188. package/assets/nft_shapes/MulticolorDotsLoading.png +0 -0
  189. package/assets/nft_shapes/NFTIcon.png +0 -0
  190. package/assets/nft_shapes/NoneIcon.png +0 -0
  191. package/assets/nft_shapes/Pins.glb +0 -0
  192. package/assets/nft_shapes/Tape.glb +0 -0
  193. package/assets/nft_shapes/Wood_Slim.glb +0 -0
  194. package/assets/nft_shapes/Wood_Twigs.glb +0 -0
  195. package/assets/nft_shapes/Wood_Wide.glb +0 -0
  196. package/assets/shaders/bound_material.wgsl +183 -0
  197. package/assets/shaders/bound_material_baker.wgsl +145 -0
  198. package/assets/shaders/bound_node.wgsl +57 -0
  199. package/assets/shaders/bound_prepass.wgsl +160 -0
  200. package/assets/shaders/floor_bake.wgsl +30 -0
  201. package/assets/shaders/floor_fragment.wgsl +74 -0
  202. package/assets/shaders/floor_vertex.wgsl +47 -0
  203. package/assets/shaders/loading.wgsl +35 -0
  204. package/assets/shaders/mask_material.wgsl +117 -0
  205. package/assets/shaders/nineslice_material.wgsl +47 -0
  206. package/assets/shaders/nishita_cloud.wgsl +378 -0
  207. package/assets/shaders/outline.wgsl +69 -0
  208. package/assets/shaders/simplex.wgsl +77 -0
  209. package/assets/shaders/stretch_uv_material.wgsl +79 -0
  210. package/assets/shaders/text_quad_vertex.wgsl +78 -0
  211. package/assets/sounds/avatar/avatar_footstep_jump01.wav +0 -0
  212. package/assets/sounds/avatar/avatar_footstep_jump02.wav +0 -0
  213. package/assets/sounds/avatar/avatar_footstep_jump03.wav +0 -0
  214. package/assets/sounds/avatar/avatar_footstep_land01.wav +0 -0
  215. package/assets/sounds/avatar/avatar_footstep_land02.wav +0 -0
  216. package/assets/sounds/avatar/avatar_footstep_run01.wav +0 -0
  217. package/assets/sounds/avatar/avatar_footstep_run02.wav +0 -0
  218. package/assets/sounds/avatar/avatar_footstep_run03.wav +0 -0
  219. package/assets/sounds/avatar/avatar_footstep_run04.wav +0 -0
  220. package/assets/sounds/avatar/avatar_footstep_run05.wav +0 -0
  221. package/assets/sounds/avatar/avatar_footstep_run06.wav +0 -0
  222. package/assets/sounds/avatar/avatar_footstep_run07.wav +0 -0
  223. package/assets/sounds/avatar/avatar_footstep_run08.wav +0 -0
  224. package/assets/sounds/avatar/avatar_footstep_walk01.wav +0 -0
  225. package/assets/sounds/avatar/avatar_footstep_walk02.wav +0 -0
  226. package/assets/sounds/avatar/avatar_footstep_walk03.wav +0 -0
  227. package/assets/sounds/avatar/avatar_footstep_walk04.wav +0 -0
  228. package/assets/sounds/avatar/avatar_footstep_walk05.wav +0 -0
  229. package/assets/sounds/avatar/avatar_footstep_walk06.wav +0 -0
  230. package/assets/sounds/avatar/avatar_footstep_walk07.wav +0 -0
  231. package/assets/sounds/avatar/avatar_footstep_walk08.wav +0 -0
  232. package/assets/sounds/ui/generic_button_hover.wav +0 -0
  233. package/assets/sounds/ui/generic_button_press.wav +0 -0
  234. package/assets/sounds/ui/mainmenu_widget_open.wav +0 -0
  235. package/assets/sounds/ui/toggle_disable.wav +0 -0
  236. package/assets/sounds/ui/toggle_enable.wav +0 -0
  237. package/assets/sounds/ui/voice_chat_mic_off.wav +0 -0
  238. package/assets/sounds/ui/voice_chat_mic_on.wav +0 -0
  239. package/assets/sounds/ui/widget_chat_message_private_send.wav +0 -0
  240. package/assets/sounds/ui/widget_emotes_close.wav +0 -0
  241. package/assets/sounds/ui/widget_emotes_highlight.wav +0 -0
  242. package/assets/sounds/ui/widget_emotes_open.wav +0 -0
  243. package/assets/ui/app_settings.dui +91 -0
  244. package/assets/ui/avatar.dui +18 -0
  245. package/assets/ui/button.dui +78 -0
  246. package/assets/ui/change-realm.dui +46 -0
  247. package/assets/ui/chat.dui +182 -0
  248. package/assets/ui/combo.dui +23 -0
  249. package/assets/ui/dialog.dui +46 -0
  250. package/assets/ui/discover.dui +139 -0
  251. package/assets/ui/emote-select.dui +45 -0
  252. package/assets/ui/emote.dui +116 -0
  253. package/assets/ui/foreign-profile-dialog.dui +18 -0
  254. package/assets/ui/fullscreen-block.dui +12 -0
  255. package/assets/ui/login.dui +72 -0
  256. package/assets/ui/map.dui +8 -0
  257. package/assets/ui/minimap.dui +16 -0
  258. package/assets/ui/motd.dui +25 -0
  259. package/assets/ui/nft-dialog.dui +29 -0
  260. package/assets/ui/oow.dui +41 -0
  261. package/assets/ui/permissions-dialog.dui +39 -0
  262. package/assets/ui/permissions.dui +54 -0
  263. package/assets/ui/profile-detail.dui +24 -0
  264. package/assets/ui/profile.dui +29 -0
  265. package/assets/ui/spinner.dui +3 -0
  266. package/assets/ui/toast.dui +27 -0
  267. package/assets/ui/tracker.dui +21 -0
  268. package/assets/ui/update.dui +16 -0
  269. package/assets/ui/utils.dui +40 -0
  270. package/assets/ui/wearables.dui +134 -0
  271. package/gpu_cache.js +302 -0
  272. package/index.html +134 -0
  273. package/main.js +284 -0
  274. package/package.json +9 -0
  275. package/sandbox_worker.js +394 -0
  276. package/serve.json +21 -0
  277. package/service_worker.js +93 -0
package/main.js ADDED
@@ -0,0 +1,284 @@
1
+ // Import the wasm-bindgen generated JS glue code and Rust functions
2
+ import { initGpuCache } from "./gpu_cache.js";
3
+ import init, { engine_init, engine_run } from "./pkg/webgpu_build.js"; // Ensure this path is correct
4
+
5
+ const initialRealmInput = document.getElementById("initialRealm");
6
+ const locationInput = document.getElementById("location");
7
+ const systemSceneInput = document.getElementById("systemScene");
8
+ const initButton = document.getElementById("initButton");
9
+ const canvas = document.getElementById("canvas-parent");
10
+ const header = document.getElementById("header");
11
+
12
+ let initialRealmGroup = document.getElementById("initialRealm")?.parentElement;
13
+ let locationGroup = document.getElementById("location")?.parentElement;
14
+ let systemSceneGroup = document.getElementById("systemScene")?.parentElement;
15
+
16
+ var autoStart = true;
17
+
18
+ function populateInputsFromQueryParams() {
19
+ const queryParams = new URLSearchParams(window.location.search);
20
+
21
+ const manualParams = queryParams.get("manualParams");
22
+ if (manualParams) {
23
+ autoStart = false;
24
+ }
25
+
26
+ const initialRealmParam = queryParams.get("initialRealm");
27
+ if (initialRealmInput && initialRealmParam) {
28
+ initialRealmInput.value = decodeURIComponent(initialRealmParam);
29
+ } else if (initialRealmInput) {
30
+ initialRealmInput.value = "https://realm-provider-ea.decentraland.org/main";
31
+ }
32
+ const locationParam = queryParams.get("location");
33
+ if (locationInput && locationParam) {
34
+ locationInput.value = decodeURIComponent(locationParam);
35
+ } else if (locationInput) {
36
+ locationInput.value = "";
37
+ }
38
+ const systemSceneParam = queryParams.get("systemScene");
39
+ if (systemSceneInput && systemSceneParam) {
40
+ systemSceneInput.value = decodeURIComponent(systemSceneParam);
41
+ } else if (systemSceneInput) {
42
+ systemSceneInput.value = "https://dclexplorer.github.io/bevy-ui-scene/BevyUiScene";
43
+ }
44
+
45
+ initialRealmInput.disabled = autoStart;
46
+ locationInput.disabled = autoStart;
47
+ systemSceneInput.disabled = autoStart;
48
+ }
49
+ function hideHeader() {
50
+ if (header) header.style.display = "none";
51
+ if (canvas) canvas.style.display = "block";
52
+ }
53
+
54
+ if ("serviceWorker" in navigator) {
55
+ window.addEventListener("load", () => {
56
+ navigator.serviceWorker
57
+ .register("service_worker.js")
58
+ .then((registration) => {
59
+ console.log(
60
+ "Page: Service Worker registered successfully with scope: ",
61
+ registration.scope
62
+ );
63
+ })
64
+ .catch((error) => {
65
+ console.log("Page: Service Worker registration failed: ", error);
66
+ });
67
+ });
68
+
69
+ // make sure the worker stays around after a hard reload
70
+ // 1. Check if a service worker is active and controlling the page.
71
+ if (navigator.serviceWorker && navigator.serviceWorker.controller) {
72
+ // SUCCESS CASE:
73
+ // If the recovery flag is present, it means we just successfully
74
+ // recovered from a hard reload. We can now remove the flag.
75
+ if (sessionStorage.getItem('sw_reloaded')) {
76
+ console.log('Service Worker recovery successful. Cleaning up flag.');
77
+ sessionStorage.removeItem('sw_reloaded');
78
+ }
79
+ // Everything is fine, let the app load.
80
+ } else {
81
+ // 2. RECOVERY CASE: No service worker is in control.
82
+ // This could be a first visit or a hard reload.
83
+ if (navigator.serviceWorker && navigator.serviceWorker.getRegistration) {
84
+ navigator.serviceWorker.getRegistration().then(registration => {
85
+ // We only try to recover if a service worker is already registered.
86
+ if (registration) {
87
+ // Prevent an infinite reload loop.
88
+ if (sessionStorage.getItem('sw_reloaded')) {
89
+ sessionStorage.removeItem('sw_reloaded');
90
+ console.error('Service Worker failed to take control after reload.');
91
+ } else {
92
+ // Set the flag and perform a standard reload.
93
+ console.log('Page is uncontrolled. Reloading to activate Service Worker...');
94
+ sessionStorage.setItem('sw_reloaded', 'true');
95
+ window.location.reload();
96
+ }
97
+ }
98
+ });
99
+ }
100
+ }
101
+ }
102
+
103
+ async function initEngine() {
104
+ populateInputsFromQueryParams();
105
+
106
+ if (initButton) {
107
+ initButton.disabled = true;
108
+ if (autoStart) {
109
+ initButton.textContent = "Autostarting .."
110
+ } else {
111
+ initButton.textContent = "Loading ..."
112
+ }
113
+ }
114
+
115
+ const wasmUrl = "./pkg/webgpu_build_bg.wasm";
116
+
117
+ try {
118
+ const compiledModule = await WebAssembly.compileStreaming(fetch(wasmUrl));
119
+
120
+ const initialMemoryPages = 640; // setting initial memory high causes malloc failures
121
+ const maximumMemoryPages = 65536;
122
+ const sharedMemory = new WebAssembly.Memory({
123
+ initial: initialMemoryPages,
124
+ maximum: maximumMemoryPages,
125
+ shared: true,
126
+ });
127
+ window.wasm_memory = sharedMemory;
128
+
129
+ window.setVideoSource = (video, src) => {
130
+ async function isHlsStream(url) {
131
+ try {
132
+ const response = await fetch(url, {
133
+ method: "HEAD",
134
+ mode: "cors",
135
+ });
136
+
137
+ if (!response.ok) {
138
+ return false;
139
+ }
140
+
141
+ const contentType = response.headers.get("Content-Type");
142
+
143
+ if (contentType) {
144
+ return (
145
+ contentType.includes("application/vnd.apple.mpegurl") ||
146
+ contentType.includes("application/x-mpegURL")
147
+ );
148
+ }
149
+
150
+ return false;
151
+ } catch (error) {
152
+ return false;
153
+ }
154
+ }
155
+
156
+ if (video.canPlayType("application/vnd.apple.mpegurl")) {
157
+ video.src = src;
158
+ } else if (Hls.isSupported()) {
159
+ // check if we need hls
160
+ setTimeout(async () => {
161
+ if (await isHlsStream(src)) {
162
+ var hls = new Hls();
163
+ hls.loadSource(src);
164
+ hls.attachMedia(video);
165
+ } else {
166
+ video.src = src;
167
+ }
168
+ }, 0);
169
+ }
170
+ };
171
+
172
+ window.spawn_and_init_sandbox = async () => {
173
+ var timeoutId;
174
+ return new Promise((resolve, _reject) => {
175
+ // var sandboxWorker = new Worker(sandboxJs, { type: "module" });
176
+ var sandboxWorker = new Worker("sandbox_worker.js", { type: "module" });
177
+
178
+ var timeoutCount = 0;
179
+ let logTimeout = () => {
180
+ console.log(
181
+ "[Main JS] Still waiting for worker to init",
182
+ timeoutCount
183
+ );
184
+ timeoutCount += 1;
185
+ timeoutId = setTimeout(logTimeout, 5000);
186
+ };
187
+ timeoutId = setTimeout(logTimeout, 5000);
188
+
189
+ sandboxWorker.onmessage = (workerEvent) => {
190
+ if (workerEvent.data.type === "READY") {
191
+ sandboxWorker.postMessage({
192
+ type: "INIT_WORKER",
193
+ payload: {
194
+ compiledModule,
195
+ sharedMemory,
196
+ },
197
+ });
198
+ }
199
+ if (workerEvent.data.type === "INIT_COMPLETE") {
200
+ resolve();
201
+ }
202
+ if (workerEvent.data.type === "INIT_FAILED") {
203
+ console.log("[Main JS] Sandbox init failed; retrying");
204
+ sandboxWorker = new Worker(sandboxJs, { type: "module" });
205
+ }
206
+ };
207
+ }).finally(() => {
208
+ clearTimeout(timeoutId);
209
+ });
210
+ };
211
+
212
+ await init({ module_or_path: compiledModule, memory: sharedMemory });
213
+ console.log("[Main JS] Main application WebAssembly module initialized.");
214
+
215
+ let res = await engine_init();
216
+ console.log(
217
+ "[Main JS] Main application WebAssembly module custom initialized: ",
218
+ res
219
+ );
220
+
221
+ // start asset loader thread
222
+ await new Promise((resolve, _reject) => {
223
+ const assetLoader = new Worker("asset_loader.js", { type: "module" });
224
+ assetLoader.onmessage = (workerEvent) => {
225
+ if (workerEvent.data.type === "READY") {
226
+ assetLoader.postMessage({
227
+ type: "INIT_ASSET_LOADER",
228
+ payload: {
229
+ compiledModule,
230
+ sharedMemory,
231
+ },
232
+ });
233
+ }
234
+ if (workerEvent.data.type === "INITIALIZED") {
235
+ resolve();
236
+ }
237
+ };
238
+ });
239
+ } catch (error) {
240
+ console.error(
241
+ "[Main JS] Error during Wasm initialization or setup:",
242
+ error
243
+ );
244
+ if (initButton) {
245
+ initButton.textContent = "Load Failed";
246
+ }
247
+ }
248
+ }
249
+
250
+ function start() {
251
+ const initialRealm = initialRealmInput.value;
252
+ const location = locationInput.value;
253
+ const systemScene = systemSceneInput.value;
254
+ console.log(
255
+ `[Main JS] "Go" button clicked. Initial Realm: "${initialRealm}", Location: "${location}", System Scene: "${systemScene}"`
256
+ );
257
+ hideHeader();
258
+
259
+ const platform = (() => {
260
+ if (navigator.userAgent.includes("Mac")) return "macos";
261
+ if (navigator.userAgent.includes("Win")) return "windows";
262
+ if (navigator.userAgent.includes("Linux")) return "linux";
263
+ return "unknown";
264
+ })();
265
+
266
+ engine_run(platform, initialRealm, location, systemScene, true, 1e6);
267
+ }
268
+
269
+ initButton.onclick = start;
270
+
271
+ Promise.all([initEngine(), initGpuCache()])
272
+ .then(() => {
273
+ if (autoStart) {
274
+ start()
275
+ } else {
276
+ initButton.disabled = false;
277
+ initButton.textContent = "Go";
278
+ }
279
+ })
280
+ .catch((e) => {
281
+ console.log("error", e);
282
+ initButton.textContent = "Load Failed";
283
+ });
284
+
package/package.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "@dcl-regenesislabs/bevy-explorer-web",
3
+ "version": "0.1.0-18229784557.commit-ef374b9",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/decentraland/bevy-explorer.git"
7
+ },
8
+ "commit": "ef374b9d611f6fcc5cdad1664cdbcc92d9a8a4a9"
9
+ }
@@ -0,0 +1,394 @@
1
+ // sandbox_worker.js - Runs inside the final Web Worker, the most isolated environment.
2
+
3
+ // Import the wasm-bindgen generated JS glue code.
4
+ import init, * as wasm_bindgen_exports from "./pkg/webgpu_build.js";
5
+
6
+ // self.WebSocket = {}
7
+
8
+ console.log("[Scene Worker] Starting");
9
+
10
+ const allowListES2020 = [
11
+ "Array",
12
+ "ArrayBuffer",
13
+ "BigInt",
14
+ "BigInt64Array",
15
+ "BigUint64Array",
16
+ "Boolean",
17
+ "DataView",
18
+ "Date",
19
+ "decodeURI",
20
+ "decodeURIComponent",
21
+ "encodeURI",
22
+ "encodeURIComponent",
23
+ "Error",
24
+ "escape",
25
+ "eval",
26
+ "EvalError",
27
+ "fetch",
28
+ "Float32Array",
29
+ "Float64Array",
30
+ "Function",
31
+ "Infinity",
32
+ "Int16Array",
33
+ "Int32Array",
34
+ "Int8Array",
35
+ "isFinite",
36
+ "isNaN",
37
+ "JSON",
38
+ "Map",
39
+ "Math",
40
+ "NaN",
41
+ "Number",
42
+ "Object",
43
+ "parseFloat",
44
+ "parseInt",
45
+ "Promise",
46
+ "Proxy",
47
+ "RangeError",
48
+ "ReferenceError",
49
+ "Reflect",
50
+ "RegExp",
51
+ "Set",
52
+ "SharedArrayBuffer",
53
+ "String",
54
+ "Symbol",
55
+ "SyntaxError",
56
+ "TypeError",
57
+ "Uint16Array",
58
+ "Uint32Array",
59
+ "Uint8Array",
60
+ "Uint8ClampedArray",
61
+ "undefined",
62
+ "unescape",
63
+ "URIError",
64
+ "WeakMap",
65
+ "WebSocket",
66
+ "WeakSet",
67
+ ];
68
+
69
+ const jsContext = Object.create(null);
70
+ var jsProxy = undefined;
71
+ var jsPreamble = undefined;
72
+ function createJsContext(wasmApi, context) {
73
+ const isSuper = wasmApi.is_super(context);
74
+
75
+ Object.defineProperty(jsContext, "console", {
76
+ value: {
77
+ log: console.log.bind(console),
78
+ info: console.info.bind(console),
79
+ debug: console.debug.bind(console),
80
+ trace: console.trace.bind(console),
81
+ warning: console.error.bind(console),
82
+ error: console.error.bind(console),
83
+ },
84
+ });
85
+
86
+ const ops = Object.create(null);
87
+ for (const exportName in wasmApi) {
88
+ if (exportName.substring(0, 3) === "op_") {
89
+ Object.defineProperty(ops, exportName, {
90
+ configurable: false,
91
+ get() {
92
+ return (...args) => {
93
+ // wrap ops to inject context arg
94
+ return wasmApi[exportName](context, ...args);
95
+ };
96
+ },
97
+ });
98
+ }
99
+ }
100
+ const core = Object.create(null);
101
+ Object.defineProperty(core, "ops", {
102
+ configurable: false,
103
+ value: ops,
104
+ });
105
+ const Deno = Object.create(null);
106
+ Object.defineProperty(Deno, "core", {
107
+ configurable: false,
108
+ value: core,
109
+ });
110
+ Object.defineProperty(jsContext, "Deno", {
111
+ configurable: false,
112
+ value: Deno,
113
+ });
114
+
115
+ Object.defineProperty(jsContext, "require", {
116
+ configurable: false,
117
+ value: require,
118
+ });
119
+ Object.defineProperty(jsContext, "localStorage", {
120
+ configurable: false,
121
+ value: createWebStorageProxy(ops),
122
+ });
123
+
124
+ // if (!isSuper) {
125
+ // Object.defineProperty(jsContext, "fetch", {
126
+ // configurable: false,
127
+ // get() {
128
+ // return (url, options) => {
129
+ // console.error('[Sandbox worker] Fetch request to', url, 'was intentionally blocked by the proxy.');
130
+ // return Promise.reject(new Error('This request has been intentionally failed by the proxy.'));
131
+ // };
132
+ // }
133
+ // })
134
+ // Object.defineProperty(jsContext, "WebSocket", {
135
+ // configurable: false,
136
+ // get() {
137
+ // console.log("get WebSocket!!!")
138
+ // return {}
139
+ // }
140
+ // })
141
+ // }
142
+
143
+ jsProxy = new Proxy(jsContext, {
144
+ has() {
145
+ return true;
146
+ },
147
+ get(_target, propKey, _receiver) {
148
+ if (propKey === "eval") return eval;
149
+ if (propKey === "globalThis") return jsProxy;
150
+ if (propKey === "global") return jsProxy;
151
+ if (propKey === "undefined") return undefined;
152
+ if (jsContext[propKey] !== undefined) return jsContext[propKey];
153
+ if (allowListES2020.includes(propKey)) {
154
+ return globalThis[propKey];
155
+ }
156
+ return undefined;
157
+ },
158
+ });
159
+
160
+ const contextKeys = Object.getOwnPropertyNames(jsContext);
161
+ const allGlobals = [...new Set([...allowListES2020, ...contextKeys])];
162
+ jsPreamble = allGlobals
163
+ .map((key) => `const ${key} = globalThis.${key};`)
164
+ .join("\n");
165
+ }
166
+
167
+ const defer = Promise.resolve().then.bind(Promise.resolve());
168
+
169
+ async function runWithScope(code) {
170
+ const module = { exports: {} };
171
+
172
+ const func = new Function(
173
+ "globalThis",
174
+ "module",
175
+ "exports",
176
+ `${jsPreamble}\n\n${code}`
177
+ );
178
+
179
+ await defer(() => func.call(jsProxy, jsProxy, module, module.exports));
180
+ return module.exports;
181
+ }
182
+
183
+ // prefetch all the requireable scripts before we replace the fetch function
184
+ var allowedModules = undefined;
185
+
186
+ async function preloadModules(context, fetch_fn) {
187
+ const modules = [
188
+ "~system/BevyExplorerApi",
189
+ "~system/CommunicationsController",
190
+ "~system/CommsApi",
191
+ "~system/EngineApi",
192
+ "~system/EnvironmentApi",
193
+ "~system/EthereumController",
194
+ "~system/Players",
195
+ "~system/PortableExperiences",
196
+ "~system/RestrictedActions",
197
+ "~system/Runtime",
198
+ "~system/Scene",
199
+ "~system/SignedFetch",
200
+ "~system/Testing",
201
+ "~system/UserActionModule",
202
+ "~system/UserIdentity",
203
+ "~system/AdaptationLayerHelper",
204
+ ];
205
+
206
+ const promises = modules.map(async (key) => {
207
+ try {
208
+ const code = fetch_fn(context, key);
209
+ const result = await runWithScope(code);
210
+ return [key, result];
211
+ } catch (e) {
212
+ return undefined
213
+ }
214
+ });
215
+
216
+ allowedModules = Object.fromEntries((await Promise.all(promises)).filter(e => e));
217
+ }
218
+
219
+ function require(moduleName) {
220
+ let code = allowedModules[moduleName];
221
+ if (!code) {
222
+ throw "can't find module `" + moduleName + "`";
223
+ }
224
+
225
+ return code;
226
+ }
227
+
228
+ self.onmessage = async (event) => {
229
+ if (event.data && event.data.type === "INIT_WORKER") {
230
+ const { compiledModule, sharedMemory } = event.data.payload;
231
+
232
+ if (!compiledModule || !sharedMemory) {
233
+ console.error("[Sandbox Worker] Invalid payload received.");
234
+ return;
235
+ }
236
+
237
+ var wasm_init;
238
+ try {
239
+ // init wasm
240
+ wasm_init = await init({
241
+ module_or_path: compiledModule,
242
+ memory: sharedMemory,
243
+ });
244
+ } catch (e) {
245
+ console.error(
246
+ "[Scene Worker] Error during Wasm instantiation or setup:",
247
+ e
248
+ );
249
+ postMessage({ type: `INIT_FAILED` });
250
+ self.close();
251
+ return;
252
+ }
253
+
254
+ postMessage({ type: `INIT_COMPLETE` });
255
+
256
+ // add listener to clean up on unhandled rejections
257
+ self.addEventListener("unhandledrejection", (event) => {
258
+ // Prevent the default browser action (logging to console)
259
+ event.preventDefault();
260
+
261
+ console.error(
262
+ "[Sandbox worker] FATAL: Unhandled Promise Rejection in Worker:",
263
+ event.reason
264
+ );
265
+
266
+ try {
267
+ wasm_init.__wbindgen_thread_destroy();
268
+ } catch (cleanupError) {
269
+ console.error(
270
+ "[Sandbox worker] Error during WASM cleanup:",
271
+ cleanupError
272
+ );
273
+ }
274
+
275
+ self.close();
276
+ });
277
+
278
+ var wasmContext;
279
+ try {
280
+ wasmContext = await wasm_bindgen_exports.wasm_init_scene();
281
+ } catch (e) {
282
+ console.error("[Scene Worker] Error during scene construction:", e);
283
+ try {
284
+ wasm_init.drop_context(wasmContext);
285
+ } catch (e) {}
286
+ wasm_init.__wbindgen_thread_destroy();
287
+ self.close();
288
+ return;
289
+ }
290
+
291
+ try {
292
+ createJsContext(wasm_bindgen_exports, wasmContext);
293
+ const ops = jsContext.Deno.core.ops;
294
+
295
+ // preload modules
296
+ await preloadModules(wasmContext, wasm_bindgen_exports.builtin_module);
297
+
298
+ const sceneCode = wasmContext.get_source();
299
+ let module = await runWithScope(sceneCode);
300
+
301
+ // send any initial rpc requests
302
+ ops.op_crdt_send_to_renderer([]);
303
+
304
+ await module.onStart();
305
+
306
+ var elapsed = 0;
307
+ const startTime = new Date();
308
+ var prevElapsed = 0;
309
+ var elapsed = 0;
310
+ var count = 0;
311
+ while (ops.op_continue_running()) {
312
+ const dt = (elapsed - prevElapsed) / 1000;
313
+ await module.onUpdate(dt);
314
+ prevElapsed = elapsed;
315
+ elapsed = new Date() - startTime;
316
+ count += 1;
317
+ }
318
+ console.log("[Scene Worker] exiting gracefully");
319
+ } catch (e) {
320
+ console.error("[Scene Worker] Error during scene execution:", e);
321
+ }
322
+
323
+ try {
324
+ wasm_init.drop_context(wasmContext);
325
+ } catch (e) {}
326
+ wasm_init.__wbindgen_thread_destroy();
327
+ self.close();
328
+ }
329
+ };
330
+
331
+ function createWebStorageProxy(ops) {
332
+ return new Proxy(
333
+ {},
334
+ {
335
+ get(_target, prop, _receiver) {
336
+ if (prop === "length") {
337
+ return ops.op_webstorage_length();
338
+ }
339
+
340
+ if (prop === "getItem") {
341
+ return (key) => ops.op_webstorage_get(String(key));
342
+ }
343
+ if (prop === "setItem") {
344
+ return (key, value) =>
345
+ ops.op_webstorage_set(String(key), String(value));
346
+ }
347
+ if (prop === "key") {
348
+ return (index) => ops.op_webstorage_key(index);
349
+ }
350
+ if (prop === "removeItem") {
351
+ return (key) => ops.op_webstorage_remove(String(key));
352
+ }
353
+ if (prop === "clear") {
354
+ return () => ops.op_webstorage_clear();
355
+ }
356
+
357
+ // Handle direct property access like `localStorage.myKey`
358
+ return ops.op_storage_get(String(prop));
359
+ },
360
+
361
+ set(_target, prop, value, _receiver) {
362
+ ops.op_storage_set(String(prop), String(value));
363
+ return true;
364
+ },
365
+
366
+ deleteProperty(_target, prop) {
367
+ ops.op_webstorage_remove(String(prop));
368
+ return true;
369
+ },
370
+
371
+ ownKeys(_target) {
372
+ return ops.op_webstorage_iterate_keys();
373
+ },
374
+
375
+ getOwnPropertyDescriptor(_target, prop) {
376
+ if (ops.op_webstorage_has(String(prop))) {
377
+ return {
378
+ value: ops.op_webstorage_get(String(prop)),
379
+ writable: true,
380
+ enumerable: true,
381
+ configurable: true,
382
+ };
383
+ }
384
+ return undefined;
385
+ },
386
+
387
+ has(_target, prop) {
388
+ return ops.op_webstorage_has(String(prop));
389
+ },
390
+ }
391
+ );
392
+ }
393
+
394
+ postMessage({ type: `READY` });
package/serve.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "headers": [
3
+ {
4
+ "source": "**/*",
5
+ "headers": [
6
+ {
7
+ "key": "Cross-Origin-Opener-Policy",
8
+ "value": "same-origin"
9
+ },
10
+ {
11
+ "key": "Cross-Origin-Embedder-Policy",
12
+ "value": "require-corp"
13
+ },
14
+ {
15
+ "key": "Cross-Origin-Resource-Policy",
16
+ "value": "cross-origin"
17
+ }
18
+ ]
19
+ }
20
+ ]
21
+ }