minecraft-renderer 0.1.79 → 0.1.81

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 (205) hide show
  1. package/README.md +66 -26
  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 +66 -66
  6. package/dist/minecraft-renderer.js.meta.json +1 -1
  7. package/dist/threeWorker.js +450 -450
  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 +349 -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/cameraCollisionBlockCache.ts +156 -0
  113. package/src/three/cameraCollisionSolidity.ts +50 -0
  114. package/src/three/cameraShake.ts +15 -6
  115. package/src/three/chunkMeshManager.ts +223 -390
  116. package/src/three/cinimaticScript.ts +26 -15
  117. package/src/three/cubeDrawSpans.ts +27 -37
  118. package/src/three/cubeMultiDraw.ts +9 -22
  119. package/src/three/documentRenderer.ts +15 -18
  120. package/src/three/entities.ts +175 -150
  121. package/src/three/entity/EntityMesh.ts +114 -108
  122. package/src/three/entity/animations.js +3 -3
  123. package/src/three/entity/armorModels.ts +15 -15
  124. package/src/three/entity/gltfAnimationUtils.ts +2 -5
  125. package/src/three/fireworks.ts +34 -32
  126. package/src/three/fireworksRenderer.ts +32 -29
  127. package/src/three/globalBlockBuffer.ts +167 -100
  128. package/src/three/globalLegacyBuffer.ts +248 -264
  129. package/src/three/graphicsBackendBase.ts +19 -25
  130. package/src/three/graphicsBackendOffThread.ts +12 -15
  131. package/src/three/hand.ts +21 -21
  132. package/src/three/handLegacy.ts +3 -13
  133. package/src/three/holdingBlock.ts +116 -79
  134. package/src/three/holdingBlockFactory.ts +1 -4
  135. package/src/three/holdingBlockItemIdentity.test.ts +25 -17
  136. package/src/three/holdingBlockItemIdentity.ts +9 -6
  137. package/src/three/holdingBlockLegacy.ts +113 -132
  138. package/src/three/itemMesh.ts +20 -29
  139. package/src/three/legacyMultiDraw.ts +10 -16
  140. package/src/three/legacySectionCull.ts +8 -14
  141. package/src/three/menuBackground/activeView.ts +1 -4
  142. package/src/three/menuBackground/assetUrl.ts +1 -1
  143. package/src/three/menuBackground/classic.ts +4 -12
  144. package/src/three/menuBackground/gpuPreference.ts +1 -3
  145. package/src/three/menuBackground/index.ts +2 -11
  146. package/src/three/menuBackground/renderer.ts +1 -5
  147. package/src/three/menuBackground/types.ts +1 -4
  148. package/src/three/menuBackground/v2.ts +196 -96
  149. package/src/three/menuBackground/v2Meta.ts +3 -3
  150. package/src/three/menuBackground/worldBlocks.ts +37 -35
  151. package/src/three/modules/blockBreakParticles.ts +59 -28
  152. package/src/three/modules/cameraBobbing.ts +3 -6
  153. package/src/three/modules/index.ts +1 -1
  154. package/src/three/modules/rain.ts +10 -23
  155. package/src/three/modules/sciFiWorldReveal.ts +11 -25
  156. package/src/three/modules/starfield.ts +7 -13
  157. package/src/three/renderSlot.ts +28 -16
  158. package/src/three/rendererModuleSystem.ts +1 -3
  159. package/src/three/sceneOrigin.ts +96 -33
  160. package/src/three/sectionRaycastAabb.ts +24 -110
  161. package/src/three/shaderCubeMesh.ts +6 -17
  162. package/src/three/shaders/cubeBlockShader.ts +85 -96
  163. package/src/three/shaders/legacyBlockShader.ts +21 -43
  164. package/src/three/shaders/textureIndexMapping.ts +89 -95
  165. package/src/three/shaders/tintPalette.ts +156 -170
  166. package/src/three/signTextureCache.ts +9 -12
  167. package/src/three/skyboxRenderer.ts +62 -70
  168. package/src/three/tests/chunkMeshManagerLegacy.test.ts +34 -64
  169. package/src/three/tests/cubeDrawSpans.test.ts +55 -25
  170. package/src/three/tests/globalBlockBuffer.test.ts +217 -0
  171. package/src/three/tests/globalLegacyBuffer.test.ts +300 -41
  172. package/src/three/tests/legacyMultiDraw.test.ts +8 -29
  173. package/src/three/tests/pr3PerFrameCpuCuts.test.ts +106 -29
  174. package/src/three/tests/signTextureCache.test.ts +4 -4
  175. package/src/three/thirdPersonVoxelRaycast.ts +120 -0
  176. package/src/three/threeJsMedia.ts +55 -72
  177. package/src/three/threeJsParticles.ts +32 -41
  178. package/src/three/threeJsSound.ts +3 -3
  179. package/src/three/threeJsUtils.ts +3 -3
  180. package/src/three/threeWorker.ts +2 -2
  181. package/src/three/waypointSprite.ts +55 -82
  182. package/src/three/waypoints.ts +20 -23
  183. package/src/three/world/cursorBlock.ts +25 -12
  184. package/src/three/world/vr.ts +11 -17
  185. package/src/three/worldGeometryExport.ts +15 -34
  186. package/src/three/worldRendererThree.ts +144 -166
  187. package/src/wasm-mesher/bridge/convertChunk.ts +3 -9
  188. package/src/wasm-mesher/bridge/render-from-wasm.ts +204 -229
  189. package/src/wasm-mesher/bridge/shaderCubeBridge.ts +26 -67
  190. package/src/wasm-mesher/tests/cameraCollisionBlockCache.test.ts +82 -0
  191. package/src/wasm-mesher/tests/cullingRegression.test.ts +307 -0
  192. package/src/wasm-mesher/tests/heightmapParity.test.ts +8 -18
  193. package/src/wasm-mesher/tests/mesherWasmConversionCache.test.ts +2 -2
  194. package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +1 -93
  195. package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +103 -141
  196. package/src/wasm-mesher/tests/splitColumnWasmOutput.test.ts +14 -22
  197. package/src/wasm-mesher/tests/thirdPersonVoxelRaycast.test.ts +63 -0
  198. package/src/wasm-mesher/worker/mesherWasm.ts +150 -141
  199. package/src/wasm-mesher/worker/mesherWasmConversionCache.ts +2 -8
  200. package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +1 -3
  201. package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +1 -5
  202. package/src/wasm-mesher/worker/mesherWasmRequestTracker.ts +42 -42
  203. package/src/worldView/worldView.spiral.test.ts +1 -1
  204. package/src/worldView/worldView.ts +34 -39
  205. package/src/worldView/worldViewWorkerBridge.test.ts +4 -4
