@@ -292,6 +292,9 @@ export class Entities {
292
292
playerObject . animation . update ( playerObject , dt )
293
293
}
294
294
295
+ // Update armor positions
296
+ this . syncArmorPositions ( entity )
297
+
295
298
// Update visibility based on distance and chunk load status
296
299
if ( botPos && entity . position ) {
297
300
const dx = entity . position . x - botPos . x
@@ -312,6 +315,79 @@ export class Entities {
312
315
}
313
316
}
314
317
318
+ private syncArmorPositions ( entity : SceneEntity ) {
319
+ if ( ! entity . playerObject ) return
320
+
321
+ // todo-low use property access for less loop iterations (small performance gain)
322
+ entity . traverse ( ( armor ) => {
323
+ if ( ! armor . name . startsWith ( 'geometry_armor_' ) ) return
324
+
325
+ const { skin } = entity . playerObject !
326
+
327
+ switch ( armor . name ) {
328
+ case 'geometry_armor_head' :
329
+ // Head armor sync
330
+ if ( armor . children [ 0 ] ?. children [ 0 ] ) {
331
+ armor . children [ 0 ] . children [ 0 ] . rotation . set (
332
+ - skin . head . rotation . x ,
333
+ skin . head . rotation . y ,
334
+ skin . head . rotation . z ,
335
+ skin . head . rotation . order
336
+ )
337
+ }
338
+ break
339
+
340
+ case 'geometry_armor_legs' :
341
+ // Legs armor sync
342
+ if ( armor . children [ 0 ] ) {
343
+ // Left leg
344
+ if ( armor . children [ 0 ] . children [ 2 ] ) {
345
+ armor . children [ 0 ] . children [ 2 ] . rotation . set (
346
+ - skin . leftLeg . rotation . x ,
347
+ skin . leftLeg . rotation . y ,
348
+ skin . leftLeg . rotation . z ,
349
+ skin . leftLeg . rotation . order
350
+ )
351
+ }
352
+ // Right leg
353
+ if ( armor . children [ 0 ] . children [ 1 ] ) {
354
+ armor . children [ 0 ] . children [ 1 ] . rotation . set (
355
+ - skin . rightLeg . rotation . x ,
356
+ skin . rightLeg . rotation . y ,
357
+ skin . rightLeg . rotation . z ,
358
+ skin . rightLeg . rotation . order
359
+ )
360
+ }
361
+ }
362
+ break
363
+
364
+ case 'geometry_armor_feet' :
365
+ // Boots armor sync
366
+ if ( armor . children [ 0 ] ) {
367
+ // Right boot
368
+ if ( armor . children [ 0 ] . children [ 0 ] ) {
369
+ armor . children [ 0 ] . children [ 0 ] . rotation . set (
370
+ - skin . rightLeg . rotation . x ,
371
+ skin . rightLeg . rotation . y ,
372
+ skin . rightLeg . rotation . z ,
373
+ skin . rightLeg . rotation . order
374
+ )
375
+ }
376
+ // Left boot (reversed Z rotation)
377
+ if ( armor . children [ 0 ] . children [ 1 ] ) {
378
+ armor . children [ 0 ] . children [ 1 ] . rotation . set (
379
+ - skin . leftLeg . rotation . x ,
380
+ skin . leftLeg . rotation . y ,
381
+ - skin . leftLeg . rotation . z ,
382
+ skin . leftLeg . rotation . order
383
+ )
384
+ }
385
+ }
386
+ break
387
+ }
388
+ } )
389
+ }
390
+
315
391
getPlayerObject ( entityId : string | number ) {
316
392
const playerObject = this . entities [ entityId ] ?. playerObject
317
393
return playerObject
@@ -1203,6 +1279,16 @@ function addArmorModel (worldRenderer: WorldRendererThree, entityMesh: THREE.Obj
1203
1279
} )
1204
1280
} else {
1205
1281
mesh = getMesh ( worldRenderer , texturePath , armorModel [ slotType ] )
1282
+ // // enable debug mode to see the mesh
1283
+ // mesh.traverse(c => {
1284
+ // if (c instanceof THREE.Mesh) {
1285
+ // c.material.wireframe = true
1286
+ // }
1287
+ // })
1288
+ if ( slotType === 'head' ) {
1289
+ // avoid z-fighting with the head
1290
+ mesh . children [ 0 ] . position . y += 0.01
1291
+ }
1206
1292
mesh . name = meshName
1207
1293
material = mesh . material
1208
1294
if ( ! isPlayerHead ) {
0 commit comments