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
@@ -47,7 +47,7 @@ const degreesToRadians = (degrees: number) => degrees * (Math.PI / 180)
47
47
 
48
48
  function convert2sComplementToHex(complement: number) {
49
49
  if (complement < 0) {
50
- complement = (0xFF_FF_FF_FF + complement + 1) >>> 0
50
+ complement = (0xff_ff_ff_ff + complement + 1) >>> 0
51
51
  }
52
52
  return complement.toString(16)
53
53
  }
@@ -104,15 +104,15 @@ const TAU_YAW = Math.PI * 2
104
104
 
105
105
  /** Prismarine yaw in radians → shortest delta from→to in (-π, π]. */
106
106
  function shortestYawRadians(fromYawRad: number, toYawRad: number): number {
107
- const norm = ((toYawRad - fromYawRad) % TAU_YAW + TAU_YAW) % TAU_YAW
107
+ const norm = (((toYawRad - fromYawRad) % TAU_YAW) + TAU_YAW) % TAU_YAW
108
108
  return norm > Math.PI ? norm - TAU_YAW : norm
109
109
  }
110
110
 
111
- function getUsernameTexture({
112
- username,
113
- nameTagBackgroundColor = 'rgba(0, 0, 0, 0.3)',
114
- nameTagTextOpacity = 255
115
- }: any, { fontFamily = 'mojangles' }: any, version: string) {
111
+ function getUsernameTexture(
112
+ { username, nameTagBackgroundColor = 'rgba(0, 0, 0, 0.3)', nameTagTextOpacity = 255 }: any,
113
+ { fontFamily = 'mojangles' }: any,
114
+ version: string
115
+ ) {
116
116
  const canvas = createCanvas(64, 64)
117
117
 
118
118
  const PrismarineChat = PrismarineChatLoader(version)
@@ -157,10 +157,7 @@ const addNametag = (entity, options: { fontFamily: string }, mesh, version: stri
157
157
  }
158
158
  if (entity.username === undefined || entity.username === null) return
159
159
 
160
- const plainUsername =
161
- typeof entity.username === 'string'
162
- ? entity.username
163
- : new (PrismarineChatLoader(version))(entity.username).toString()
160
+ const plainUsername = typeof entity.username === 'string' ? entity.username : new (PrismarineChatLoader(version))(entity.username).toString()
164
161
  if (plainUsername.startsWith('EMPTY')) return
165
162
 
166
163
  const canvas = getUsernameTexture(entity, options, version)
@@ -203,22 +200,31 @@ const addNametag = (entity, options: { fontFamily: string }, mesh, version: stri
203
200
  // todo cleanup
204
201
  const nametags = {}
205
202
 
206
- const isFirstUpperCase = (str) => str.charAt(0) === str.charAt(0).toUpperCase()
203
+ const isFirstUpperCase = str => str.charAt(0) === str.charAt(0).toUpperCase()
207
204
 
208
- function metadataAsArray (metadata: unknown): unknown[] | undefined {
205
+ function metadataAsArray(metadata: unknown): unknown[] | undefined {
209
206
  if (metadata == null) return undefined
210
207
  if (Array.isArray(metadata)) return metadata
211
208
  if (typeof metadata === 'object') {
212
209
  const record = metadata as Record<string, unknown>
213
- const keys = Object.keys(record).filter((k) => /^\d+$/.test(k)).map(Number).sort((a, b) => a - b)
210
+ const keys = Object.keys(record)
211
+ .filter(k => /^\d+$/.test(k))
212
+ .map(Number)
213
+ .sort((a, b) => a - b)
214
214
  if (keys.length && keys[0] === 0 && keys.every((k, i) => k === i)) {
215
- return keys.map((k) => record[String(k)])
215
+ return keys.map(k => record[String(k)])
216
216
  }
217
217
  }
218
218
  return undefined
219
219
  }
220
220
 
221
- function getEntityMesh(mcData: IndexedData | undefined, entity: import('prismarine-entity').Entity & { delete?: any; pos?: any; name?: any }, world: WorldRendererThree, options: { fontFamily: string }, overrides) {
221
+ function getEntityMesh(
222
+ mcData: IndexedData | undefined,
223
+ entity: import('prismarine-entity').Entity & { delete?: any; pos?: any; name?: any },
224
+ world: WorldRendererThree,
225
+ options: { fontFamily: string },
226
+ overrides
227
+ ) {
222
228
  if (entity.name) {
223
229
  try {
224
230
  // https://github.com/PrismarineJS/prismarine-viewer/pull/410
@@ -241,10 +247,15 @@ function getEntityMesh(mcData: IndexedData | undefined, entity: import('prismari
241
247
  const cube = new THREE.Mesh(geometry, material)
242
248
  const nametagCount = (nametags[entity.name] = (nametags[entity.name] || 0) + 1)
243
249
  if (nametagCount < 6) {
244
- addNametag({
245
- username: entity.name,
246
- height: entity.height,
247
- }, options, cube, world.version)
250
+ addNametag(
251
+ {
252
+ username: entity.name,
253
+ height: entity.height
254
+ },
255
+ options,
256
+ cube,
257
+ world.version
258
+ )
248
259
  }
249
260
  return cube
250
261
  }
@@ -254,7 +265,7 @@ export type SceneEntity = THREE.Object3D & {
254
265
  username?: string
255
266
  uuid?: string
256
267
  additionalCleanup?: () => void
257
- originalEntity: import('prismarine-entity').Entity & { delete?; pos?, name, team?: Team }
268
+ originalEntity: import('prismarine-entity').Entity & { delete?; pos?; name; team?: Team }
258
269
  }
259
270
 
260
271
  export class Entities {
@@ -295,9 +306,12 @@ export class Entities {
295
306
  return `${visibleEntities}/${totalEntities} ${visiblePlayerEntities.length}/${playerEntities.length}`
296
307
  }
297
308
 
298
- constructor(public worldRenderer: WorldRendererThree, public mcData?: IndexedData) {
309
+ constructor(
310
+ public worldRenderer: WorldRendererThree,
311
+ public mcData?: IndexedData
312
+ ) {
299
313
  this.debugMode = 'none'
300
- this.onSkinUpdate = () => { }
314
+ this.onSkinUpdate = () => {}
301
315
  this.watchResourcesUpdates()
302
316
  }
303
317
 
@@ -355,7 +369,7 @@ export class Entities {
355
369
  for (const entity of Object.values(this.entities)) {
356
370
  // update all entities textures like held items, armour, etc
357
371
  // todo update entity textures itself
358
- this.update({ ...entity.originalEntity, delete: true, } as SceneEntity['originalEntity'], {})
372
+ this.update({ ...entity.originalEntity, delete: true } as SceneEntity['originalEntity'], {})
359
373
  this.update(entity.originalEntity, {})
360
374
  }
361
375
  }
@@ -421,11 +435,7 @@ export class Entities {
421
435
 
422
436
  if (thirdPerson) {
423
437
  const yOffset = this.worldRenderer.playerStateReactive.eyeHeight
424
- entity.position.set(
425
- this.worldRenderer.cameraWorldPos.x,
426
- this.worldRenderer.cameraWorldPos.y - yOffset,
427
- this.worldRenderer.cameraWorldPos.z
428
- )
438
+ entity.position.set(this.worldRenderer.cameraWorldPos.x, this.worldRenderer.cameraWorldPos.y - yOffset, this.worldRenderer.cameraWorldPos.z)
429
439
  }
430
440
  }
431
441
 
@@ -460,7 +470,7 @@ export class Entities {
460
470
  const rotation = this.worldRenderer.cameraShake.getBaseRotation()
461
471
  entity.rotation.set(0, rotation.yaw, 0)
462
472
 
463
- entity.traverse((c) => {
473
+ entity.traverse(c => {
464
474
  if (c.name === 'head') {
465
475
  c.rotation.set(-rotation.pitch, 0, 0)
466
476
  }
@@ -473,7 +483,7 @@ export class Entities {
473
483
  if (!entity.playerObject) return
474
484
 
475
485
  // todo-low use property access for less loop iterations (small performance gain)
476
- entity.traverse((armor) => {
486
+ entity.traverse(armor => {
477
487
  if (!armor.name.startsWith('geometry_armor_')) return
478
488
 
479
489
  const { skin } = entity.playerObject!
@@ -482,12 +492,7 @@ export class Entities {
482
492
  case 'geometry_armor_head':
483
493
  // Head armor sync
484
494
  if (armor.children[0]?.children[0]) {
485
- armor.children[0].children[0].rotation.set(
486
- -skin.head.rotation.x,
487
- skin.head.rotation.y,
488
- skin.head.rotation.z,
489
- skin.head.rotation.order
490
- )
495
+ armor.children[0].children[0].rotation.set(-skin.head.rotation.x, skin.head.rotation.y, skin.head.rotation.z, skin.head.rotation.order)
491
496
  }
492
497
  break
493
498
 
@@ -548,19 +553,23 @@ export class Entities {
548
553
  return playerObject
549
554
  }
550
555
 
551
- uuidPerSkinUrlsCache = {} as Record<string, { skinUrl?: string, capeUrl?: string }>
556
+ uuidPerSkinUrlsCache = {} as Record<string, { skinUrl?: string; capeUrl?: string }>
552
557
  currentSkinUrls = {} as Record<string, string>
553
558
 
554
559
  private isCanvasBlank(canvas: HTMLCanvasElement | OffscreenCanvas): boolean {
555
560
  const ctx = canvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null
556
- return !ctx
557
- ?.getImageData(0, 0, canvas.width, canvas.height).data
558
- .some(channel => channel !== 0)
561
+ return !ctx?.getImageData(0, 0, canvas.width, canvas.height).data.some(channel => channel !== 0)
559
562
  }
560
563
 
561
564
  // todo true/undefined doesnt reset the skin to the default one
562
565
  // eslint-disable-next-line max-params
563
- async updatePlayerSkin(entityId: string | number, username: string | undefined, uuidCache: string | undefined, skinUrl: string | true, capeUrl: string | true | undefined = undefined) {
566
+ async updatePlayerSkin(
567
+ entityId: string | number,
568
+ username: string | undefined,
569
+ uuidCache: string | undefined,
570
+ skinUrl: string | true,
571
+ capeUrl: string | true | undefined = undefined
572
+ ) {
564
573
  const isCustomSkin = skinUrl !== stevePngUrl
565
574
  if (isCustomSkin) {
566
575
  this.loadedSkinEntityIds.add(String(entityId))
@@ -623,7 +632,6 @@ export class Entities {
623
632
  }
624
633
  })
625
634
 
626
-
627
635
  playerObject.cape.visible = false
628
636
  if (!capeUrl) {
629
637
  playerObject.backEquipment = null
@@ -636,12 +644,7 @@ export class Entities {
636
644
  }
637
645
 
638
646
  /** Local preview override: hand + player model until server skin refresh or reconnect. */
639
- async applyTemporaryPlayerSkinOverride (
640
- skinUrl: string,
641
- entityId: string | number,
642
- username?: string,
643
- uuid?: string
644
- ) {
647
+ async applyTemporaryPlayerSkinOverride(skinUrl: string, entityId: string | number, username?: string, uuid?: string) {
645
648
  this.worldRenderer.playerStateReactive.playerSkin = skinUrl
646
649
  await this.updatePlayerSkin(entityId, username, uuid, skinUrl, undefined)
647
650
  }
@@ -740,10 +743,7 @@ export class Entities {
740
743
  }
741
744
  }
742
745
 
743
- private applyMovementAnimation(
744
- playerObject: PlayerObjectType,
745
- animation: 'walking' | 'running' | 'oneSwing' | 'idle' | 'crouch' | 'crouchWalking',
746
- ): void {
746
+ private applyMovementAnimation(playerObject: PlayerObjectType, animation: 'walking' | 'running' | 'oneSwing' | 'idle' | 'crouch' | 'crouchWalking'): void {
747
747
  const anim = playerObject.animation as WalkingGeneralSwing | undefined
748
748
  if (!anim) return
749
749
 
@@ -759,9 +759,8 @@ export class Entities {
759
759
  }
760
760
 
761
761
  playAnimation(entityPlayerId, animation: 'walking' | 'running' | 'oneSwing' | 'idle' | 'crouch' | 'crouchWalking') {
762
- const playerObject = entityPlayerId === 'player_entity'
763
- ? this.playerEntity?.playerObject
764
- : this.getPlayerObject(entityPlayerId) ?? this.playerEntity?.playerObject
762
+ const playerObject =
763
+ entityPlayerId === 'player_entity' ? this.playerEntity?.playerObject : (this.getPlayerObject(entityPlayerId) ?? this.playerEntity?.playerObject)
765
764
 
766
765
  if (!playerObject) return
767
766
  this.applyMovementAnimation(playerObject, animation)
@@ -782,7 +781,7 @@ export class Entities {
782
781
  }
783
782
 
784
783
  private textFromComponent(component) {
785
- return typeof component === 'string' ? component : component.text ?? ''
784
+ return typeof component === 'string' ? component : (component.text ?? '')
786
785
  }
787
786
 
788
787
  getItemMesh(item, specificProps: ItemSpecificContextProperties, faceCamera = false, previousModel?: string) {
@@ -791,7 +790,13 @@ export class Entities {
791
790
  if (previousModel && previousModel === textureUv?.modelName) return undefined
792
791
 
793
792
  if (textureUv && 'resolvedModel' in textureUv) {
794
- const mesh = getBlockMeshFromModel(this.worldRenderer.material, textureUv.resolvedModel, textureUv.modelName, this.worldRenderer.resourcesManager.currentResources.worldBlockProvider!, this.worldRenderer.resourcesManager.currentResources.mcData!)
793
+ const mesh = getBlockMeshFromModel(
794
+ this.worldRenderer.material,
795
+ textureUv.resolvedModel,
796
+ textureUv.modelName,
797
+ this.worldRenderer.resourcesManager.currentResources.worldBlockProvider!,
798
+ this.worldRenderer.resourcesManager.currentResources.mcData!
799
+ )
795
800
  let SCALE = 1
796
801
  if (specificProps['minecraft:display_context'] === 'ground') {
797
802
  SCALE = 0.5
@@ -804,7 +809,7 @@ export class Entities {
804
809
  return {
805
810
  mesh: outerGroup,
806
811
  isBlock: true,
807
- modelName: textureUv.modelName,
812
+ modelName: textureUv.modelName
808
813
  }
809
814
  }
810
815
 
@@ -815,15 +820,19 @@ export class Entities {
815
820
  const sizeX = su ?? 1 // su is actually width
816
821
  const sizeY = sv ?? 1 // sv is actually height
817
822
 
818
- const result = createItemMesh(textureThree, {
819
- u,
820
- v,
821
- sizeX,
822
- sizeY
823
- }, {
824
- faceCamera,
825
- use3D: !faceCamera, // Only use 3D for non-camera-facing items
826
- })
823
+ const result = createItemMesh(
824
+ textureThree,
825
+ {
826
+ u,
827
+ v,
828
+ sizeX,
829
+ sizeY
830
+ },
831
+ {
832
+ faceCamera,
833
+ use3D: !faceCamera // Only use 3D for non-camera-facing items
834
+ }
835
+ )
827
836
 
828
837
  let SCALE = 1
829
838
  if (specificProps['minecraft:display_context'] === 'ground') {
@@ -887,18 +896,31 @@ export class Entities {
887
896
 
888
897
  const group = new THREE.Group() as unknown as SceneEntity
889
898
  group.originalEntity = entity
890
- if (entity.name === 'item' || entity.name === 'tnt' || entity.name === 'falling_block' || entity.name === 'snowball'
891
- || entity.name === 'egg' || entity.name === 'ender_pearl' || entity.name === 'experience_bottle'
892
- || entity.name === 'splash_potion' || entity.name === 'lingering_potion') {
893
- const item = entity.name === 'tnt' || entity.type === 'projectile'
894
- ? { name: entity.name }
895
- : entity.name === 'falling_block'
896
- ? { blockState: entity['objectData'] }
897
- : metadataAsArray(entity.metadata)?.find((m: any) => typeof m === 'object' && m?.itemCount)
899
+ if (
900
+ entity.name === 'item' ||
901
+ entity.name === 'tnt' ||
902
+ entity.name === 'falling_block' ||
903
+ entity.name === 'snowball' ||
904
+ entity.name === 'egg' ||
905
+ entity.name === 'ender_pearl' ||
906
+ entity.name === 'experience_bottle' ||
907
+ entity.name === 'splash_potion' ||
908
+ entity.name === 'lingering_potion'
909
+ ) {
910
+ const item =
911
+ entity.name === 'tnt' || entity.type === 'projectile'
912
+ ? { name: entity.name }
913
+ : entity.name === 'falling_block'
914
+ ? { blockState: entity['objectData'] }
915
+ : metadataAsArray(entity.metadata)?.find((m: any) => typeof m === 'object' && m?.itemCount)
898
916
  if (item) {
899
- const object = this.getItemMesh(item, {
900
- 'minecraft:display_context': 'ground',
901
- }, entity.type === 'projectile')
917
+ const object = this.getItemMesh(
918
+ item,
919
+ {
920
+ 'minecraft:display_context': 'ground'
921
+ },
922
+ entity.type === 'projectile'
923
+ )
902
924
  if (object) {
903
925
  mesh = object.mesh
904
926
  if (entity.name === 'item' || entity.type === 'projectile') {
@@ -954,10 +976,7 @@ export class Entities {
954
976
  // todo use width and height instead
955
977
  const boxHelper = new THREE.BoxHelper(
956
978
  mesh,
957
- entity.type === 'hostile' ? 0xff_00_00 :
958
- entity.type === 'mob' ? 0x00_ff_00 :
959
- entity.type === 'player' ? 0x00_00_ff :
960
- 0xff_a5_00,
979
+ entity.type === 'hostile' ? 0xff_00_00 : entity.type === 'mob' ? 0x00_ff_00 : entity.type === 'player' ? 0x00_00_ff : 0xff_a5_00
961
980
  )
962
981
  boxHelper.name = 'debug'
963
982
  group.add(mesh)
@@ -987,7 +1006,9 @@ export class Entities {
987
1006
  const meta = getGeneralEntitiesMetadata(entity, this.mcData)
988
1007
 
989
1008
  const meta0 = metadataAsArray(entity.metadata)?.[0] ?? (entity.metadata as { 0?: unknown } | undefined)?.[0]
990
- const isInvisible = ((meta0 ?? 0) as unknown as number) & 0x20 || (this.worldRenderer.playerStateReactive.cameraSpectatingEntity === entity.id && this.worldRenderer.playerStateUtils.isSpectator())
1009
+ const isInvisible =
1010
+ ((meta0 ?? 0) as unknown as number) & 0x20 ||
1011
+ (this.worldRenderer.playerStateReactive.cameraSpectatingEntity === entity.id && this.worldRenderer.playerStateUtils.isSpectator())
991
1012
  for (const child of mesh!.children ?? []) {
992
1013
  if (child.name !== 'nametag') {
993
1014
  child.visible = !isInvisible
@@ -1002,10 +1023,11 @@ export class Entities {
1002
1023
  }
1003
1024
  // entity specific meta
1004
1025
  const textDisplayMeta = getSpecificEntityMetadata('text_display', entity, this.mcData)
1005
- const displayTextRaw = textDisplayMeta?.text || meta.custom_name_visible && meta.custom_name
1026
+ const displayTextRaw = textDisplayMeta?.text || (meta.custom_name_visible && meta.custom_name)
1006
1027
  if (entity.name !== 'player' && displayTextRaw) {
1007
1028
  const nameTagFixed = textDisplayMeta && (textDisplayMeta.billboard_render_constraints === 'fixed' || !textDisplayMeta.billboard_render_constraints)
1008
- const nameTagBackgroundColor = (textDisplayMeta && (parseInt(textDisplayMeta.style_flags, 10) & 0x04) === 0) ? toRgba(textDisplayMeta.background_color) : undefined
1029
+ const nameTagBackgroundColor =
1030
+ textDisplayMeta && (parseInt(textDisplayMeta.style_flags, 10) & 0x04) === 0 ? toRgba(textDisplayMeta.background_color) : undefined
1009
1031
  let nameTagTextOpacity: any
1010
1032
  if (textDisplayMeta?.text_opacity) {
1011
1033
  const rawOpacity = parseInt(textDisplayMeta?.text_opacity, 10)
@@ -1013,10 +1035,15 @@ export class Entities {
1013
1035
  }
1014
1036
  addNametag(
1015
1037
  {
1016
- ...entity, username: typeof displayTextRaw === 'string' ? mojangson.simplify(mojangson.parse(displayTextRaw)) : nbt.simplify(displayTextRaw),
1017
- nameTagBackgroundColor, nameTagTextOpacity, nameTagFixed,
1018
- nameTagScale: textDisplayMeta?.scale, nameTagTranslation: textDisplayMeta && (textDisplayMeta.translation || new THREE.Vector3(0, 0, 0)),
1019
- nameTagRotationLeft: toQuaternion(textDisplayMeta?.left_rotation), nameTagRotationRight: toQuaternion(textDisplayMeta?.right_rotation)
1038
+ ...entity,
1039
+ username: typeof displayTextRaw === 'string' ? mojangson.simplify(mojangson.parse(displayTextRaw)) : nbt.simplify(displayTextRaw),
1040
+ nameTagBackgroundColor,
1041
+ nameTagTextOpacity,
1042
+ nameTagFixed,
1043
+ nameTagScale: textDisplayMeta?.scale,
1044
+ nameTagTranslation: textDisplayMeta && (textDisplayMeta.translation || new THREE.Vector3(0, 0, 0)),
1045
+ nameTagRotationLeft: toQuaternion(textDisplayMeta?.left_rotation),
1046
+ nameTagRotationRight: toQuaternion(textDisplayMeta?.right_rotation)
1020
1047
  },
1021
1048
  this.entitiesOptions,
1022
1049
  mesh,
@@ -1060,7 +1087,7 @@ export class Entities {
1060
1087
  if (armorStandMeta.left_arm_pose) {
1061
1088
  c.setRotationFromEuler(poseToEuler(armorStandMeta.left_arm_pose))
1062
1089
  } else {
1063
- c.setRotationFromEuler(poseToEuler({ 'yaw': -10, 'pitch': -10, 'roll': 0 }))
1090
+ c.setRotationFromEuler(poseToEuler({ yaw: -10, pitch: -10, roll: 0 }))
1064
1091
  }
1065
1092
  break
1066
1093
  case 'bone_leftarm':
@@ -1070,21 +1097,21 @@ export class Entities {
1070
1097
  if (armorStandMeta.right_arm_pose) {
1071
1098
  c.setRotationFromEuler(poseToEuler(armorStandMeta.right_arm_pose))
1072
1099
  } else {
1073
- c.setRotationFromEuler(poseToEuler({ 'yaw': 10, 'pitch': -10, 'roll': 0 }))
1100
+ c.setRotationFromEuler(poseToEuler({ yaw: 10, pitch: -10, roll: 0 }))
1074
1101
  }
1075
1102
  break
1076
1103
  case 'bone_rightleg':
1077
1104
  if (armorStandMeta.left_leg_pose) {
1078
1105
  c.setRotationFromEuler(poseToEuler(armorStandMeta.left_leg_pose))
1079
1106
  } else {
1080
- c.setRotationFromEuler(poseToEuler({ 'yaw': -1, 'pitch': -1, 'roll': 0 }))
1107
+ c.setRotationFromEuler(poseToEuler({ yaw: -1, pitch: -1, roll: 0 }))
1081
1108
  }
1082
1109
  break
1083
1110
  case 'bone_leftleg':
1084
1111
  if (armorStandMeta.right_leg_pose) {
1085
1112
  c.setRotationFromEuler(poseToEuler(armorStandMeta.right_leg_pose))
1086
1113
  } else {
1087
- c.setRotationFromEuler(poseToEuler({ 'yaw': 1, 'pitch': 1, 'roll': 0 }))
1114
+ c.setRotationFromEuler(poseToEuler({ yaw: 1, pitch: 1, roll: 0 }))
1088
1115
  }
1089
1116
  break
1090
1117
  }
@@ -1099,26 +1126,28 @@ export class Entities {
1099
1126
  if (itemFrameMeta) {
1100
1127
  // TODO: fix type
1101
1128
  // todo! fix errors in mc-data (no entities data prior 1.18.2)
1102
- const item = (itemFrameMeta?.item ?? entity.metadata?.[8]) as any as { itemId, blockId, components, nbtData: { value: { map: { value: number } } } }
1129
+ const item = (itemFrameMeta?.item ?? entity.metadata?.[8]) as any as { itemId; blockId; components; nbtData: { value: { map: { value: number } } } }
1103
1130
  mesh!.scale.set(1, 1, 1)
1104
1131
  mesh!.position.set(0, 0, -0.5)
1105
1132
 
1106
1133
  e.rotation.x = -entity.pitch
1107
- e.children.find(c => {
1108
- if (c.name.startsWith('map_')) {
1109
- disposeObject(c)
1110
- const existingMapNumber = parseInt(c.name.split('_')[1], 10)
1111
- this.itemFrameMaps[existingMapNumber] = this.itemFrameMaps[existingMapNumber]?.filter(mesh => mesh !== c)
1112
- if (c instanceof THREE.Mesh) {
1113
- c.material?.map?.dispose()
1134
+ e.children
1135
+ .find(c => {
1136
+ if (c.name.startsWith('map_')) {
1137
+ disposeObject(c)
1138
+ const existingMapNumber = parseInt(c.name.split('_')[1], 10)
1139
+ this.itemFrameMaps[existingMapNumber] = this.itemFrameMaps[existingMapNumber]?.filter(mesh => mesh !== c)
1140
+ if (c instanceof THREE.Mesh) {
1141
+ c.material?.map?.dispose()
1142
+ }
1143
+ return true
1144
+ } else if (c.name === 'item') {
1145
+ disposeObject(c)
1146
+ return true
1114
1147
  }
1115
- return true
1116
- } else if (c.name === 'item') {
1117
- disposeObject(c)
1118
- return true
1119
- }
1120
- return false
1121
- })?.removeFromParent()
1148
+ return false
1149
+ })
1150
+ ?.removeFromParent()
1122
1151
 
1123
1152
  if (item && (item.itemId ?? item.blockId ?? 0) !== 0) {
1124
1153
  // Get rotation from metadata, default to 0 if not present
@@ -1133,7 +1162,7 @@ export class Entities {
1133
1162
  } else {
1134
1163
  // Handle regular item rotation (8 possibilities, 45° increments)
1135
1164
  const itemMesh = this.getItemMesh(item, {
1136
- 'minecraft:display_context': 'fixed',
1165
+ 'minecraft:display_context': 'fixed'
1137
1166
  })
1138
1167
  if (itemMesh) {
1139
1168
  itemMesh.mesh.position.set(0, 0, -0.05)
@@ -1145,7 +1174,7 @@ export class Entities {
1145
1174
  // Rotate 180° around Y axis first
1146
1175
  itemMesh.mesh.rotateY(Math.PI)
1147
1176
  // Then apply the 45° increment rotation
1148
- itemMesh.mesh.rotateZ(-rotation * Math.PI / 4)
1177
+ itemMesh.mesh.rotateZ((-rotation * Math.PI) / 4)
1149
1178
  itemMesh.mesh.name = 'item'
1150
1179
  e.add(itemMesh.mesh)
1151
1180
  }
@@ -1162,7 +1191,7 @@ export class Entities {
1162
1191
  this.updateEntityPosition(entity, justAdded, overrides)
1163
1192
  }
1164
1193
 
1165
- updateEntityPosition(entity: import('prismarine-entity').Entity, justAdded: boolean, overrides: { rotation?: { head?: { y: number, x: number } } }) {
1194
+ updateEntityPosition(entity: import('prismarine-entity').Entity, justAdded: boolean, overrides: { rotation?: { head?: { y: number; x: number } } }) {
1166
1195
  const e = this.entities[entity.id]
1167
1196
  if (!e) return
1168
1197
  const ANIMATION_DURATION = justAdded ? 0 : TWEEN_DURATION
@@ -1186,8 +1215,7 @@ export class Entities {
1186
1215
  let targetYaw: number | undefined
1187
1216
  if (e.playerObject && overrides?.rotation?.head) {
1188
1217
  const hy = overrides.rotation.head.y
1189
- const headYawWorld =
1190
- typeof hy === 'number' && Number.isFinite(hy) ? hy : entity.yaw
1218
+ const headYawWorld = typeof hy === 'number' && Number.isFinite(hy) ? hy : entity.yaw
1191
1219
  if (typeof headYawWorld === 'number' && Number.isFinite(headYawWorld)) {
1192
1220
  targetYaw = headYawWorld
1193
1221
  }
@@ -1198,9 +1226,7 @@ export class Entities {
1198
1226
  const dy = shortestYawRadians(e.rotation.y, targetYaw)
1199
1227
  // Stop previous rotation tween to prevent accumulation (mirror _posTween)
1200
1228
  e.userData._rotTween?.stop()
1201
- e.userData._rotTween = new TWEEN.Tween(e.rotation)
1202
- .to({ y: e.rotation.y + dy }, ANIMATION_DURATION)
1203
- .start()
1229
+ e.userData._rotTween = new TWEEN.Tween(e.rotation).to({ y: e.rotation.y + dy }, ANIMATION_DURATION).start()
1204
1230
  }
1205
1231
 
1206
1232
  if (e?.playerObject && overrides?.rotation?.head) {
@@ -1208,13 +1234,11 @@ export class Entities {
1208
1234
  playerObject.skin.head.rotation.y = 0
1209
1235
 
1210
1236
  const hp = overrides.rotation.head.x
1211
- playerObject.skin.head.rotation.x =
1212
- typeof hp === 'number' && Number.isFinite(hp) ? -hp : 0
1237
+ playerObject.skin.head.rotation.x = typeof hp === 'number' && Number.isFinite(hp) ? -hp : 0
1213
1238
  }
1214
1239
  }
1215
1240
 
1216
- afterAddEntity(entity: import('prismarine-entity').Entity) {
1217
- }
1241
+ afterAddEntity(entity: import('prismarine-entity').Entity) {}
1218
1242
 
1219
1243
  beforeEntityAdded(entity: import('prismarine-entity').Entity) {
1220
1244
  const override = this.pendingModelOverrides.get(entity.id.toString())
@@ -1244,7 +1268,7 @@ export class Entities {
1244
1268
  ? new THREE.Vector3(wp.x, wp.y, wp.z)
1245
1269
  : mesh.position.clone().add(new THREE.Vector3(this.worldRenderer.sceneOrigin.x, this.worldRenderer.sceneOrigin.y, this.worldRenderer.sceneOrigin.z))
1246
1270
  const distance = entityWorldPos.distanceTo(cameraPos)
1247
- if (distance < MAX_DISTANCE_SKIN_LOAD && distance < (this.worldRenderer.viewDistance * 16)) {
1271
+ if (distance < MAX_DISTANCE_SKIN_LOAD && distance < this.worldRenderer.viewDistance * 16) {
1248
1272
  if (this.loadedSkinEntityIds.has(String(entityId))) return
1249
1273
  void this.updatePlayerSkin(entityId, mesh.playerObject.realUsername, mesh.playerObject.realPlayerUuid, true, true)
1250
1274
  }
@@ -1274,7 +1298,8 @@ export class Entities {
1274
1298
  const playerTeam = this.worldRenderer.playerStateReactive.team
1275
1299
  const entityTeam = entity.originalEntity.team
1276
1300
  const nameTagVisibility = entityTeam?.nameTagVisibility || 'always'
1277
- const showNameTag = nameTagVisibility === 'always' ||
1301
+ const showNameTag =
1302
+ nameTagVisibility === 'always' ||
1278
1303
  (nameTagVisibility === 'hideForOwnTeam' && entityTeam?.team !== playerTeam?.team) ||
1279
1304
  (nameTagVisibility === 'hideForOtherTeams' && (entityTeam?.team === playerTeam?.team || playerTeam === undefined))
1280
1305
  entity.traverse(c => {
@@ -1292,7 +1317,7 @@ export class Entities {
1292
1317
  }
1293
1318
  const parameters = {
1294
1319
  transparent: true,
1295
- alphaTest: 0.1,
1320
+ alphaTest: 0.1
1296
1321
  }
1297
1322
  if (texture) {
1298
1323
  parameters['map'] = texture
@@ -1315,7 +1340,7 @@ export class Entities {
1315
1340
  mapMesh.position.set(0, 0, 0.437)
1316
1341
  }
1317
1342
  // Apply 90° increment rotation for maps (0-3)
1318
- mapMesh.rotateZ(Math.PI * 2 - rotation * Math.PI / 2)
1343
+ mapMesh.rotateZ(Math.PI * 2 - (rotation * Math.PI) / 2)
1319
1344
  mapMesh.name = `map_${mapNumber}`
1320
1345
 
1321
1346
  if (!texture) {
@@ -1348,7 +1373,7 @@ export class Entities {
1348
1373
  if (!item) return
1349
1374
 
1350
1375
  const itemObject = this.getItemMesh(item, {
1351
- 'minecraft:display_context': 'thirdperson',
1376
+ 'minecraft:display_context': 'thirdperson'
1352
1377
  })
1353
1378
  if (itemObject?.mesh) {
1354
1379
  entityMesh.traverse(c => {
@@ -1390,16 +1415,14 @@ export class Entities {
1390
1415
  handleDamageEvent(entityId, damageAmount) {
1391
1416
  const entityMesh = this.entities[entityId]?.children.find(c => c.name === 'mesh')
1392
1417
  if (entityMesh) {
1393
- entityMesh.traverse((child) => {
1418
+ entityMesh.traverse(child => {
1394
1419
  if (child instanceof THREE.Mesh && child.material.clone) {
1395
1420
  const clonedMaterial = child.material.clone()
1396
1421
  clonedMaterial.dispose()
1397
1422
  child.material = child.material.clone()
1398
1423
  const originalColor = child.material.color.clone()
1399
1424
  child.material.color.set(0xff_00_00)
1400
- new TWEEN.Tween(child.material.color)
1401
- .to(originalColor, 500)
1402
- .start()
1425
+ new TWEEN.Tween(child.material.color).to(originalColor, 500).start()
1403
1426
  }
1404
1427
  })
1405
1428
  }
@@ -1413,12 +1436,7 @@ export class Entities {
1413
1436
  return intersects[0]?.object
1414
1437
  }
1415
1438
 
1416
- updateEntityModel(
1417
- entityId: string,
1418
- modelPathOrParts: string | EntityModelOverridePart[],
1419
- modelType?: Entity.EntityModelType,
1420
- metadata?: any
1421
- ) {
1439
+ updateEntityModel(entityId: string, modelPathOrParts: string | EntityModelOverridePart[], modelType?: Entity.EntityModelType, metadata?: any) {
1422
1440
  const parts: EntityModelOverridePart[] = Array.isArray(modelPathOrParts)
1423
1441
  ? modelPathOrParts
1424
1442
  : [{ modelPath: modelPathOrParts, modelType: modelType!, metadata }]
@@ -1468,7 +1486,7 @@ export class Entities {
1468
1486
  // Update player-specific equipment
1469
1487
  if (isPlayer && entityMesh.playerObject) {
1470
1488
  const { playerObject } = entityMesh
1471
- playerObject.backEquipment = entity.equipment.some((item) => item?.name === 'elytra') ? 'elytra' : 'cape'
1489
+ playerObject.backEquipment = entity.equipment.some(item => item?.name === 'elytra') ? 'elytra' : 'cape'
1472
1490
  if (playerObject.backEquipment === 'elytra') {
1473
1491
  void this.loadAndApplyCape(entity.id, elytraTexture)
1474
1492
  }
@@ -1479,15 +1497,21 @@ export class Entities {
1479
1497
  }
1480
1498
  }
1481
1499
 
1482
- function getGeneralEntitiesMetadata(entity: { name; metadata }, mcData?: IndexedData): Partial<UnionToIntersection<EntityMetadataVersions[keyof EntityMetadataVersions]>> {
1500
+ function getGeneralEntitiesMetadata(
1501
+ entity: { name; metadata },
1502
+ mcData?: IndexedData
1503
+ ): Partial<UnionToIntersection<EntityMetadataVersions[keyof EntityMetadataVersions]>> {
1483
1504
  const entityData = mcData?.entitiesByName[entity.name]
1484
- return new Proxy({}, {
1485
- get(target, p, receiver) {
1486
- if (typeof p !== 'string' || !entityData) return
1487
- const index = entityData.metadataKeys?.indexOf(p)
1488
- return entity.metadata?.[index ?? -1]
1489
- },
1490
- })
1505
+ return new Proxy(
1506
+ {},
1507
+ {
1508
+ get(target, p, receiver) {
1509
+ if (typeof p !== 'string' || !entityData) return
1510
+ const index = entityData.metadataKeys?.indexOf(p)
1511
+ return entity.metadata?.[index ?? -1]
1512
+ }
1513
+ }
1514
+ )
1491
1515
  }
1492
1516
 
1493
1517
  function getSpecificEntityMetadata<T extends keyof EntityMetadataVersions>(name: T, entity, mcData?: IndexedData): EntityMetadataVersions[T] | undefined {
@@ -1519,7 +1543,8 @@ function addArmorModel(worldRenderer: WorldRendererThree, entityMesh: THREE.Obje
1519
1543
  texturePath = decodedData.textures?.SKIN?.url
1520
1544
  const { skinTexturesProxy } = worldRenderer.worldRendererConfig
1521
1545
  if (skinTexturesProxy) {
1522
- texturePath = texturePath?.replace('http://textures.minecraft.net/', skinTexturesProxy)
1546
+ texturePath = texturePath
1547
+ ?.replace('http://textures.minecraft.net/', skinTexturesProxy)
1523
1548
  .replace('https://textures.minecraft.net/', skinTexturesProxy)
1524
1549
  }
1525
1550
  }
@@ -1569,16 +1594,16 @@ function addArmorModel(worldRenderer: WorldRendererThree, entityMesh: THREE.Obje
1569
1594
  if (armorMaterial === 'leather' && !overlay) {
1570
1595
  const color = (item.nbt?.value as any)?.display?.value?.color?.value
1571
1596
  if (color) {
1572
- const r = color >> 16 & 0xff
1573
- const g = color >> 8 & 0xff
1597
+ const r = (color >> 16) & 0xff
1598
+ const g = (color >> 8) & 0xff
1574
1599
  const b = color & 0xff
1575
1600
  material.color.setRGB(r / 255, g / 255, b / 255)
1576
1601
  } else {
1577
- material.color.setHex(0xB5_6D_51) // default brown color
1602
+ material.color.setHex(0xb5_6d_51) // default brown color
1578
1603
  }
1579
1604
  addArmorModel(worldRenderer, entityMesh, slotType, item, layer, true)
1580
1605
  } else {
1581
- material.color.setHex(0xFF_FF_FF)
1606
+ material.color.setHex(0xff_ff_ff)
1582
1607
  }
1583
1608
  const group = new THREE.Object3D()
1584
1609
  group.name = `armor_${slotType}${overlay ? '_overlay' : ''}`