@@ -49,7 +49,7 @@ export const getBackendMethods = (worldRenderer: WorldRendererThree): any => {
49
49
  setVideoVolume: worldRenderer.media.setVideoVolume.bind(worldRenderer.media),
50
50
  setVideoSpeed: worldRenderer.media.setVideoSpeed.bind(worldRenderer.media),
51
51
  handleUserClick: worldRenderer.media.handleUserClick.bind(worldRenderer.media),
52
- addSectionAnimation(id: string, animation: typeof worldRenderer.sectionsOffsetsAnimations[string]) {
52
+ addSectionAnimation(id: string, animation: (typeof worldRenderer.sectionsOffsetsAnimations)[string]) {
53
53
  worldRenderer.sectionsOffsetsAnimations[id] = animation
54
54
  },
55
55
  removeSectionAnimation(id: string) {
@@ -105,7 +105,7 @@ export const getBackendMethods = (worldRenderer: WorldRendererThree): any => {
105
105
  return {
106
106
  loadedSectionsChunks,
107
107
  loadedChunks: { ...worldRenderer.loadedChunks },
108
- finishedChunks: { ...worldRenderer.finishedChunks },
108
+ finishedChunks: { ...worldRenderer.finishedChunks }
109
109
  }
110
110
  }
111
111
  }
@@ -157,9 +157,9 @@ export const createGraphicsBackendBase = () => {
157
157
  }
158
158
 
159
159
  documentRenderer = new DocumentRenderer(initOptions, mainData?.canvas)
160
- ; (globalThis as any).renderer = documentRenderer.renderer
161
- ; (globalThis as any).documentRenderer = documentRenderer
162
- ; (globalThis as any).threeJsBackend = backend
160
+ ;(globalThis as any).renderer = documentRenderer.renderer
161
+ ;(globalThis as any).documentRenderer = documentRenderer
162
+ ;(globalThis as any).threeJsBackend = backend
163
163
 
164
164
  callModsMethod('default', backend)
165
165
  }
@@ -171,8 +171,8 @@ export const createGraphicsBackendBase = () => {
171
171
  worldRenderer.destroy()
172
172
  worldRenderer = null
173
173
  frameTimingCollector = null
174
- ; (globalThis as any).world = undefined
175
- ; (globalThis as any).frameTimingCollector = undefined
174
+ ;(globalThis as any).world = undefined
175
+ ;(globalThis as any).frameTimingCollector = undefined
176
176
  }
177
177
 
178
178
  if (menuBackgroundRenderer) {
@@ -184,12 +184,7 @@ export const createGraphicsBackendBase = () => {
184
184
  ...initOptions.config.menuBackground,
185
185
  ...menuBackgroundStartOptions
186
186
  }
187
- menuBackgroundRenderer = new MenuBackgroundRenderer(
188
- documentRenderer,
189
- { ...initOptions },
190
- mergedOptions,
191
- !!process.env.SINGLE_FILE_BUILD_MODE
192
- )
187
+ menuBackgroundRenderer = new MenuBackgroundRenderer(documentRenderer, { ...initOptions }, mergedOptions, !!process.env.SINGLE_FILE_BUILD_MODE)
193
188
  callModsMethod('menuBackgroundCreated', menuBackgroundRenderer)
194
189
  await menuBackgroundRenderer.start(mergedOptions)
195
190
  callModsMethod('menuBackgroundReady', menuBackgroundRenderer)
@@ -207,25 +202,25 @@ export const createGraphicsBackendBase = () => {
207
202
  worldRenderer.destroy()
208
203
  worldRenderer = null
209
204
  frameTimingCollector = null
210
- ; (globalThis as any).world = undefined
211
- ; (globalThis as any).frameTimingCollector = undefined
205
+ ;(globalThis as any).world = undefined
206
+ ;(globalThis as any).frameTimingCollector = undefined
212
207
  }
213
208
 
214
209
  const displayOptionsRestorers = [ResourcesManager, WorldViewWorker]
215
- const displayOptions: DisplayWorldOptions = isWebWorker ? restoreTransferred(displayOptionsArg, displayOptionsRestorers, globalThis as unknown as Worker) : displayOptionsArg
210
+ const displayOptions: DisplayWorldOptions = isWebWorker
211
+ ? restoreTransferred(displayOptionsArg, displayOptionsRestorers, globalThis as unknown as Worker)
212
+ : displayOptionsArg
216
213
 
217
214
  documentRenderer.nonReactiveState = displayOptions.nonReactiveState
218
- // Set resourcesManager globally for world rendering
219
- ; (globalThis as any).resourcesManager = displayOptions.resourcesManager
215
+ // Set resourcesManager globally for world rendering
216
+ ;(globalThis as any).resourcesManager = displayOptions.resourcesManager
220
217
 
221
218
  worldRenderer = new WorldRendererThree(documentRenderer.renderer, initOptions, displayOptions)
222
219
 
223
220
  await worldRenderer.worldReadyPromise
224
221
 
225
- frameTimingCollector = displayOptions.inWorldRenderingConfig.enableDebugOverlay
226
- ? new FrameTimingCollector(displayOptions.nonReactiveState)
227
- : null
228
- ; (globalThis as any).frameTimingCollector = frameTimingCollector
222
+ frameTimingCollector = displayOptions.inWorldRenderingConfig.enableDebugOverlay ? new FrameTimingCollector(displayOptions.nonReactiveState) : null
223
+ ;(globalThis as any).frameTimingCollector = frameTimingCollector
229
224
 
230
225
  const originalRender = documentRenderer.render
231
226
 
@@ -242,8 +237,7 @@ export const createGraphicsBackendBase = () => {
242
237
  }
243
238
 
244
239
  documentRenderer.inWorldRenderingConfig = displayOptions.inWorldRenderingConfig
245
-
246
- ; (globalThis as any).world = worldRenderer
240
+ ;(globalThis as any).world = worldRenderer
247
241
 
248
242
  callModsMethod('worldReady', worldRenderer)
249
243
  }
@@ -284,7 +278,7 @@ export const createGraphicsBackendBase = () => {
284
278
  return {
285
279
  'Geo Memory': worldRenderer?.chunkMeshManager.getEstimatedMemoryUsage().total ?? '-'
286
280
  }
287
- },
281
+ }
288
282
  }),
