minecraft-renderer 0.1.78 → 0.1.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 (200) hide show
  1. package/README.md +29 -25
  2. package/dist/mesher.js +36 -36
  3. package/dist/mesher.js.map +4 -4
  4. package/dist/mesherWasm.js +217 -217
  5. package/dist/minecraft-renderer.js +32 -32
  6. package/dist/minecraft-renderer.js.meta.json +1 -1
  7. package/dist/threeWorker.js +415 -415
  8. package/package.json +5 -2
  9. package/src/bundler/bundlePrepare.ts +3 -8
  10. package/src/graphicsBackend/appViewer.ts +10 -7
  11. package/src/graphicsBackend/config.ts +1 -5
  12. package/src/graphicsBackend/playerState.ts +35 -34
  13. package/src/graphicsBackend/preloadWorkers.ts +43 -41
  14. package/src/graphicsBackend/rendererDefaultOptions.ts +68 -70
  15. package/src/graphicsBackend/rendererOptionsSync.ts +24 -50
  16. package/src/graphicsBackend/types.ts +2 -2
  17. package/src/index.ts +6 -27
  18. package/src/lib/DebugGui.ts +34 -31
  19. package/src/lib/animationController.ts +9 -9
  20. package/src/lib/bakeLegacyLight.ts +1 -6
  21. package/src/lib/bindAbortableListener.test.ts +32 -12
  22. package/src/lib/bindAbortableListener.ts +14 -6
  23. package/src/lib/blockEntityLightRegistry.ts +11 -20
  24. package/src/lib/blockEntityLighting.test.ts +1 -6
  25. package/src/lib/blockEntityLighting.ts +5 -5
  26. package/src/lib/buildSharedConfig.mjs +4 -4
  27. package/src/lib/buildWorkerMcDataIndexes.test.ts +4 -4
  28. package/src/lib/buildWorkerMcDataIndexes.ts +11 -19
  29. package/src/lib/cameraBobbing.ts +1 -1
  30. package/src/lib/canvas2DOverlay.example.ts +13 -33
  31. package/src/lib/canvas2DOverlay.quickstart.ts +24 -54
  32. package/src/lib/canvas2DOverlay.ts +28 -47
  33. package/src/lib/cleanupDecorator.ts +2 -2
  34. package/src/lib/createPlayerObject.test.ts +2 -7
  35. package/src/lib/createPlayerObject.ts +18 -25
  36. package/src/lib/frameTimingCollector.ts +2 -5
  37. package/src/lib/guiRenderer.ts +57 -42
  38. package/src/lib/items.ts +15 -9
  39. package/src/lib/mesherlogReader.ts +5 -6
  40. package/src/lib/simpleUtils.ts +5 -5
  41. package/src/lib/skyLight.ts +3 -3
  42. package/src/lib/smoothSwitcher.ts +11 -18
  43. package/src/lib/ui/newStats.ts +10 -12
  44. package/src/lib/utils/proxy.ts +7 -1
  45. package/src/lib/utils/skins.ts +4 -4
  46. package/src/lib/utils.ts +1 -1
  47. package/src/lib/workerMessageSanitize.ts +5 -12
  48. package/src/lib/workerProxy.ts +52 -42
  49. package/src/lib/workerSyncOps.test.ts +58 -41
  50. package/src/lib/worldrendererCommon.reconfigure.test.ts +24 -21
  51. package/src/lib/worldrendererCommon.removeColumn.test.ts +11 -13
  52. package/src/lib/worldrendererCommon.ts +338 -211
  53. package/src/mesher-legacy/mesher.ts +9 -4
  54. package/src/mesher-legacy/test/a.ts +1 -1
  55. package/src/mesher-legacy/test/mesherTester.ts +2 -2
  56. package/src/mesher-legacy/test/playground.ts +1 -1
  57. package/src/mesher-legacy/test/run/test-js.ts +1 -1
  58. package/src/mesher-legacy/test/snapshotUtils.ts +3 -8
  59. package/src/mesher-legacy/test/test-perf.ts +1 -1
  60. package/src/mesher-legacy/test/tests.test.ts +2 -2
  61. package/src/mesher-shared/blockEntityMetadata.test.ts +7 -5
  62. package/src/mesher-shared/blockEntityMetadata.ts +28 -19
  63. package/src/mesher-shared/blockPropertiesForMeshing.ts +2 -2
  64. package/src/mesher-shared/computeHeightmap.ts +2 -4
  65. package/src/mesher-shared/exportedGeometryTypes.ts +3 -3
  66. package/src/mesher-shared/faceOcclusion.ts +324 -0
  67. package/src/mesher-shared/models.ts +80 -131
  68. package/src/mesher-shared/modelsGeometryCommon.ts +30 -15
  69. package/src/mesher-shared/shared.ts +46 -46
  70. package/src/mesher-shared/standaloneRenderer.ts +40 -44
  71. package/src/mesher-shared/tests/faceOcclusion.test.ts +179 -0
  72. package/src/mesher-shared/tests/liquidQuadInvariant.test.ts +12 -8
  73. package/src/mesher-shared/vertexShading.ts +2 -11
  74. package/src/mesher-shared/world.ts +19 -19
  75. package/src/mesher-shared/worldLighting.test.ts +2 -2
  76. package/src/performanceMonitor/PerformanceMonitor.ts +4 -13
  77. package/src/performanceMonitor/formatPerformanceFactorsDebug.ts +2 -2
  78. package/src/performanceMonitor/index.ts +1 -5
  79. package/src/performanceMonitor/types.ts +1 -1
  80. package/src/playerState/playerState.ts +55 -50
  81. package/src/playerState/types.ts +2 -8
  82. package/src/playground/allEntitiesDebug.ts +19 -16
  83. package/src/playground/baseScene.ts +29 -32
  84. package/src/playground/mobileControls.tsx +133 -129
  85. package/src/playground/playground.html +76 -73
  86. package/src/playground/playground.ts +14 -1
  87. package/src/playground/playgroundUi.tsx +100 -74
  88. package/src/playground/reactUtils.ts +3 -7
  89. package/src/playground/scenes/entities.ts +10 -7
  90. package/src/playground/scenes/frequentUpdates.ts +5 -5
  91. package/src/playground/scenes/geometryExport.ts +6 -20
  92. package/src/playground/scenes/highPosEntityUpdates.ts +2 -10
  93. package/src/playground/scenes/index.ts +1 -1
  94. package/src/playground/scenes/lightingStarfield.ts +18 -12
  95. package/src/playground/scenes/main.ts +15 -11
  96. package/src/playground/scenes/partialBlockCulling.ts +31 -0
  97. package/src/playground/scenes/railsCobweb.ts +1 -1
  98. package/src/playground/scenes/rotationIssue.ts +1 -1
  99. package/src/playground/scenes/slabsOptimization.ts +1 -2
  100. package/src/playground/scenes/transparencyIssue.ts +1 -1
  101. package/src/playground/shared.ts +2 -2
  102. package/src/resourcesManager/resourcesManager.ts +29 -54
  103. package/src/resourcesManager/resourcesManager.worker.test.ts +6 -10
  104. package/src/shims/minecraftData.ts +70 -24
  105. package/src/sign-renderer/index.html +10 -12
  106. package/src/sign-renderer/index.ts +29 -29
  107. package/src/sign-renderer/playground.ts +22 -15
  108. package/src/sign-renderer/tests.test.ts +16 -13
  109. package/src/sign-renderer/vite.config.ts +2 -2
  110. package/src/three/appShared.ts +46 -25
  111. package/src/three/bannerRenderer.ts +33 -61
  112. package/src/three/cameraShake.ts +15 -6
  113. package/src/three/chunkMeshManager.ts +329 -301
  114. package/src/three/cinimaticScript.ts +26 -15
  115. package/src/three/cubeDrawSpans.ts +27 -37
  116. package/src/three/cubeMultiDraw.ts +9 -22
  117. package/src/three/documentRenderer.ts +15 -18
  118. package/src/three/entities.ts +175 -150
  119. package/src/three/entity/EntityMesh.ts +114 -108
  120. package/src/three/entity/animations.js +3 -3
  121. package/src/three/entity/armorModels.ts +15 -15
  122. package/src/three/entity/gltfAnimationUtils.ts +2 -5
  123. package/src/three/fireworks.ts +34 -32
  124. package/src/three/fireworksRenderer.ts +32 -29
  125. package/src/three/globalBlockBuffer.ts +174 -99
  126. package/src/three/globalLegacyBuffer.ts +465 -136
  127. package/src/three/graphicsBackendBase.ts +19 -25
  128. package/src/three/graphicsBackendOffThread.ts +12 -15
  129. package/src/three/hand.ts +21 -21
  130. package/src/three/handLegacy.ts +3 -13
  131. package/src/three/holdingBlock.ts +116 -79
  132. package/src/three/holdingBlockFactory.ts +1 -4
  133. package/src/three/holdingBlockItemIdentity.test.ts +25 -17
  134. package/src/three/holdingBlockItemIdentity.ts +9 -6
  135. package/src/three/holdingBlockLegacy.ts +113 -132
  136. package/src/three/itemMesh.ts +20 -29
  137. package/src/three/legacyMultiDraw.ts +93 -0
  138. package/src/three/legacySectionCull.ts +8 -14
  139. package/src/three/menuBackground/activeView.ts +1 -4
  140. package/src/three/menuBackground/assetUrl.ts +1 -1
  141. package/src/three/menuBackground/classic.ts +4 -12
  142. package/src/three/menuBackground/gpuPreference.ts +1 -3
  143. package/src/three/menuBackground/index.ts +2 -11
  144. package/src/three/menuBackground/renderer.ts +1 -5
  145. package/src/three/menuBackground/types.ts +1 -4
  146. package/src/three/menuBackground/v2.ts +196 -96
  147. package/src/three/menuBackground/v2Meta.ts +3 -3
  148. package/src/three/menuBackground/worldBlocks.ts +37 -35
  149. package/src/three/modules/blockBreakParticles.ts +59 -28
  150. package/src/three/modules/cameraBobbing.ts +3 -6
  151. package/src/three/modules/index.ts +1 -1
  152. package/src/three/modules/rain.ts +10 -23
  153. package/src/three/modules/sciFiWorldReveal.ts +11 -25
  154. package/src/three/modules/starfield.ts +7 -13
  155. package/src/three/renderSlot.ts +28 -16
  156. package/src/three/rendererModuleSystem.ts +1 -3
  157. package/src/three/sceneOrigin.ts +96 -33
  158. package/src/three/sectionRaycastAabb.ts +30 -18
  159. package/src/three/shaderCubeMesh.ts +6 -17
  160. package/src/three/shaders/cubeBlockShader.ts +85 -96
  161. package/src/three/shaders/legacyBlockShader.ts +21 -43
  162. package/src/three/shaders/textureIndexMapping.ts +89 -95
  163. package/src/three/shaders/tintPalette.ts +156 -170
  164. package/src/three/signTextureCache.ts +9 -12
  165. package/src/three/skyboxRenderer.ts +62 -70
  166. package/src/three/tests/chunkMeshManagerLegacy.test.ts +133 -25
  167. package/src/three/tests/cubeDrawSpans.test.ts +55 -25
  168. package/src/three/tests/globalBlockBuffer.test.ts +217 -0
  169. package/src/three/tests/globalLegacyBuffer.test.ts +460 -58
  170. package/src/three/tests/legacyMultiDraw.test.ts +88 -0
  171. package/src/three/tests/pr3PerFrameCpuCuts.test.ts +370 -0
  172. package/src/three/tests/signTextureCache.test.ts +4 -4
  173. package/src/three/threeJsMedia.ts +55 -72
  174. package/src/three/threeJsParticles.ts +32 -41
  175. package/src/three/threeJsSound.ts +3 -3
  176. package/src/three/threeJsUtils.ts +3 -3
  177. package/src/three/threeWorker.ts +2 -2
  178. package/src/three/waypointSprite.ts +55 -82
  179. package/src/three/waypoints.ts +20 -23
  180. package/src/three/world/cursorBlock.ts +25 -12
  181. package/src/three/world/vr.ts +11 -17
  182. package/src/three/worldGeometryExport.ts +15 -34
  183. package/src/three/worldRendererThree.ts +131 -133
  184. package/src/wasm-mesher/bridge/convertChunk.ts +3 -9
  185. package/src/wasm-mesher/bridge/render-from-wasm.ts +204 -229
  186. package/src/wasm-mesher/bridge/shaderCubeBridge.ts +26 -67
  187. package/src/wasm-mesher/tests/cullingRegression.test.ts +307 -0
  188. package/src/wasm-mesher/tests/heightmapParity.test.ts +8 -18
  189. package/src/wasm-mesher/tests/mesherWasmConversionCache.test.ts +2 -2
  190. package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +17 -4
  191. package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +103 -141
  192. package/src/wasm-mesher/tests/splitColumnWasmOutput.test.ts +14 -22
  193. package/src/wasm-mesher/worker/mesherWasm.ts +150 -141
  194. package/src/wasm-mesher/worker/mesherWasmConversionCache.ts +2 -8
  195. package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +1 -3
  196. package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +1 -5
  197. package/src/wasm-mesher/worker/mesherWasmRequestTracker.ts +42 -42
  198. package/src/worldView/worldView.spiral.test.ts +1 -1
  199. package/src/worldView/worldView.ts +34 -39
  200. package/src/worldView/worldViewWorkerBridge.test.ts +4 -4
