prismarine-physics 1.9.0 → 1.11.0

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.
@@ -13,7 +13,7 @@ jobs:
13
13
 
14
14
  strategy:
15
15
  matrix:
16
- node-version: [18.x]
16
+ node-version: [24.x]
17
17
 
18
18
  steps:
19
19
  - uses: actions/checkout@v2
@@ -3,6 +3,9 @@ on:
3
3
  push:
4
4
  branches:
5
5
  - master # Change this to your default branch
6
+ permissions:
7
+ id-token: write
8
+ contents: write
6
9
  jobs:
7
10
  npm-publish:
8
11
  name: npm-publish
@@ -13,13 +16,12 @@ jobs:
13
16
  - name: Set up Node.js
14
17
  uses: actions/setup-node@master
15
18
  with:
16
- node-version: 18.0.0
19
+ node-version: 24
20
+ registry-url: 'https://registry.npmjs.org'
17
21
  - id: publish
18
- uses: JS-DevTools/npm-publish@v1
19
- with:
20
- token: ${{ secrets.NPM_AUTH_TOKEN }}
22
+ uses: JS-DevTools/npm-publish@v4
21
23
  - name: Create Release
22
- if: steps.publish.outputs.type != 'none'
24
+ if: ${{ steps.publish.outputs.type }}
23
25
  id: create_release
24
26
  uses: actions/create-release@v1
25
27
  env:
package/HISTORY.md CHANGED
@@ -1,5 +1,18 @@
1
1
  ## History
2
2
 