289
283
  updateCamera(pos: Vec3 | null, yaw: number, pitch: number) {
290
284
  // Mark camera update event for frame timing visualization
@@ -27,15 +27,18 @@ function initThreeWorker(onGotMessage: (data: any) => void) {
27
27
  worker.onmessage = ({ data }) => {
28
28
  onGotMessage(data)
29
29
  }
30
- if (worker.on) worker.on('message', (data) => { worker.onmessage({ data }) })
30
+ if (worker.on)
31
+ worker.on('message', data => {
32
+ worker.onmessage({ data })
33
+ })
31
34
  return worker
32
35
  }
33
36
 
34
- export const createGraphicsBackendOffThread: GraphicsBackendLoader = async (initOptions) => {
37
+ export const createGraphicsBackendOffThread: GraphicsBackendLoader = async initOptions => {
35
38
  const workerSideChannel = {
36
- onMessage: (_data: unknown) => {},
39
+ onMessage: (_data: unknown) => {}
37
40
  }
38
- const worker = initThreeWorker((data) => {
41
+ const worker = initThreeWorker(data => {
39
42
  workerSideChannel.onMessage(data)
40
43
  })
41
44
  type WorkerType = ReturnType<ReturnType<typeof createGraphicsBackendBase>['workerProxy']>
@@ -72,7 +75,7 @@ export const createGraphicsBackendOffThread: GraphicsBackendLoader = async (init
72
75
  const workerThreeSendData = {
73
76
  ...dynamicMcDataFiles,
74
77
  items: 'itemsArray',
75
- entities: 'entitiesArray',
78
+ entities: 'entitiesArray'
76
79
  }
77
80
  await meshersSendMcDataAwait([worker], MENU_BACKGROUND_MC_VERSION, workerThreeSendData, mcData)
78
81
  }
@@ -88,7 +91,7 @@ export const createGraphicsBackendOffThread: GraphicsBackendLoader = async (init
88
91
  const worldView = options.worldView as unknown as WorldView
89
92
  workerSideChannel.onMessage = (data: any) => {
90
93
  if (data?.type === 'reloadLoadedChunks') {
91
- void worldView.reloadLoadedChunks().catch((err) => {
94
+ void worldView.reloadLoadedChunks().catch(err => {
92
95
  console.error('[Renderer] Failed to reload chunks after mesher reconfigure:', err)
93
96
  })
94
97
  }
@@ -97,14 +100,9 @@ export const createGraphicsBackendOffThread: GraphicsBackendLoader = async (init
97
100
  const workerThreeSendData = {
98
101
  ...dynamicMcDataFiles,
99
102
  items: 'itemsArray',
100
- entities: 'entitiesArray',
103
+ entities: 'entitiesArray'
101
104
  }
102
- await meshersSendMcDataAwait(
103
- [worker],
104
- options.version,
105
- workerThreeSendData,
106
- options.resourcesManager.currentResources.mcData
107
- )
105
+ await meshersSendMcDataAwait([worker], options.version, workerThreeSendData, options.resourcesManager.currentResources.mcData)
108
106
  console.log('mc data sent to three worker')
109
107
 
110
108
  options.inWorldRenderingConfig['__syncToWorker'] = true
@@ -130,7 +128,6 @@ export const createGraphicsBackendOffThread: GraphicsBackendLoader = async (init
130
128
  }
131
129
  proxy.updateSizeExternal(canvas.size.width, canvas.size.height, window.devicePixelRatio || 1)
132
130
 
133
-
134
131
  const fpsStat = addNewStat('fps')
135
132
  setInterval(() => {
136
133
  const { fps, avgRenderTime, worstRenderTime } = options.nonReactiveState
@@ -139,7 +136,7 @@ export const createGraphicsBackendOffThread: GraphicsBackendLoader = async (init
139
136
  }, 1000)
140
137
 
141
138
  const chunksStat = addNewStat('downloaded-chunks', 100, 140, 20, {
142
- className: MC_RENDERER_DEBUG_OVERLAY_CLASS,
139
+ className: MC_RENDERER_DEBUG_OVERLAY_CLASS
143
140
  })
144
141
  setInterval(() => {
145
142
  const advanced = (initOptions.config.statsVisible ?? 0) > 1
package/src/three/hand.ts CHANGED
@@ -2,7 +2,6 @@
2
2
  import * as THREE from 'three'
3
3
  import { loadSkinFromUsername, loadSkinImage, stevePngUrl } from '../lib/utils/skins'
4
4
 
5
-
6
5
  export const getMyHand = async (image?: string, userName?: string) => {
7
6
  let newMap: THREE.Texture
8
7
  if (!image && !userName) {
@@ -26,12 +25,7 @@ export const getMyHand = async (image?: string, userName?: string) => {
26
25
  const pixelWidth = slim ? 3 : 4
27
26
 
28
27
  // Exact replica of vanilla's Cube: addBox(-3, -2, -2, 4, 12, 4) at texOffs(40, 16)
29
- const box = createVanillaCubeGeometry(
30
- 40, 16,
31
- slim ? -2 : -3, -2, -2,
32
- pixelWidth, 12, 4,
33
- 64, 64
34
- )
28
+ const box = createVanillaCubeGeometry(40, 16, slim ? -2 : -3, -2, -2, pixelWidth, 12, 4, 64, 64)
35
29
 
36
30
  const material = new THREE.MeshStandardMaterial()
37
31
  material.map = newMap
@@ -49,11 +43,17 @@ export const getMyHand = async (image?: string, userName?: string) => {
49
43
  * Vertices, face winding, normals, and UV mapping match the decompiled Java source.
50
44
  * Position coordinates are in pixels, divided by 16 for block units.
51
45
  */
52
- function createVanillaCubeGeometry (
53
- texU: number, texV: number,
54
- originX: number, originY: number, originZ: number,
55
- sizeX: number, sizeY: number, sizeZ: number,
56
- texWidth: number, texHeight: number,
46
+ function createVanillaCubeGeometry(
47
+ texU: number,
48
+ texV: number,
49
+ originX: number,
50
+ originY: number,
51
+ originZ: number,
52
+ sizeX: number,
53
+ sizeY: number,
54
+ sizeZ: number,
55
+ texWidth: number,
56
+ texHeight: number,
57
57
  mirror = false
58
58
  ): THREE.BufferGeometry {
59
59
  let minX = originX / 16
@@ -64,7 +64,7 @@ function createVanillaCubeGeometry (
64
64
  let maxZ = (originZ + sizeZ) / 16
65
65
 
66
66
  if (mirror) {
67
- [minX, maxX] = [maxX, minX]
67
+ ;[minX, maxX] = [maxX, minX]
68
68
  }
69
69
 
70
70
  // 8 corner vertices matching vanilla's Cube constructor
@@ -76,7 +76,7 @@ function createVanillaCubeGeometry (
76
76
  [minX, minY, maxZ], // 4
77
77
  [maxX, minY, maxZ], // 5
78
78
  [maxX, maxY, maxZ], // 6
79
- [minX, maxY, maxZ], // 7
79
+ [minX, maxY, maxZ] // 7
80
80
  ]
81
81
 
82
82
  // UV grid (pixel coords)
@@ -92,12 +92,12 @@ function createVanillaCubeGeometry (
92
92
 
93
93
  // 6 faces: vanilla vertex order + UV rect + normal
94
94
  const faces: { vi: number[]; uv: number[]; n: number[] }[] = [
95
- { vi: [5, 4, 0, 1], uv: [u1, v0, u2, v1], n: [0, -1, 0] }, // DOWN
96
- { vi: [2, 3, 7, 6], uv: [u2, v1, u3, v0], n: [0, 1, 0] }, // UP
97
- { vi: [0, 4, 7, 3], uv: [u0, v1, u1, v2], n: [-1, 0, 0] }, // WEST
98
- { vi: [1, 0, 3, 2], uv: [u1, v1, u2, v2], n: [0, 0, -1] }, // NORTH
99
- { vi: [5, 1, 2, 6], uv: [u2, v1, u4, v2], n: [1, 0, 0] }, // EAST
100
- { vi: [4, 5, 6, 7], uv: [u4, v1, u5, v2], n: [0, 0, 1] }, // SOUTH
95
+ { vi: [5, 4, 0, 1], uv: [u1, v0, u2, v1], n: [0, -1, 0] }, // DOWN
96
+ { vi: [2, 3, 7, 6], uv: [u2, v1, u3, v0], n: [0, 1, 0] }, // UP
97
+ { vi: [0, 4, 7, 3], uv: [u0, v1, u1, v2], n: [-1, 0, 0] }, // WEST
98
+ { vi: [1, 0, 3, 2], uv: [u1, v1, u2, v2], n: [0, 0, -1] }, // NORTH
99
+ { vi: [5, 1, 2, 6], uv: [u2, v1, u4, v2], n: [1, 0, 0] }, // EAST
100
+ { vi: [4, 5, 6, 7], uv: [u4, v1, u5, v2], n: [0, 0, 1] } // SOUTH
101
101
  ]
102
102
 
103
103
  const positions: number[] = []
@@ -115,7 +115,7 @@ function createVanillaCubeGeometry (
115
115
  [uR / texWidth, 1 - vT / texHeight],
116
116
  [uL / texWidth, 1 - vT / texHeight],
117
117
  [uL / texWidth, 1 - vB / texHeight],
118
- [uR / texWidth, 1 - vB / texHeight],
118
+ [uR / texWidth, 1 - vB / texHeight]
119
119
  ]
120
120
 
121
121
  const order = mirror ? [3, 2, 1, 0] : [0, 1, 2, 3]
@@ -3,7 +3,6 @@ import * as THREE from 'three'
3
3
  import { loadSkinFromUsername, loadSkinImage } from '../lib/utils/skins'
4
4
  import { steveTexture } from './entities'
5
5
 
6
-
7
6
  export const getMyHand = async (image?: string, userName?: string) => {
8
7
  let newMap: THREE.Texture
9
8
  if (!image && !userName) {
@@ -39,21 +38,12 @@ export const getMyHand = async (image?: string, userName?: string) => {
39
38
  return group
40
39
  }
41
40
 
42
- function setUVs (
43
- box: THREE.BoxGeometry,
44
- u: number,
45
- v: number,
46
- width: number,
47
- height: number,
48
- depth: number,
49
- textureWidth: number,
50
- textureHeight: number
51
- ): void {
41
+ function setUVs(box: THREE.BoxGeometry, u: number, v: number, width: number, height: number, depth: number, textureWidth: number, textureHeight: number): void {
52
42
  const toFaceVertices = (x1: number, y1: number, x2: number, y2: number) => [
53
43
  new THREE.Vector2(x1 / textureWidth, 1 - y2 / textureHeight),
54
44
  new THREE.Vector2(x2 / textureWidth, 1 - y2 / textureHeight),
55
45
  new THREE.Vector2(x2 / textureWidth, 1 - y1 / textureHeight),
56
- new THREE.Vector2(x1 / textureWidth, 1 - y1 / textureHeight),
46
+ new THREE.Vector2(x1 / textureWidth, 1 - y1 / textureHeight)
57
47
  ]
58
48
 
59
49
  const top = toFaceVertices(u + depth, v, u + width + depth, v + depth)
@@ -85,6 +75,6 @@ function setUVs (
85
75
  uvAttr.needsUpdate = true
86
76
  }
87
77
 
88
- function setSkinUVs (box: THREE.BoxGeometry, u: number, v: number, width: number, height: number, depth: number): void {
78
+ function setSkinUVs(box: THREE.BoxGeometry, u: number, v: number, width: number, height: number, depth: number): void {
89
79
  setUVs(box, u, v, width, height, depth, 64, 64)
90
80
  }
@@ -38,23 +38,23 @@ function buildBareHandMatrix(swingProgress: number, equipProgress: number): THRE
38
38
  // Step 1: Base position with swing
39
39
  mat.multiply(_tempMat.makeTranslation(side * (swingX + 0.64), swingY - 0.6 + equipProgress * -0.6, swingZ - 0.72))
40
40
  // Step 2: Base Y rotation 45°
41
- mat.multiply(_tempMat.makeRotationY(side * 45 * Math.PI / 180))
41
+ mat.multiply(_tempMat.makeRotationY((side * 45 * Math.PI) / 180))
42
42
  // Step 3: Swing Y rotation
43
- mat.multiply(_tempMat.makeRotationY(side * Math.sin(sqrtSwing * Math.PI) * 70 * Math.PI / 180))
43
+ mat.multiply(_tempMat.makeRotationY((side * Math.sin(sqrtSwing * Math.PI) * 70 * Math.PI) / 180))
44
44
  // Step 4: Swing Z rotation
45
- mat.multiply(_tempMat.makeRotationZ(side * Math.sin(swingProgress * swingProgress * Math.PI) * -20 * Math.PI / 180))
45
+ mat.multiply(_tempMat.makeRotationZ((side * Math.sin(swingProgress * swingProgress * Math.PI) * -20 * Math.PI) / 180))
46
46
  // Step 5: Second translation
47
47
  mat.multiply(_tempMat.makeTranslation(side * -1, 3.6, 3.5))
48
48
  // Step 6: Z rotation 120°
49
- mat.multiply(_tempMat.makeRotationZ(side * 120 * Math.PI / 180))
49
+ mat.multiply(_tempMat.makeRotationZ((side * 120 * Math.PI) / 180))
50
50
  // Step 7: X rotation 200°
51
- mat.multiply(_tempMat.makeRotationX(200 * Math.PI / 180))
51
+ mat.multiply(_tempMat.makeRotationX((200 * Math.PI) / 180))
52
52
  // Step 8: Y rotation -135°
53
- mat.multiply(_tempMat.makeRotationY(side * -135 * Math.PI / 180))
53
+ mat.multiply(_tempMat.makeRotationY((side * -135 * Math.PI) / 180))
54
54
  // Step 9: Final X offset
55
55
  mat.multiply(_tempMat.makeTranslation(side * 5.6, 0, 0))
56
56
  // Step 10: translateToHand - arm part position (-5/16, 2/16, 0)
57
- mat.multiply(_tempMat.makeTranslation(side * -5 / 16, 2 / 16, 0))
57
+ mat.multiply(_tempMat.makeTranslation((side * -5) / 16, 2 / 16, 0))
58
58
 
59
59
  return mat
60
60
  }
@@ -78,10 +78,10 @@ function buildItemArmMatrix(swingProgress: number, equipProgress: number): THREE
78
78
  // applyItemArmAttackTransform
79
79
  const sinSwingSq = Math.sin(swingProgress * swingProgress * Math.PI)
80
80
  const sinSqrtSwing = Math.sin(sqrtSwing * Math.PI)
81
- mat.multiply(_tempMat.makeRotationY(side * (45 + sinSwingSq * -20) * Math.PI / 180))
82
- mat.multiply(_tempMat.makeRotationZ(side * sinSqrtSwing * -20 * Math.PI / 180))
83
- mat.multiply(_tempMat.makeRotationX(sinSqrtSwing * -80 * Math.PI / 180))
84
- mat.multiply(_tempMat.makeRotationY(side * -45 * Math.PI / 180))
81
+ mat.multiply(_tempMat.makeRotationY((side * (45 + sinSwingSq * -20) * Math.PI) / 180))
82
+ mat.multiply(_tempMat.makeRotationZ((side * sinSqrtSwing * -20 * Math.PI) / 180))
83
+ mat.multiply(_tempMat.makeRotationX((sinSqrtSwing * -80 * Math.PI) / 180))
84
+ mat.multiply(_tempMat.makeRotationY((side * -45 * Math.PI) / 180))
85
85
 
86
86
  return mat
87
87
  }
@@ -89,10 +89,12 @@ function buildItemArmMatrix(swingProgress: number, equipProgress: number): THREE
89
89
  export default class HoldingBlock implements IHoldingBlock {
90
90
  // TODO refactor with the tree builder for better visual understanding
91
91
  holdingBlock: THREE.Object3D | undefined = undefined
92
- blockSwapAnimation: {
93
- switcher: SmoothSwitcher
94
- // hidden: boolean
95
- } | undefined = undefined
92
+ blockSwapAnimation:
93
+ | {
94
+ switcher: SmoothSwitcher
95
+ // hidden: boolean
96
+ }
97
+ | undefined = undefined
96
98
  cameraGroup = new THREE.Mesh()
97
99
  armTransformGroup = new THREE.Group()
98
100
  camera = new THREE.PerspectiveCamera(70, 1, 0.05, 100)
@@ -120,20 +122,31 @@ export default class HoldingBlock implements IHoldingBlock {
120
122
  private disposed = false
121
123
  private unsubs: Array<() => void> = []
122
124
 
123
- constructor(public worldRenderer: WorldRendererThree, public offHand = false) {
125
+ constructor(
126
+ public worldRenderer: WorldRendererThree,
127
+ public offHand = false
128
+ ) {
124
129
  this.initCameraGroup()
125
130
  this.swingAnimator = new HandSwingAnimator()
126
131
  this.unsubs.push(
127
- this.worldRenderer.onReactivePlayerStateUpdated('heldItemMain', () => {
128
- if (!this.offHand) {
129
- this.updateItem()
130
- }
131
- }, false),
132
- this.worldRenderer.onReactivePlayerStateUpdated('heldItemOff', () => {
133
- if (this.offHand) {
134
- this.updateItem()
135
- }
136
- }, false)
132
+ this.worldRenderer.onReactivePlayerStateUpdated(
133
+ 'heldItemMain',
134
+ () => {
135
+ if (!this.offHand) {
136
+ this.updateItem()
137
+ }
138
+ },
139
+ false
140
+ ),
141
+ this.worldRenderer.onReactivePlayerStateUpdated(
142
+ 'heldItemOff',
143
+ () => {
144
+ if (this.offHand) {
145
+ this.updateItem()
146
+ }
147
+ },
148
+ false
149
+ )
137
150
  )
138
151
  this.config = worldRenderer.displayOptions.inWorldRenderingConfig
139
152
 
@@ -141,33 +154,38 @@ export default class HoldingBlock implements IHoldingBlock {
141
154
  // this.offHandDisplay = true
142
155
  if (!this.offHand) {
143
156
  // load default hand
144
- void getMyHand().then((hand) => {
145
- if (this.disposed) return
146
- this.playerHand = hand
147
- // trigger update
148
- this.updateItem()
149
- }).then(() => {
150
- if (this.disposed) return
151
- // now watch over the player skin
152
- const unsub = watchProperty(
153
- async () => {
154
- return getMyHand(this.worldRenderer.playerStateReactive.playerSkin, this.worldRenderer.playerStateReactive.onlineMode ? this.worldRenderer.playerStateReactive.username : undefined)
155
- },
156
- this.worldRenderer.playerStateReactive,
157
- 'playerSkin',
158
- (newHand) => {
159
- if (newHand) {
160
- this.playerHand = newHand
161
- // trigger update
162
- this.updateItem()
157
+ void getMyHand()
158
+ .then(hand => {
159
+ if (this.disposed) return
160
+ this.playerHand = hand
161
+ // trigger update
162
+ this.updateItem()
163
+ })
164
+ .then(() => {
165
+ if (this.disposed) return
166
+ // now watch over the player skin
167
+ const unsub = watchProperty(
168
+ async () => {
169
+ return getMyHand(
170
+ this.worldRenderer.playerStateReactive.playerSkin,
171
+ this.worldRenderer.playerStateReactive.onlineMode ? this.worldRenderer.playerStateReactive.username : undefined
172
+ )
173
+ },
174
+ this.worldRenderer.playerStateReactive,
175
+ 'playerSkin',
176
+ newHand => {
177
+ if (newHand) {
178
+ this.playerHand = newHand
179
+ // trigger update
180
+ this.updateItem()
181
+ }
182
+ },
183
+ oldHand => {
184
+ disposeObject(oldHand!, true)
163
185
  }
164
- },
165
- (oldHand) => {
166
- disposeObject(oldHand!, true)
167
- }
168
- )
169
- this.unsubs.push(unsub)
170
- })
186
+ )
187
+ this.unsubs.push(unsub)
188
+ })
171
189
  }
172
190
  }
173
191
 
@@ -202,7 +220,7 @@ export default class HoldingBlock implements IHoldingBlock {
202
220
  void this.setNewItem()
203
221
  } else {
204
222
  void this.setNewItem({
205
- type: 'hand',
223
+ type: 'hand'
206
224
  })
207
225
  }
208
226
  }
@@ -225,7 +243,8 @@ export default class HoldingBlock implements IHoldingBlock {
225
243
  render(originalCamera: THREE.PerspectiveCamera, renderer: THREE.WebGLRenderer, ambientLight: THREE.AmbientLight, directionalLight: THREE.DirectionalLight) {
226
244
  if (!this.lastHeldItem) return
227
245
  const now = performance.now()
228
- if (this.lastUpdate && now - this.lastUpdate > 50) { // one tick
246
+ if (this.lastUpdate && now - this.lastUpdate > 50) {
247
+ // one tick
229
248
  void this.replaceItemModel(this.lastHeldItem)
230
249
  }
231
250
 
@@ -323,7 +342,7 @@ export default class HoldingBlock implements IHoldingBlock {
323
342
 
324
343
  const targetProgress = forceState === 'disappeared' ? 1 : 0
325
344
  let cancelled = false
326
- return new Promise<boolean>((resolve) => {
345
+ return new Promise<boolean>(resolve => {
327
346
  this.blockSwapAnimation!.switcher.transitionTo(
328
347
  { progress: targetProgress },
329
348
  forceState,
@@ -423,10 +442,15 @@ export default class HoldingBlock implements IHoldingBlock {
423
442
 
424
443
  let blockInner: THREE.Object3D | undefined
425
444
  if (handItem.type === 'item' || handItem.type === 'block') {
426
- const result = this.worldRenderer.entities.getItemMesh({
427
- ...handItem.fullItem,
428
- itemId: handItem.id,
429
- }, getFirstPersonItemSpecificProps(this.worldRenderer), false, this.lastItemModelName)
445
+ const result = this.worldRenderer.entities.getItemMesh(
446
+ {
447
+ ...handItem.fullItem,
448
+ itemId: handItem.id
449
+ },
450
+ getFirstPersonItemSpecificProps(this.worldRenderer),
451
+ false,
452
+ this.lastItemModelName
453
+ )
430
454
  if (result) {
431
455
  const { mesh: itemMesh, isBlock, modelName } = result
432
456
  if (isBlock) {
@@ -495,8 +519,6 @@ export default class HoldingBlock implements IHoldingBlock {
495
519
  this.holdingBlock = result.model
496
520
  this.currentDisplayType = result.type
497
521
  this.armTransformGroup.add(result.model)
498
-
499
-
500
522
  }
501
523
 
502
524
  testUnknownBlockSwitch() {
@@ -562,7 +584,6 @@ export default class HoldingBlock implements IHoldingBlock {
562
584
  // Idle animation disabled — walking bob is handled by vanilla bobView applied to cameraGroup
563
585
  this.idleAnimator = undefined
564
586
  }
565
-
566
587
  }
567
588
 
568
589
  class HandIdleAnimator {
@@ -587,7 +608,10 @@ class HandIdleAnimator {
587
608
 
588
609
  private readonly debugGui: DebugGui
589
610
 
590
- constructor(public handMesh: THREE.Object3D, public playerState: PlayerStateRenderer) {
611
+ constructor(
612
+ public handMesh: THREE.Object3D,
613
+ public playerState: PlayerStateRenderer
614
+ ) {
591
615
  this.handMesh = handMesh
592
616
  this.globalTime = 0
593
617
  this.currentState = 'NOT_MOVING'
@@ -616,12 +640,24 @@ class HandIdleAnimator {
616
640
  },
617
641
  (property, value) => {
618
642
  switch (property) {
619
- case 'x': this.handMesh.position.x = value; break
620
- case 'y': this.handMesh.position.y = value; break
621
- case 'z': this.handMesh.position.z = value; break
622
- case 'rotationX': this.handMesh.rotation.x = value; break
623
- case 'rotationY': this.handMesh.rotation.y = value; break
624
- case 'rotationZ': this.handMesh.rotation.z = value; break
643
+ case 'x':
644
+ this.handMesh.position.x = value
645
+ break
646
+ case 'y':
647
+ this.handMesh.position.y = value
648
+ break
649
+ case 'z':
650
+ this.handMesh.position.z = value
651
+ break
652
+ case 'rotationX':
653
+ this.handMesh.rotation.x = value
654
+ break
655
+ case 'rotationY':
656
+ this.handMesh.rotation.y = value
657
+ break
658
+ case 'rotationZ':
659
+ this.handMesh.rotation.z = value
660
+ break
625
661
  }
626
662
  },
627
663
  {
@@ -647,10 +683,13 @@ class HandIdleAnimator {
647
683
  this.idleOffset.rotationZ = this.handMesh.rotation.z - this.defaultPosition.rotationZ
648
684
 
649
685
  this.idleTween = new tweenJs.Tween(this.idleOffset, this.tween)
650
- .to({
651
- y: 0.05,
652
- rotationZ: 0.05
653
- }, 3000)
686
+ .to(
687
+ {
688
+ y: 0.05,
689
+ rotationZ: 0.05
690
+ },
691
+ 3000
692
+ )
654
693
  .easing(tweenJs.Easing.Sinusoidal.InOut)
655
694
  .yoyo(true)
656
695
  .repeat(Infinity)
@@ -748,8 +787,7 @@ class HandIdleAnimator {
748
787
  }
749
788
 
750
789
  // If we're not transitioning between states and in a stable state that should have idle animation
751
- if (!this.stateSwitcher.isTransitioning &&
752
- (this.currentState === 'NOT_MOVING' || this.currentState === 'SNEAKING')) {
790
+ if (!this.stateSwitcher.isTransitioning && (this.currentState === 'NOT_MOVING' || this.currentState === 'SNEAKING')) {
753
791
  // Start idle animation if not already running
754
792
  if (!this.idleTween?.isPlaying()) {
755
793
  this.startIdleAnimation()
@@ -763,8 +801,7 @@ class HandIdleAnimator {
763
801
  }
764
802
 
765
803
  // If we're in a movement state and not transitioning, update the movement animation
766
- if (!this.stateSwitcher.isTransitioning &&
767
- (this.currentState === 'WALKING' || this.currentState === 'SPRINTING')) {
804
+ if (!this.stateSwitcher.isTransitioning && (this.currentState === 'WALKING' || this.currentState === 'SPRINTING')) {
768
805
  const stateTransform = this.getStateTransform(this.currentState, this.globalTime)
769
806
  Object.assign(this.handMesh.position, stateTransform)
770
807
  Object.assign(this.handMesh.rotation, {
@@ -796,14 +833,14 @@ class HandSwingAnimator {
796
833
 
797
834
  readonly debugParams = {
798
835
  animationTime: 250,
799
- animationStage: 0,
836
+ animationStage: 0
800
837
  }
801
838
 
802
839
  private readonly debugGui: DebugGui
803
840
 
804
841
  constructor() {
805
842
  this.debugGui = new DebugGui('hand_animator', this.debugParams, undefined, {
806
- animationStage: { min: 0, max: 1, step: 0.01 },
843
+ animationStage: { min: 0, max: 1, step: 0.01 }
807
844
  })
808
845
  }
809
846
 
@@ -4,10 +4,7 @@ import HoldingBlockLegacy from './holdingBlockLegacy'
4
4
  import type { IHoldingBlock } from './holdingBlockTypes'
5
5
  import type { WorldRendererThree } from './worldRendererThree'
6
6
 
7
- export function createHoldingBlock(
8
- worldRenderer: WorldRendererThree,
9
- offHand: boolean = false
10
- ): IHoldingBlock {
7
+ export function createHoldingBlock(worldRenderer: WorldRendererThree, offHand: boolean = false): IHoldingBlock {
11
8
  const config = worldRenderer.displayOptions.inWorldRenderingConfig
12
9
  if (config.handRenderer === 'legacy') {
13
10
  return new HoldingBlockLegacy(worldRenderer, offHand)