@@ -12,19 +12,13 @@ const CULL_BOX_EPSILON = 0.01
12
12
  * Set a legacy section mesh world translation once at build time.
13
13
  * Position proxy is not used — camera-relative math lives in the shader.
14
14
  */
15
- export function setupLegacySectionMatrix (
16
- mesh: THREE.Mesh,
17
- sx: number,
18
- sy: number,
19
- sz: number,
20
- renderOrigin: RenderOrigin,
21
- ): void {
15
+ export function setupLegacySectionMatrix(mesh: THREE.Mesh, sx: number, sy: number, sz: number, renderOrigin: RenderOrigin): void {
22
16
  mesh.matrix.makeTranslation(sx - renderOrigin.x, sy - renderOrigin.y, sz - renderOrigin.z)
23
17
  mesh.matrixWorldNeedsUpdate = true
24
18
  mesh.frustumCulled = false
25
19
  }
26
20
 
27
- export function sectionIntersectsFrustum (
21
+ export function sectionIntersectsFrustum(
28
22
  sectionWorldX: number,
29
23
  sectionWorldY: number,
30
24
  sectionWorldZ: number,
@@ -34,8 +28,8 @@ export function sectionIntersectsFrustum (
34
28
  frustum: THREE.Frustum,
35
29
  box: THREE.Box3,
36
30
  boxMin: THREE.Vector3,
37
- boxMax: THREE.Vector3,
38
- ): { visible: boolean, distSq: number } {
31
+ boxMax: THREE.Vector3
32
+ ): { visible: boolean; distSq: number } {
39
33
  const dx = sectionWorldX - cameraWorldX
40
34
  const dy = sectionWorldY - cameraWorldY
41
35
  const dz = sectionWorldZ - cameraWorldZ
@@ -47,7 +41,7 @@ export function sectionIntersectsFrustum (
47
41
 
48
42
  return {
49
43
  visible: frustum.intersectsBox(box),
50
- distSq: dx * dx + dy * dy + dz * dz,
44
+ distSq: dx * dx + dy * dy + dz * dz
51
45
  }
52
46
  }
53
47
 
@@ -55,7 +49,7 @@ export function sectionIntersectsFrustum (
55
49
  * Per-frame frustum cull + back-to-front renderOrder for one legacy section.
56
50
  * Used for pooled per-section meshes (reveal defer + invariant fallback).
57
51
  */
58
- export function updateLegacySectionCullState (
52
+ export function updateLegacySectionCullState(
59
53
  mesh: THREE.Mesh,
60
54
  sectionWorldX: number,
61
55
  sectionWorldY: number,
@@ -66,7 +60,7 @@ export function updateLegacySectionCullState (
66
60
  frustum: THREE.Frustum,
67
61
  box: THREE.Box3,
68
62
  boxMin: THREE.Vector3,
69
- boxMax: THREE.Vector3,
63
+ boxMax: THREE.Vector3
70
64
  ): void {
71
65
  const { visible, distSq } = sectionIntersectsFrustum(
72
66
  sectionWorldX,
@@ -78,7 +72,7 @@ export function updateLegacySectionCullState (
78
72
  frustum,
79
73
  box,
80
74
  boxMin,
81
- boxMax,
75
+ boxMax
82
76
  )
83
77
  mesh.visible = visible
84
78
  mesh.renderOrder = -distSq
@@ -10,10 +10,7 @@ export interface MenuBackgroundView {
10
10
  dispose(): void
11
11
  }
12
12
 
13
- export function resizeMenuBackgroundCamera(
14
- camera: THREE.PerspectiveCamera,
15
- canvas: { width: number, height: number }
16
- ) {
13
+ export function resizeMenuBackgroundCamera(camera: THREE.PerspectiveCamera, canvas: { width: number; height: number }) {
17
14
  camera.aspect = canvas.width / canvas.height
18
15
  camera.updateProjectionMatrix()
19
16
  }
@@ -1,5 +1,5 @@
1
1
  //@ts-nocheck
2
- export function menuBackgroundAssetUrl (...segments: string[]): string {
2
+ export function menuBackgroundAssetUrl(...segments: string[]): string {
3
3
  const relative = segments.filter(s => s.length > 0).join('/')
4
4
  const base =
5
5
  typeof globalThis.location !== 'undefined' && globalThis.location.href
@@ -17,7 +17,7 @@ const panoramaFiles = [
17
17
  'panorama_4.webp', // top (+y)
18
18
  'panorama_5.webp', // bottom (-y)
19
19
  'panorama_0.webp', // front (+z)
20
- 'panorama_2.webp', // back (-z)
20
+ 'panorama_2.webp' // back (-z)
21
21
  ]
22
22
 
23
23
  const FADE_IN_DURATION_MS = 200
@@ -44,12 +44,7 @@ export class ClassicMenuBackground implements MenuBackgroundView {
44
44
  directional.castShadow = true
45
45
  this.scene.add(directional)
46
46
 
47
- this.camera = new THREE.PerspectiveCamera(
48
- 85,
49
- documentRenderer.canvas.width / documentRenderer.canvas.height,
50
- 0.05,
51
- 1000
52
- )
47
+ this.camera = new THREE.PerspectiveCamera(85, documentRenderer.canvas.width / documentRenderer.canvas.height, 0.05, 1000)
53
48
  this.camera.position.set(0, 0, 0)
54
49
  this.camera.rotation.set(0, 0, 0)
55
50
  }
@@ -130,7 +125,7 @@ export class ClassicMenuBackground implements MenuBackgroundView {
130
125
  const v = Math.random() * 0.01
131
126
  m.children[0].onBeforeRender = () => {
132
127
  m.rotation.y += v
133
- m.rotation.z = Math.cos(panoramaBox.rotation.y * 3) * Math.PI / 4 - Math.PI / 2
128
+ m.rotation.z = (Math.cos(panoramaBox.rotation.y * 3) * Math.PI) / 4 - Math.PI / 2
134
129
  }
135
130
  group.add(m)
136
131
  }
@@ -144,10 +139,7 @@ export class ClassicMenuBackground implements MenuBackgroundView {
144
139
  async debugImageInFrontOfCamera() {
145
140
  const bitmap = await loadImageFromUrl(menuBackgroundAssetUrl('background', 'panorama_0.webp'))
146
141
  const image = loadThreeJsTextureFromBitmap(bitmap)
147
- const mesh = new THREE.Mesh(
148
- new THREE.PlaneGeometry(1000, 1000),
149
- new THREE.MeshBasicMaterial({ map: image })
150
- )
142
+ const mesh = new THREE.Mesh(new THREE.PlaneGeometry(1000, 1000), new THREE.MeshBasicMaterial({ map: image }))
151
143
  mesh.position.set(0, 0, -500)
152
144
  this.scene.add(mesh)
153
145
  }
@@ -2,9 +2,7 @@
2
2
  export type RendererGpuPreference = 'default' | 'high-performance' | 'low-power'
3
3
 
4
4
  /** Maps stored `gpuPreference` to WebGL `powerPreference` (undefined = browser default). */
5
- export function gpuPreferenceToWebGLPowerPreference(
6
- preference: RendererGpuPreference
7
- ): 'high-performance' | 'low-power' | undefined {
5
+ export function gpuPreferenceToWebGLPowerPreference(preference: RendererGpuPreference): 'high-performance' | 'low-power' | undefined {
8
6
  if (preference === 'high-performance') return 'high-performance'
9
7
  if (preference === 'low-power') return 'low-power'
10
8
  return undefined
@@ -5,12 +5,7 @@ export { resizeMenuBackgroundCamera } from './activeView'
5
5
  export type { MenuBackgroundMode, MenuBackgroundOptions } from './types'
6
6
  export { resolveMenuBackgroundMode } from './types'
7
7
  export { ClassicMenuBackground } from './classic'
8
- export type {
9
- V2SceneId,
10
- V2CameraId,
11
- V2MenuBackgroundOptions,
12
- MinecraftBlockGroupId
13
- } from './v2'
8
+ export type { V2SceneId, V2CameraId, V2MenuBackgroundOptions, MinecraftBlockGroupId } from './v2'
14
9
  export {
15
10
  V2MenuBackground,
16
11
  V2_SCENE_IDS,
@@ -23,11 +18,7 @@ export {
23
18
  } from './v2'
24
19
  export { WorldBlocksMenuBackground } from './worldBlocks'
25
20
  export { MenuBackgroundRenderer } from './renderer'
26
- export {
27
- MENU_BACKGROUND_OPTION_DEFAULTS,
28
- MENU_BACKGROUND_MOTION_DEFAULTS,
29
- menuBackgroundSpeedToMultiplier
30
- } from './config'
21
+ export { MENU_BACKGROUND_OPTION_DEFAULTS, MENU_BACKGROUND_MOTION_DEFAULTS, menuBackgroundSpeedToMultiplier } from './config'
31
22
  export {
32
23
  RENDERER_DEFAULT_OPTIONS,
33
24
  RENDERER_OPTIONS_META,
@@ -79,11 +79,7 @@ export class MenuBackgroundRenderer {
79
79
  this.abortController.signal
80
80
  )
81
81
  case 'worldBlocks':
82
- return new WorldBlocksMenuBackground(
83
- this.documentRenderer,
84
- this.options,
85
- this.abortController.signal
86
- )
82
+ return new WorldBlocksMenuBackground(this.documentRenderer, this.options, this.abortController.signal)
87
83
  default:
88
84
  return new ClassicMenuBackground(this.documentRenderer)
89
85
  }
@@ -27,10 +27,7 @@ export interface MenuBackgroundOptions {
27
27
  resourcesManager?: ResourcesManager
28
28
  }
29
29
 
30
- export function resolveMenuBackgroundMode(
31
- options?: MenuBackgroundOptions,
32
- singleFileBuild = false
33
- ): MenuBackgroundMode {
30
+ export function resolveMenuBackgroundMode(options?: MenuBackgroundOptions, singleFileBuild = false): MenuBackgroundMode {
34
31
  if (options?.mode) return options.mode
35
32
  if (singleFileBuild) return 'worldBlocks'
36
33
  return MENU_BACKGROUND_OPTION_DEFAULTS.mode
@@ -7,23 +7,9 @@ import type { MenuBackgroundView } from './activeView'
7
7
  import { resizeMenuBackgroundCamera } from './activeView'
8
8
  import { loadThreeJsTextureFromBitmap } from '../threeJsUtils'
9
9
  import { MENU_BACKGROUND_MOTION_DEFAULTS, MENU_BACKGROUND_OPTION_DEFAULTS } from './config'
10
- import {
11
- V2_CAMERA_IDS,
12
- V2_SCENE_IDS,
13
- MINECRAFT_BLOCK_GROUP_IDS,
14
- type V2CameraId,
15
- type V2SceneId,
16
- type MinecraftBlockGroupId,
17
- } from './v2Meta'
18
-
19
- export {
20
- V2_SCENE_IDS,
21
- V2_SCENE_LABELS,
22
- V2_CAMERA_IDS,
23
- V2_CAMERA_LABELS,
24
- MINECRAFT_BLOCK_GROUP_IDS,
25
- MINECRAFT_BLOCK_GROUP_LABELS,
26
- } from './v2Meta'
10
+ import { V2_CAMERA_IDS, V2_SCENE_IDS, MINECRAFT_BLOCK_GROUP_IDS, type V2CameraId, type V2SceneId, type MinecraftBlockGroupId } from './v2Meta'
11
+
12
+ export { V2_SCENE_IDS, V2_SCENE_LABELS, V2_CAMERA_IDS, V2_CAMERA_LABELS, MINECRAFT_BLOCK_GROUP_IDS, MINECRAFT_BLOCK_GROUP_LABELS } from './v2Meta'
27
13
  export type { V2SceneId, V2CameraId, MinecraftBlockGroupId } from './v2Meta'
28
14
 
29
15
  /** Mouse parallax scale (HTML prototype uses 1). */
@@ -44,41 +30,132 @@ export interface V2MenuBackgroundOptions {
44
30
  /** Block pools for textured floating cubes (selected via {@link V2MenuBackground.setBlockGroup}). */
45
31
  export const MINECRAFT_BLOCK_GROUPS = {
46
32
  mixed: [
47
- 'white_wool', 'cyan_wool', 'blue_wool', 'purple_wool',
48
- 'white_stained_glass', 'cyan_stained_glass', 'blue_stained_glass', 'purple_stained_glass',
49
- 'glowstone', 'sea_lantern', 'amethyst_block', 'copper_block', 'gold_block', 'diamond_block'
33
+ 'white_wool',
34
+ 'cyan_wool',
35
+ 'blue_wool',
36
+ 'purple_wool',
37
+ 'white_stained_glass',
38
+ 'cyan_stained_glass',
39
+ 'blue_stained_glass',
40
+ 'purple_stained_glass',
41
+ 'glowstone',
42
+ 'sea_lantern',
43
+ 'amethyst_block',
44
+ 'copper_block',
45
+ 'gold_block',
46
+ 'diamond_block'
50
47
  ],
51
48
  stainedGlass: [
52
- 'white_stained_glass', 'orange_stained_glass', 'magenta_stained_glass', 'light_blue_stained_glass',
53
- 'yellow_stained_glass', 'lime_stained_glass', 'pink_stained_glass', 'gray_stained_glass',
54
- 'light_gray_stained_glass', 'cyan_stained_glass', 'purple_stained_glass', 'blue_stained_glass',
55
- 'brown_stained_glass', 'green_stained_glass', 'red_stained_glass', 'black_stained_glass'
49
+ 'white_stained_glass',
50
+ 'orange_stained_glass',
51
+ 'magenta_stained_glass',
52
+ 'light_blue_stained_glass',
53
+ 'yellow_stained_glass',
54
+ 'lime_stained_glass',
55
+ 'pink_stained_glass',
56
+ 'gray_stained_glass',
57
+ 'light_gray_stained_glass',
58
+ 'cyan_stained_glass',
59
+ 'purple_stained_glass',
60
+ 'blue_stained_glass',
61
+ 'brown_stained_glass',
62
+ 'green_stained_glass',
63
+ 'red_stained_glass',
64
+ 'black_stained_glass'
56
65
  ],
57
66
  wool: [
58
- 'white_wool', 'orange_wool', 'magenta_wool', 'light_blue_wool', 'yellow_wool', 'lime_wool',
59
- 'pink_wool', 'gray_wool', 'light_gray_wool', 'cyan_wool', 'purple_wool', 'blue_wool',
60
- 'brown_wool', 'green_wool', 'red_wool', 'black_wool'
67
+ 'white_wool',
68
+ 'orange_wool',
69
+ 'magenta_wool',
70
+ 'light_blue_wool',
71
+ 'yellow_wool',
72
+ 'lime_wool',
73
+ 'pink_wool',
74
+ 'gray_wool',
75
+ 'light_gray_wool',
76
+ 'cyan_wool',
77
+ 'purple_wool',
78
+ 'blue_wool',
79
+ 'brown_wool',
80
+ 'green_wool',
81
+ 'red_wool',
82
+ 'black_wool'
61
83
  ],
62
84
  construction: [
63
- 'copper_block', 'exposed_copper', 'weathered_copper', 'oxidized_copper',
64
- 'cut_copper', 'exposed_cut_copper', 'weathered_cut_copper', 'oxidized_cut_copper',
65
- 'iron_block', 'gold_block', 'diamond_block', 'emerald_block', 'netherite_block',
66
- 'lapis_block', 'redstone_block', 'coal_block', 'quartz_block', 'amethyst_block',
67
- 'bricks', 'stone_bricks', 'deepslate_bricks', 'polished_blackstone'
68
- ],
69
- glow: [
70
- 'glowstone', 'sea_lantern', 'shroomlight', 'ochre_froglight', 'verdant_froglight', 'pearlescent_froglight',
71
- 'redstone_lamp', 'beacon'
85
+ 'copper_block',
86
+ 'exposed_copper',
87
+ 'weathered_copper',
88
+ 'oxidized_copper',
89
+ 'cut_copper',
90
+ 'exposed_cut_copper',
91
+ 'weathered_cut_copper',
92
+ 'oxidized_cut_copper',
93
+ 'iron_block',
94
+ 'gold_block',
95
+ 'diamond_block',
96
+ 'emerald_block',
97
+ 'netherite_block',
98
+ 'lapis_block',
99
+ 'redstone_block',
100
+ 'coal_block',
101
+ 'quartz_block',
102
+ 'amethyst_block',
103
+ 'bricks',
104
+ 'stone_bricks',
105
+ 'deepslate_bricks',
106
+ 'polished_blackstone'
72
107
  ],
108
+ glow: ['glowstone', 'sea_lantern', 'shroomlight', 'ochre_froglight', 'verdant_froglight', 'pearlescent_froglight', 'redstone_lamp', 'beacon'],
73
109
  world: [
74
- 'grass_block', 'podzol', 'mycelium', 'dirt', 'coarse_dirt', 'rooted_dirt', 'mud', 'clay',
75
- 'stone', 'cobblestone', 'mossy_cobblestone', 'deepslate', 'cobbled_deepslate', 'tuff', 'calcite',
76
- 'sand', 'red_sand', 'gravel', 'snow_block',
77
- 'coal_ore', 'deepslate_coal_ore', 'iron_ore', 'deepslate_iron_ore', 'copper_ore', 'deepslate_copper_ore',
78
- 'gold_ore', 'deepslate_gold_ore', 'diamond_ore', 'deepslate_diamond_ore', 'emerald_ore', 'deepslate_emerald_ore',
79
- 'lapis_ore', 'deepslate_lapis_ore', 'redstone_ore', 'deepslate_redstone_ore', 'nether_gold_ore', 'ancient_debris',
80
- 'oak_log', 'birch_log', 'spruce_log', 'jungle_log', 'acacia_log', 'dark_oak_log', 'mangrove_log', 'cherry_log',
81
- 'netherrack', 'soul_sand', 'basalt', 'end_stone'
110
+ 'grass_block',
111
+ 'podzol',
112
+ 'mycelium',
113
+ 'dirt',
114
+ 'coarse_dirt',
115
+ 'rooted_dirt',
116
+ 'mud',
117
+ 'clay',
118
+ 'stone',
119
+ 'cobblestone',
120
+ 'mossy_cobblestone',
121
+ 'deepslate',
122
+ 'cobbled_deepslate',
123
+ 'tuff',
124
+ 'calcite',
125
+ 'sand',
126
+ 'red_sand',
127
+ 'gravel',
128
+ 'snow_block',
129
+ 'coal_ore',
130
+ 'deepslate_coal_ore',
131
+ 'iron_ore',
132
+ 'deepslate_iron_ore',
133
+ 'copper_ore',
134
+ 'deepslate_copper_ore',
135
+ 'gold_ore',
136
+ 'deepslate_gold_ore',
137
+ 'diamond_ore',
138
+ 'deepslate_diamond_ore',
139
+ 'emerald_ore',
140
+ 'deepslate_emerald_ore',
141
+ 'lapis_ore',
142
+ 'deepslate_lapis_ore',
143
+ 'redstone_ore',
144
+ 'deepslate_redstone_ore',
145
+ 'nether_gold_ore',
146
+ 'ancient_debris',
147
+ 'oak_log',
148
+ 'birch_log',
149
+ 'spruce_log',
150
+ 'jungle_log',
151
+ 'acacia_log',
152
+ 'dark_oak_log',
153
+ 'mangrove_log',
154
+ 'cherry_log',
155
+ 'netherrack',
156
+ 'soul_sand',
157
+ 'basalt',
158
+ 'end_stone'
82
159
  ]
83
160
  } as const
84
161
 
@@ -96,7 +173,7 @@ interface ScenePalette {
96
173
  pt2: number
97
174
  name: string
98
175
  /** Vertical (or radial) sky gradient instead of a flat scene background. */
99
- gradientBg?: { top: number, mid?: number, bottom: number, radial?: boolean }
176
+ gradientBg?: { top: number; mid?: number; bottom: number; radial?: boolean }
100
177
  starColor?: number
101
178
  starOpacity?: number
102
179
  galaxyOpacity?: number
@@ -106,8 +183,8 @@ interface ScenePalette {
106
183
  }
107
184
 
108
185
  interface CameraMode {
109
- pos: (t: number, mx: number, my: number) => { x: number, y: number, z: number }
110
- look: (t: number, mx: number, my: number) => { x: number, y: number, z: number }
186
+ pos: (t: number, mx: number, my: number) => { x: number; y: number; z: number }
187
+ look: (t: number, mx: number, my: number) => { x: number; y: number; z: number }
111
188
  roll: (t: number, mx?: number) => number
112
189
  spd: number
113
190
  }
@@ -125,36 +202,60 @@ interface FloatingBlock {
125
202
 
126
203
  const PAL: Record<V2SceneId, ScenePalette> = {
127
204
  galaxy: {
128
- bg: 0x02_04_12, fog: 0x02_04_12, fogD: 0.011,
205
+ bg: 0x02_04_12,
206
+ fog: 0x02_04_12,
207
+ fogD: 0.011,
129
208
  blocks: [0x00_f0_ff, 0x00_d4_ff, 0x00_b8_ff, 0x00_e8_ff, 0x22_cc_ff, 0x00_a8_ff],
130
209
  emit: [0x00_33_66, 0x00_22_55, 0x00_1a_44],
131
210
  nebula: [0x00_11_33, 0x11_00_22, 0x00_11_22],
132
211
  galFn: b => new THREE.Color(b * 0.05, b * 0.2, b),
133
- ambient: 0x04_08_18, dir: 0x33_66_ff, pt1: 0x00_aa_ff, pt2: 0xff_44_ff, name: 'GALAXY'
212
+ ambient: 0x04_08_18,
213
+ dir: 0x33_66_ff,
214
+ pt1: 0x00_aa_ff,
215
+ pt2: 0xff_44_ff,
216
+ name: 'GALAXY'
134
217
  },
135
218
  nether: {
136
- bg: 0x0e_01_00, fog: 0x0e_01_00, fogD: 0.016,
219
+ bg: 0x0e_01_00,
220
+ fog: 0x0e_01_00,
221
+ fogD: 0.016,
137
222
  blocks: [0xff_22_00, 0xff_66_00, 0xff_99_00, 0xcc_11_00, 0xff_44_22, 0xff_aa_00],
138
223
  emit: [0x22_08_00, 0x11_00_00, 0x33_11_00],
139
224
  nebula: [0x1a_04_00, 0x0d_00_00, 0x1a_08_00],
140
225
  galFn: b => new THREE.Color(b, b * 0.15, 0),
141
- ambient: 0x18_02_00, dir: 0xff_33_00, pt1: 0xff_44_00, pt2: 0xff_aa_00, name: 'NETHER'
226
+ ambient: 0x18_02_00,
227
+ dir: 0xff_33_00,
228
+ pt1: 0xff_44_00,
229
+ pt2: 0xff_aa_00,
230
+ name: 'NETHER'
142
231
  },
143
232
  end: {
144
- bg: 0x00_00_00, fog: 0x00_00_00, fogD: 0.009,
233
+ bg: 0x00_00_00,
234
+ fog: 0x00_00_00,
235
+ fogD: 0.009,
145
236
  blocks: [0x77_22_aa, 0xaa_44_cc, 0x55_00_77, 0xdd_aa_ff, 0x33_00_55, 0xbb_aa_ff],
146
237
  emit: [0x0a_00_15, 0x18_00_25, 0x05_00_10],
147
238
  nebula: [0x08_00_18, 0x0d_00_15, 0x04_00_0e],
148
239
  galFn: b => new THREE.Color(b * 0.4, 0, b),
149
- ambient: 0x06_00_10, dir: 0x99_33_ff, pt1: 0xaa_44_ff, pt2: 0x44_00_aa, name: 'THE END'
240
+ ambient: 0x06_00_10,
241
+ dir: 0x99_33_ff,
242
+ pt1: 0xaa_44_ff,
243
+ pt2: 0x44_00_aa,
244
+ name: 'THE END'
150
245
  },
151
246
  cyber: {
152
- bg: 0x0c_18_22, fog: 0x0c_18_22, fogD: 0.008,
247
+ bg: 0x0c_18_22,
248
+ fog: 0x0c_18_22,
249
+ fogD: 0.008,
153
250
  blocks: [0x00_ff_ff, 0x44_ff_cc, 0xaa_ff_44, 0x66_dd_ff, 0x88_ff_66, 0x00_ff_aa],
154
251
  emit: [0x0a_2a_33, 0x0a_33_22, 0x0a_28_38],
155
252
  nebula: [0x12_30_40, 0x18_38_28, 0x14_32_44],
156
253
  galFn: b => new THREE.Color(b * 0.15, b * 0.85, b * 0.95),
157
- ambient: 0x1a_30_40, dir: 0x66_ff_cc, pt1: 0x44_ff_ee, pt2: 0x99_ff_44, name: 'CYBER',
254
+ ambient: 0x1a_30_40,
255
+ dir: 0x66_ff_cc,
256
+ pt1: 0x44_ff_ee,
257
+ pt2: 0x99_ff_44,
258
+ name: 'CYBER',
158
259
  starColor: 0xcc_f0_ff,
159
260
  starOpacity: 0.75,
160
261
  galaxyOpacity: 0.62,
@@ -167,10 +268,7 @@ const PAL: Record<V2SceneId, ScenePalette> = {
167
268
  fog: 0x78_88_a0,
168
269
  fogD: 0.006,
169
270
  gradientBg: { top: 0xd8_e4_f8, mid: 0xa0_b0_c8, bottom: 0x68_78_90, radial: true },
170
- blocks: [
171
- 0xe8_f2_ff, 0xd0_e8_ff, 0xb8_d8_ff, 0xa0_c8_f8, 0x88_b8_f0, 0x70_a8_e8,
172
- 0x98_c8_ff, 0xc0_e0_ff, 0xf0_f8_ff, 0x78_b0_e8, 0xd8_ec_ff, 0xe0_e8_ff
173
- ],
271
+ blocks: [0xe8_f2_ff, 0xd0_e8_ff, 0xb8_d8_ff, 0xa0_c8_f8, 0x88_b8_f0, 0x70_a8_e8, 0x98_c8_ff, 0xc0_e0_ff, 0xf0_f8_ff, 0x78_b0_e8, 0xd8_ec_ff, 0xe0_e8_ff],
174
272
  emit: [0x68_98_d0, 0x88_b0_e0, 0xa8_c8_f0, 0xc0_d8_f8],
175
273
  nebula: [0x90_a8_c8, 0xa8_c0_e0, 0xc0_d4_ec, 0xd8_e8_f8, 0x78_90_b0],
176
274
  galFn: b => {
@@ -250,7 +348,7 @@ const BCOUNT = 250
250
348
  const GCNT = 10_000
251
349
  const NCNT = 3000
252
350
 
253
- const rp = <T,>(arr: T[]) => arr[Math.floor(Math.random() * arr.length)]
351
+ const rp = <T>(arr: T[]) => arr[Math.floor(Math.random() * arr.length)]
254
352
 
255
353
  const colorHex = (n: number) => '#' + n.toString(16).padStart(6, '0')
256
354
 
@@ -263,9 +361,7 @@ const makeSkyGradientTexture = (gradient: NonNullable<ScenePalette['gradientBg']
263
361
  if (!ctx) return null
264
362
  const w = canvas.width
265
363
  const h = canvas.height
266
- const grad = gradient.radial
267
- ? ctx.createRadialGradient(w / 2, h * 0.32, 0, w / 2, h * 0.32, h * 0.85)
268
- : ctx.createLinearGradient(0, 0, 0, h)
364
+ const grad = gradient.radial ? ctx.createRadialGradient(w / 2, h * 0.32, 0, w / 2, h * 0.32, h * 0.85) : ctx.createLinearGradient(0, 0, 0, h)
269
365
  grad.addColorStop(0, colorHex(gradient.top))
270
366
  if (gradient.mid != null) grad.addColorStop(0.45, colorHex(gradient.mid))
271
367
  grad.addColorStop(1, colorHex(gradient.bottom))
@@ -336,12 +432,7 @@ export class V2MenuBackground implements MenuBackgroundView {
336
432
  this.scene.fog = new THREE.FogExp2(pal.fog, pal.fogD)
337
433
  this.applyScenePalette(pal)
338
434
 
339
- this.camera = new THREE.PerspectiveCamera(
340
- 80,
341
- this.documentRenderer.canvas.width / this.documentRenderer.canvas.height,
342
- 0.1,
343
- 700
344
- )
435
+ this.camera = new THREE.PerspectiveCamera(80, this.documentRenderer.canvas.width / this.documentRenderer.canvas.height, 0.1, 700)
345
436
 
346
437
  this.ambient = new THREE.AmbientLight(pal.ambient, 2.5)
347
438
  this.scene.add(this.ambient)
@@ -368,13 +459,16 @@ export class V2MenuBackground implements MenuBackgroundView {
368
459
  const sp = new Float32Array(5000 * 3)
369
460
  for (let i = 0; i < 5000 * 3; i++) sp[i] = (Math.random() - 0.5) * 500
370
461
  sGeo.setAttribute('position', new THREE.BufferAttribute(sp, 3))
371
- this.stars = new THREE.Points(sGeo, new THREE.PointsMaterial({
372
- color: pal.starColor ?? 0xff_ff_ff,
373
- size: 0.3,
374
- transparent: true,
375
- opacity: pal.starOpacity ?? 0.7,
376
- sizeAttenuation: true
377
- }))
462
+ this.stars = new THREE.Points(
463
+ sGeo,
464
+ new THREE.PointsMaterial({
465
+ color: pal.starColor ?? 0xff_ff_ff,
466
+ size: 0.3,
467
+ transparent: true,
468
+ opacity: pal.starOpacity ?? 0.7,
469
+ sizeAttenuation: true
470
+ })
471
+ )
378
472
  this.scene.add(this.stars)
379
473
 
380
474
  this.galGeo = new THREE.BufferGeometry()
@@ -397,9 +491,16 @@ export class V2MenuBackground implements MenuBackgroundView {
397
491
  }
398
492
  this.galGeo.setAttribute('position', new THREE.BufferAttribute(gp, 3))
399
493
  this.galGeo.setAttribute('color', new THREE.BufferAttribute(gc, 3))
400
- this.galaxy = new THREE.Points(this.galGeo, new THREE.PointsMaterial({
401
- size: 0.9, vertexColors: true, transparent: true, opacity: pal.galaxyOpacity ?? 0.55, sizeAttenuation: true
402
- }))
494
+ this.galaxy = new THREE.Points(
495
+ this.galGeo,
496
+ new THREE.PointsMaterial({
497
+ size: 0.9,
498
+ vertexColors: true,
499
+ transparent: true,
500
+ opacity: pal.galaxyOpacity ?? 0.55,
501
+ sizeAttenuation: true
502
+ })
503
+ )
403
504
  this.scene.add(this.galaxy)
404
505
 
405
506
  this.nebGeo = new THREE.BufferGeometry()
@@ -419,9 +520,16 @@ export class V2MenuBackground implements MenuBackgroundView {
419
520
  }
420
521
  this.nebGeo.setAttribute('position', new THREE.BufferAttribute(np, 3))
421
522
  this.nebGeo.setAttribute('color', new THREE.BufferAttribute(nc, 3))
422
- this.nebula = new THREE.Points(this.nebGeo, new THREE.PointsMaterial({
423
- size: 3, vertexColors: true, transparent: true, opacity: pal.nebulaOpacity ?? 0.3, sizeAttenuation: true
424
- }))
523
+ this.nebula = new THREE.Points(
524
+ this.nebGeo,
525
+ new THREE.PointsMaterial({
526
+ size: 3,
527
+ vertexColors: true,
528
+ transparent: true,
529
+ opacity: pal.nebulaOpacity ?? 0.3,
530
+ sizeAttenuation: true
531
+ })
532
+ )
425
533
  this.scene.add(this.nebula)
426
534
 
427
535
  this.addBackgroundTextPlane()
@@ -534,8 +642,8 @@ export class V2MenuBackground implements MenuBackgroundView {
534
642
  if (next) {
535
643
  this.gradientSkyTexture.dispose()
536
644
  this.gradientSkyTexture = next
537
- ; (this.gradientSky.material as THREE.MeshBasicMaterial).map = next
538
- ; (this.gradientSky.material as THREE.MeshBasicMaterial).needsUpdate = true
645
+ ;(this.gradientSky.material as THREE.MeshBasicMaterial).map = next
646
+ ;(this.gradientSky.material as THREE.MeshBasicMaterial).needsUpdate = true
539
647
  }
540
648
  }
541
649
  }
@@ -619,11 +727,7 @@ export class V2MenuBackground implements MenuBackgroundView {
619
727
  const mesh = new THREE.Mesh(this.bGeo, mat)
620
728
  const s = 0.3 + Math.random() * 3
621
729
  mesh.scale.setScalar(s)
622
- mesh.position.set(
623
- (Math.random() - 0.5) * 140,
624
- (Math.random() - 0.5) * 70,
625
- init ? -(Math.random() * 140) : -155 - Math.random() * 30
626
- )
730
+ mesh.position.set((Math.random() - 0.5) * 140, (Math.random() - 0.5) * 70, init ? -(Math.random() * 140) : -155 - Math.random() * 30)
627
731
  mesh.rotation.set(Math.random() * Math.PI * 2, Math.random() * Math.PI * 2, Math.random() * Math.PI * 2)
628
732
  const d: FloatingBlock = {
629
733
  mesh,
@@ -677,9 +781,9 @@ export class V2MenuBackground implements MenuBackgroundView {
677
781
 
678
782
  private resolveBlockAtlasUv(
679
783
  blockName: string,
680
- textures: Record<string, { u: number, v: number, su?: number, sv?: number }>,
784
+ textures: Record<string, { u: number; v: number; su?: number; sv?: number }>,
681
785
  atlasJson: { suSv: number }
682
- ): { u: number, v: number, su: number, sv: number } | null {
786
+ ): { u: number; v: number; su: number; sv: number } | null {
683
787
  const pick = (key: string) => {
684
788
  const tex = textures[key]
685
789
  if (!tex) return null
@@ -861,11 +965,7 @@ export class V2MenuBackground implements MenuBackgroundView {
861
965
  b.mesh.material.opacity = base * pulse
862
966
  }
863
967
  if (b.mesh.position.z > this.camera.position.z + 15) {
864
- b.mesh.position.set(
865
- (Math.random() - 0.5) * 140,
866
- (Math.random() - 0.5) * 70,
867
- this.camera.position.z - 155 - Math.random() * 30
868
- )
968
+ b.mesh.position.set((Math.random() - 0.5) * 140, (Math.random() - 0.5) * 70, this.camera.position.z - 155 - Math.random() * 30)
869
969
  }
870
970
  }
871
971
 
@@ -2,10 +2,10 @@
2
2
  /** Settings / labels only — no Three.js or DocumentRenderer (safe for defaultOptions imports). */
3
3
 
4
4
  export const V2_SCENE_IDS = ['galaxy', 'nether', 'end', 'cyber', 'light'] as const
5
- export type V2SceneId = typeof V2_SCENE_IDS[number]
5
+ export type V2SceneId = (typeof V2_SCENE_IDS)[number]
6
6
 
7
7
  export const V2_CAMERA_IDS = ['cruise', 'barrel', 'dive', 'orbit', 'snake'] as const
8
- export type V2CameraId = typeof V2_CAMERA_IDS[number]
8
+ export type V2CameraId = (typeof V2_CAMERA_IDS)[number]
9
9
 
10
10
  export const V2_SCENE_LABELS: Record<V2SceneId, string> = {
11
11
  galaxy: 'Galaxy',
@@ -24,7 +24,7 @@ export const V2_CAMERA_LABELS: Record<V2CameraId, string> = {
24
24
  }
25
25
 
26
26
  export const MINECRAFT_BLOCK_GROUP_IDS = ['mixed', 'stainedGlass', 'wool', 'construction', 'glow', 'world'] as const
27
- export type MinecraftBlockGroupId = typeof MINECRAFT_BLOCK_GROUP_IDS[number]
27
+ export type MinecraftBlockGroupId = (typeof MINECRAFT_BLOCK_GROUP_IDS)[number]
28
28
 
29
29
  export const MINECRAFT_BLOCK_GROUP_LABELS: Record<MinecraftBlockGroupId, string> = {
30
30
  mixed: 'Mixed',