3
+ ### 1.11.0
4
+ * [Update CI to Node 24 (#129)](https://github.com/PrismarineJS/prismarine-physics/commit/7be0b38f547f186d41fc9cda8841cacf8f2fd80a) (thanks @rom1504)
5
+ * [Fix incorrect elytra physics (#123)](https://github.com/PrismarineJS/prismarine-physics/commit/be7f91bb4ec85e1b1f4ccfa1a33607e9cdfdf92c) (thanks @BossFlea)
6
+ * [fix: add scaffolding to climbable blocks and 1.21 to climbUsingJump (#126)](https://github.com/PrismarineJS/prismarine-physics/commit/06543978564247457c6ac3255c666d64a99c4de4) (thanks @jerry1091)
7
+ * [Fix publish condition for npm-publish v4 (#128)](https://github.com/PrismarineJS/prismarine-physics/commit/45d7e992c58e0f60c18eee633adad783c3e64e0f) (thanks @rom1504)
8
+ * [Switch to trusted publishing via OIDC (#127)](https://github.com/PrismarineJS/prismarine-physics/commit/f34e1d48ece5329d443c58624e2fb55ba3d5cc03) (thanks @rom1504)
9
+ * [node 22 (#122)](https://github.com/PrismarineJS/prismarine-physics/commit/37d8d0b612de347b2e132e270642fec108d4f2ec) (thanks @rom1504)
10
+
11
+ ### 1.10.0
12
+ * [Fix `.isOnLadder()` condition (#111)](https://github.com/PrismarineJS/prismarine-physics/commit/03b2e447b7f867257b8e50170439be8ca8e51743) (thanks @szdytom)
13
+ * [Bump mocha from 10.8.2 to 11.0.1 (#119)](https://github.com/PrismarineJS/prismarine-physics/commit/4a1d37c91915522d824b2d4170fce135926ce6e5) (thanks @dependabot[bot])
14
+ * [Use new block.isWaterlogged over reading block properties (#120)](https://github.com/PrismarineJS/prismarine-physics/commit/5cbba64ec457c6b5fa18002e57b87c8c584abb94) (thanks @extremeheat)
15
+
3
16
  ### 1.9.0
4
17
  * [add 1.21 to proportionalliquidgravity setting (#117)](https://github.com/PrismarineJS/prismarine-physics/commit/4986c8e395773e770d461db06bce38f9faed0757) (thanks @Madlykeanu)
5
18
 
package/index.js CHANGED
@@ -34,6 +34,22 @@ function Physics (mcData, world) {
34
34
  const lavaIds = [blocksByName.lava.id, blocksByName.flowing_lava ? blocksByName.flowing_lava.id : -1]
35
35
  const ladderId = blocksByName.ladder.id
36
36
  const vineId = blocksByName.vine.id
37
+ const scaffoldingId = blocksByName.scaffolding ? blocksByName.scaffolding.id : -1 // 1.14+
38
+
39
+ // NOTE: Copper trapdoors is coming in 1.21.
40
+ const trapdoorIds = new Set()
41
+ if (blocksByName.iron_trapdoor) { trapdoorIds.add(blocksByName.iron_trapdoor.id) } // 1.8+
42
+ if (blocksByName.acacia_trapdoor) { trapdoorIds.add(blocksByName.acacia_trapdoor.id) } // 1.13+
43
+ if (blocksByName.birch_trapdoor) { trapdoorIds.add(blocksByName.birch_trapdoor.id) } // 1.13+
44
+ if (blocksByName.jungle_trapdoor) { trapdoorIds.add(blocksByName.jungle_trapdoor.id) } // 1.13+
45
+ if (blocksByName.oak_trapdoor) { trapdoorIds.add(blocksByName.oak_trapdoor.id) } // 1.13+
46
+ if (blocksByName.dark_oak_trapdoor) { trapdoorIds.add(blocksByName.dark_oak_trapdoor.id) } // 1.13+
47
+ if (blocksByName.spruce_trapdoor) { trapdoorIds.add(blocksByName.spruce_trapdoor.id) } // 1.13+
48
+ if (blocksByName.crimson_trapdoor) { trapdoorIds.add(blocksByName.crimson_trapdoor.id) } // 1.16+
49
+ if (blocksByName.warped_trapdoor) { trapdoorIds.add(blocksByName.warped_trapdoor.id) } // 1.16+
50
+ if (blocksByName.mangrove_trapdoor) { trapdoorIds.add(blocksByName.mangrove_trapdoor.id) } // 1.19+
51
+ if (blocksByName.cherry_trapdoor) { trapdoorIds.add(blocksByName.cherry_trapdoor.id) } // 1.20+
52
+
37
53
  const waterLike = new Set()
38
54
  if (blocksByName.seagrass) waterLike.add(blocksByName.seagrass.id) // 1.13+
39
55
  if (blocksByName.tall_seagrass) waterLike.add(blocksByName.tall_seagrass.id) // 1.13+
@@ -419,9 +435,27 @@ function Physics (mcData, world) {
419
435
  vel.z += forward * cos - strafe * sin
420
436
  }
421
437
 
438
+ const climbableTrapdoorFeature = supportFeature('climbableTrapdoor')
422
439
  function isOnLadder (world, pos) {
423
440
  const block = world.getBlock(pos)
424
- return (block && (block.type === ladderId || block.type === vineId))
441
+ if (!block) { return false }
442
+ if (block.type === ladderId || block.type === vineId) { return true }
443
+ if (scaffoldingId !== -1 && block.type === scaffoldingId) { return true }
444
+
445
+ // Since 1.9, when a trapdoor satisfies the following conditions, it also becomes climbable:
446
+ // 1. The trapdoor is placed directly above a ladder.
447
+ // 2. The trapdoor is opened.
448
+ // 3. The trapdoor and the ladder directly below it face the same direction.
449
+ if (climbableTrapdoorFeature && trapdoorIds.has(block.type)) {
450
+ const blockBelow = world.getBlock(pos.offset(0, -1, 0))
451
+ if (blockBelow.type !== ladderId) { return false } // condition 1.
452
+ const blockProperties = block._properties
453
+ if (!blockProperties.open) { return false } // condition 2.
454
+ if (blockProperties.facing !== blockBelow.getProperties().facing) { return false } // condition 3
455
+ return true
456
+ }
457
+
458
+ return false
425
459
  }
426
460
 
427
461
  function doesNotCollide (world, pos) {
@@ -484,8 +518,8 @@ function Physics (mcData, world) {
484
518
  vel.z += lookDir.z * movingDownSpeedModifier / cosPitch
485
519
  }
486
520
 
487
- if (pitch < 0.0 && cosPitch > 0.0) {
488
- const lookDownSpeedModifier = horizontalSpeed * (-sinPitch) * 0.04
521
+ if (pitch > 0.0 && cosPitch > 0.0) {
522
+ const lookDownSpeedModifier = horizontalSpeed * sinPitch * 0.04
489
523
  vel.x += -lookDir.x * lookDownSpeedModifier / cosPitch
490
524
  vel.y += lookDownSpeedModifier * 3.2
491
525
  vel.z += -lookDir.z * lookDownSpeedModifier / cosPitch
@@ -592,7 +626,7 @@ function Physics (mcData, world) {
592
626
  function getRenderedDepth (block) {
593
627
  if (!block) return -1
594
628
  if (waterLike.has(block.type)) return 0
595
- if (block.getProperties().waterlogged) return 0
629
+ if (block.isWaterlogged) return 0
596
630
  if (!waterIds.includes(block.type)) return -1
597
631
  const meta = block.metadata
598
632
  return meta >= 8 ? 0 : meta
@@ -640,7 +674,7 @@ function Physics (mcData, world) {
640
674
  for (cursor.z = Math.floor(bb.minZ); cursor.z <= Math.floor(bb.maxZ); cursor.z++) {
641
675
  for (cursor.x = Math.floor(bb.minX); cursor.x <= Math.floor(bb.maxX); cursor.x++) {
642
676
  const block = world.getBlock(cursor)
643
- if (block && (waterIds.includes(block.type) || waterLike.has(block.type) || block.getProperties().waterlogged)) {
677
+ if (block && (waterIds.includes(block.type) || waterLike.has(block.type) || block.isWaterlogged)) {
644
678
  const waterLevel = cursor.y + 1 - getLiquidHeightPcent(block)
645
679
  if (Math.ceil(bb.maxY) >= waterLevel) waterBlocks.push(block)
646
680
  }
package/lib/features.json CHANGED
@@ -17,11 +17,16 @@
17
17
  {
18
18
  "name": "velocityBlocksOnTop",
19
19
  "description": "Velocity changes are caused by the block the player is standing on",
20
- "versions": ["1.15", "1.17", "1.18"]
20
+ "versions": ["1.15", "1.16", "1.17", "1.18", "1.19", "1.20"]
21
21
  },
22
22
  {
23
23
  "name": "climbUsingJump",
24
24
  "description": "Entity can climb ladders and vines by pressing jump",
25
- "versions": ["1.14", "1.15", "1.17", "1.18"]
25
+ "versions": ["1.14", "1.15", "1.16", "1.17", "1.18", "1.19", "1.20", "1.21"]
26
+ },
27
+ {
28
+ "name": "climbableTrapdoor",
29
+ "description": "Trapdoors placed directly above ladders become climbable",
30
+ "versions": ["1.9", "1.10", "1.11", "1.12", "1.13", "1.14", "1.15", "1.16", "1.17", "1.18", "1.19", "1.20"]
26
31
  }
27
32
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prismarine-physics",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "description": "Provide the physics engine for minecraft entities",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -29,7 +29,7 @@
29
29
  "homepage": "https://github.com/PrismarineJS/prismarine-physics#readme",
30
30
  "devDependencies": {
31
31
  "expect": "^27.3.1",
32
- "mocha": "^10.0.0",
32
+ "mocha": "^11.0.1",
33
33
  "prismarine-block": "^1.7.3",
34
34
  "prismarine-physics": "file:./",
35
35
  "standard": "^17.0.0"
@@ -490,8 +490,8 @@ describe('Elytra tests', () => {
490
490
  expect(webPlayer.entity.position.y).toBeGreaterThan(149)
491
491
 
492
492
  // elytra player should be far away and much lower
493
- expect(airPlayer.entity.position.x).toBeGreaterThan(200)
494
- expect(airPlayer.entity.position.y).toBeLessThan(110)
493
+ expect(airPlayer.entity.position.x).toBeGreaterThan(60)
494
+ expect(airPlayer.entity.position.y).toBeLessThan(135)
495
495
  })
496
496
 
497
497
  it('can hit a wall', () => {
@@ -0,0 +1,152 @@
1
+ /* eslint-env mocha */
2
+
3
+ const { Physics, PlayerState } = require('prismarine-physics')
4
+ const { Vec3 } = require('vec3')
5
+ const expect = require('expect')
6
+ const features = require('../lib/features.json')
7
+
8
+ describe('Scaffolding climbable and climbUsingJump feature', () => {
9
+ describe('features.json', () => {
10
+ it('climbUsingJump should include version 1.21', () => {
11
+ const climbUsingJump = features.find(f => f.name === 'climbUsingJump')
12
+ expect(climbUsingJump).toBeTruthy()
13
+ expect(climbUsingJump.versions).toContain('1.21')
14
+ })
15
+
16
+ it('climbUsingJump should include versions 1.14 through 1.21', () => {
17
+ const climbUsingJump = features.find(f => f.name === 'climbUsingJump')
18
+ for (const v of ['1.14', '1.15', '1.16', '1.17', '1.18', '1.19', '1.20', '1.21']) {
19
+ expect(climbUsingJump.versions).toContain(v)
20
+ }
21
+ })
22
+ })
23
+
24
+ describe('Scaffolding is climbable for versions >= 1.14', () => {
25
+ for (const version of ['1.14.4', '1.16.5', '1.21']) {
26
+ it(`should treat scaffolding as climbable in ${version}`, () => {
27
+ const mcData = require('minecraft-data')(version)
28
+ const Block = require('prismarine-block')(version)
29
+
30
+ const scaffoldingId = mcData.blocksByName.scaffolding.id
31
+ const stoneId = mcData.blocksByName.stone.id
32
+ const airId = mcData.blocksByName.air.id
33
+
34
+ // World: stone below y=60, scaffolding at y=61, air elsewhere
35
+ const fakeWorld = {
36
+ getBlock: (pos) => {
37
+ let type
38
+ if (pos.y < 60) {
39
+ type = stoneId
40
+ } else if (pos.y === 61 && pos.x === 0 && pos.z === 0) {
41
+ type = scaffoldingId
42
+ } else {
43
+ type = airId
44
+ }
45
+ const b = new Block(type, 0, 0)
46
+ b.position = pos
47
+ return b
48
+ }
49
+ }
50
+
51
+ const physics = Physics(mcData, fakeWorld)
52
+ const controls = {
53
+ forward: false,
54
+ back: false,
55
+ left: false,
56
+ right: false,
57
+ jump: true,
58
+ sprint: false,
59
+ sneak: false
60
+ }
61
+
62
+ const player = {
63
+ entity: {
64
+ position: new Vec3(0, 61, 0),
65
+ velocity: new Vec3(0, 0, 0),
66
+ onGround: false,
67
+ isInWater: false,
68
+ isInLava: false,
69
+ isInWeb: false,
70
+ isCollidedHorizontally: false,
71
+ isCollidedVertically: false,
72
+ elytraFlying: false,
73
+ yaw: 0,
74
+ pitch: 0,
75
+ effects: {}
76
+ },
77
+ jumpTicks: 0,
78
+ jumpQueued: false,
79
+ fireworkRocketDuration: 0,
80
+ version,
81
+ inventory: {
82
+ slots: []
83
+ }
84
+ }
85
+
86
+ const playerState = new PlayerState(player, controls)
87
+ physics.simulatePlayer(playerState, fakeWorld).apply(player)
88
+
89
+ // When on scaffolding with jump pressed, the player should climb
90
+ // (velocity.y should be positive, equal to ladderClimbSpeed)
91
+ expect(player.entity.velocity.y).toBeGreaterThan(0)
92
+ })
93
+ }
94
+ })
95
+
96
+ describe('Scaffolding does not exist pre-1.14', () => {
97
+ it('should not crash when scaffolding block does not exist (1.13.2)', () => {
98
+ const mcData = require('minecraft-data')('1.13.2')
99
+ const Block = require('prismarine-block')('1.13.2')
100
+
101
+ expect(mcData.blocksByName.scaffolding).toBeFalsy()
102
+
103
+ const fakeWorld = {
104
+ getBlock: (pos) => {
105
+ const type = (pos.y < 60) ? mcData.blocksByName.stone.id : mcData.blocksByName.air.id
106
+ const b = new Block(type, 0, 0)
107
+ b.position = pos
108
+ return b
109
+ }
110
+ }
111
+
112
+ // Should not throw
113
+ const physics = Physics(mcData, fakeWorld)
114
+ const controls = {
115
+ forward: false,
116
+ back: false,
117
+ left: false,
118
+ right: false,
119
+ jump: false,
120
+ sprint: false,
121
+ sneak: false
122
+ }
123
+
124
+ const player = {
125
+ entity: {
126
+ position: new Vec3(0, 80, 0),
127
+ velocity: new Vec3(0, 0, 0),
128
+ onGround: false,
129
+ isInWater: false,
130
+ isInLava: false,
131
+ isInWeb: false,
132
+ isCollidedHorizontally: false,
133
+ isCollidedVertically: false,
134
+ elytraFlying: false,
135
+ yaw: 0,
136
+ pitch: 0,
137
+ effects: {}
138
+ },
139
+ jumpTicks: 0,
140
+ jumpQueued: false,
141
+ fireworkRocketDuration: 0,
142
+ version: '1.13.2',
143
+ inventory: {
144
+ slots: []
145
+ }
146
+ }
147
+
148
+ const playerState = new PlayerState(player, controls)
149
+ physics.simulatePlayer(playerState, fakeWorld).apply(player)
150
+ })
151
+ })
152
+ })