minecraft-renderer 0.1.59 → 0.1.61

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minecraft-renderer",
3
- "version": "0.1.59",
3
+ "version": "0.1.61",
4
4
  "description": "The most Modular Minecraft world renderer with Three.js WebGL backend",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -10,6 +10,22 @@ export type PlayerObjectType = PlayerObject & {
10
10
  realUsername: string
11
11
  }
12
12
 
13
+ /** Starfield + log-depth world: cutout skin mats need alphaTest and depthWrite (not mesh traverse). */
14
+ export function configurePlayerSkinMaterials (playerObject: PlayerObject): void {
15
+ const skin = playerObject.skin
16
+ const materials = [
17
+ skin.layer1Material,
18
+ skin.layer1MaterialBiased,
19
+ skin.layer2Material,
20
+ skin.layer2MaterialBiased,
21
+ ]
22
+ for (const mat of materials) {
23
+ mat.transparent = true
24
+ mat.alphaTest = 0.1
25
+ mat.depthWrite = true
26
+ }
27
+ }
28
+
13
29
  export function createPlayerObject (options: {
14
30
  username?: string
15
31
  uuid?: string
@@ -25,12 +41,7 @@ export function createPlayerObject (options: {
25
41
  playerObject.realUsername = options.username ?? ''
26
42
  playerObject.position.set(0, 16, 0)
27
43
 
28
- // fix issues with starfield
29
- playerObject.traverse((obj) => {
30
- if (obj instanceof THREE.Mesh && obj.material instanceof THREE.MeshStandardMaterial) {
31
- obj.material.transparent = true
32
- }
33
- })
44
+ configurePlayerSkinMaterials(playerObject)
34
45
 
35
46
  wrapper.add(playerObject as any)
36
47
  const scale = options.scale ?? (1 / 16)
@@ -16,7 +16,7 @@ import PrismarineChatLoader from 'prismarine-chat'
16
16
  import { loadSkinFromUsername, loadSkinImage, stevePngUrl } from '../lib/utils/skins'
17
17
  import { renderComponent } from '../sign-renderer'
18
18
  import { createCanvas } from '../lib/utils'
19
- import { PlayerObjectType } from '../lib/createPlayerObject'
19
+ import { configurePlayerSkinMaterials, PlayerObjectType } from '../lib/createPlayerObject'
20
20
  import { getBlockMeshFromModel } from './holdingBlock'
21
21
  import { createItemMesh } from './itemMesh'
22
22
  import * as Entity from './entity/EntityMesh'
@@ -832,6 +832,7 @@ export class Entities {
832
832
  playerObject.skin.map = skinTexture as any
833
833
  playerObject.skin.modelType = inferModelType(skinCanvas)
834
834
  playerObject.skin['isCustom'] = skinUrl !== stevePngUrl
835
+ configurePlayerSkinMaterials(playerObject)
835
836
 
836
837
  let earsCanvas: OffscreenCanvas | undefined
837
838
  if (!playerCustomSkinImage) {
@@ -902,8 +903,13 @@ export class Entities {
902
903
  // TODO CLEANUP!
903
904
  // Handle special player entity ID for bot entity in third person
904
905
  const key = String(entityPlayerId)
905
- if (this.playerPerAnimation[key] === animation) return
906
- this.playerPerAnimation[key] = animation
906
+ // `oneSwing` is a one-shot event, not a persistent state: two swings in a row
907
+ // are both 'oneSwing', so deduping by name would swallow every repeat swing
908
+ // while standing still. Only dedupe the persistent state animations.
909
+ if (animation !== 'oneSwing') {
910
+ if (this.playerPerAnimation[key] === animation) return
911
+ this.playerPerAnimation[key] = animation
912
+ }
907
913
 
908
914
  if (entityPlayerId === 'player_entity' && this.playerEntity?.playerObject) {
909
915
  const { playerObject } = this.playerEntity
@@ -1636,12 +1642,7 @@ export class Entities {
1636
1642
  playerObject.realUsername = entity.username ?? ''
1637
1643
  playerObject.position.set(0, 16, 0)
1638
1644
 
1639
- // fix issues with starfield
1640
- playerObject.traverse((obj) => {
1641
- if (obj instanceof THREE.Mesh && obj.material instanceof THREE.MeshStandardMaterial) {
1642
- obj.material.transparent = true
1643
- }
1644
- })
1645
+ configurePlayerSkinMaterials(playerObject)
1645
1646
 
1646
1647
  wrapper.add(playerObject as any)
1647
1648
  const scale = 1 / 16
@@ -87,7 +87,13 @@ export class WalkingGeneralSwing extends PlayerAnimation {
87
87
  }
88
88
 
89
89
  swingArm() {
90
- this._swingTime = 0
90
+ // Only (re)start once we're past the halfway point of the current swing, like
91
+ // vanilla EntityLiving.swingArm. Otherwise a burst of `animation` packets
92
+ // (rapid clicks / digging) keeps resetting _swingTime and the arm never
93
+ // completes an arc, looking like a stutter of fast partial swings.
94
+ if (this._swingTime === null || this._swingTime >= this._swingDuration / 2) {
95
+ this._swingTime = 0
96
+ }
91
97
  }
92
98
 
93
99
  resetLocomotion() {
@@ -189,8 +195,6 @@ export class WalkingGeneralSwing extends PlayerAnimation {
189
195
  const crouchSpeedMul = mix(1, 0.55, crouchBlend)
190
196
  const speed = baseSpeed * crouchSpeedMul
191
197
 
192
- this._phase += dt * speed * moveBlend
193
-
194
198
  this._phase += dt * speed * moveBlend
195
199
  this._idlePhase += dt * 1.15
196
200
 
@@ -285,17 +289,22 @@ const HitAnimation = {
285
289
  animate(progress, player, isMovingOrRunning) {
286
290
  if (!player?.skin?.rightArm?.rotation) return
287
291
 
288
- const t = progress * 18
289
- player.skin.rightArm.rotation.x = -0.4537860552 * 2 + 2 * Math.sin(t + Math.PI) * 0.3
292
+ // One swing = one arc. `swing` rises to its peak at the middle of the swing
293
+ // (progress 0.5) and returns to rest at both ends, matching vanilla's
294
+ // `sin(swingProgress * PI)` and the first-person hand. Driving the trig with
295
+ // `progress * 18` previously ran ~3 sine cycles per click, which made other
296
+ // players' arms look like they were swinging several times per hit.
297
+ const swing = Math.sin(progress * Math.PI)
298
+ player.skin.rightArm.rotation.x = -0.4537860552 * 2 - 2 * swing * 0.3
290
299
 
291
300
  if (!isMovingOrRunning) {
292
301
  const basicArmRotationZ = 0.01 * Math.PI + 0.06
293
- player.skin.rightArm.rotation.z = -Math.cos(t) * 0.403 + basicArmRotationZ
294
- player.skin.body.rotation.y = -Math.cos(t) * 0.06
295
- player.skin.leftArm.rotation.x = Math.sin(t + Math.PI) * 0.077
296
- player.skin.leftArm.rotation.z = -Math.cos(t) * 0.015 + 0.13 - 0.05
297
- player.skin.leftArm.position.z = Math.cos(t) * 0.3
298
- player.skin.leftArm.position.x = 5 - Math.cos(t) * 0.05
302
+ player.skin.rightArm.rotation.z = -swing * 0.403 + basicArmRotationZ
303
+ player.skin.body.rotation.y = -swing * 0.06
304
+ player.skin.leftArm.rotation.x = -swing * 0.077
305
+ player.skin.leftArm.rotation.z = -swing * 0.015 + 0.13 - 0.05
306
+ player.skin.leftArm.position.z = swing * 0.3
307
+ player.skin.leftArm.position.x = 5 - swing * 0.05
299
308
  }
300
309
  },
301
310
  }