spectra-physics 1.0.0 → 1.2.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.
- package/README.md +51 -23
- package/index.js +2 -2
- package/lib/client/clock.js +38 -0
- package/lib/client/connection.js +103 -0
- package/lib/client/controls.js +78 -0
- package/lib/client/environment.js +94 -0
- package/lib/client/index.js +81 -0
- package/lib/client/interact.js +79 -0
- package/lib/client/items.js +85 -0
- package/lib/client/protocol.js +42 -0
- package/lib/client/registries.js +86 -0
- package/lib/client/reporter.js +91 -0
- package/lib/client/riding.js +69 -0
- package/lib/client/server.js +103 -0
- package/lib/client/teleport.js +108 -0
- package/lib/client/ticker.js +129 -0
- package/lib/engine/aabb.js +5 -3
- package/lib/engine/boat.js +57 -7
- package/lib/engine/player/blocks.js +134 -0
- package/lib/engine/player/effects.js +115 -0
- package/lib/engine/player/fluids.js +150 -0
- package/lib/engine/player/index.js +220 -0
- package/lib/engine/player/input.js +89 -0
- package/lib/engine/player/move.js +141 -0
- package/lib/engine/player/pose.js +95 -0
- package/lib/engine/player/push.js +27 -0
- package/lib/engine/player/travel.js +203 -0
- package/lib/engine/player/traversal.js +290 -0
- package/lib/engine/version.js +52 -27
- package/lib/engine/world.js +85 -20
- package/package.json +2 -1
- package/lib/engine/physics.js +0 -780
- package/lib/plugin.js +0 -574
package/lib/engine/world.js
CHANGED
|
@@ -14,37 +14,83 @@ const SPEED_FACTOR = { soul_sand: 0.4, honey_block: 0.4 }
|
|
|
14
14
|
const JUMP_FACTOR = { honey_block: 0.5 }
|
|
15
15
|
|
|
16
16
|
const FULL = [0, 0, 0, 1, 1, 1]
|
|
17
|
+
const NO_SHAPES = []
|
|
18
|
+
const SNOW_FULL = [FULL]
|
|
19
|
+
const SNOW_FALLING = [[0, 0, 0, 1, f32(0.9), 1]]
|
|
20
|
+
const ABOVE_EPSILON = f32(1.0e-5)
|
|
17
21
|
|
|
18
22
|
class WorldView {
|
|
19
23
|
constructor (bot) {
|
|
20
24
|
this.bot = bot
|
|
21
25
|
this.registry = bot.registry
|
|
22
26
|
this.Block = require('prismarine-block')(bot.registry)
|
|
23
|
-
|
|
27
|
+
let states = 1
|
|
28
|
+
for (const b of bot.registry.blocksArray ?? []) states = Math.max(states, (b.maxStateId ?? b.id) + 1)
|
|
29
|
+
this.infos = new Array(states).fill(null)
|
|
30
|
+
this.boxes = []
|
|
31
|
+
this.boxPool = []
|
|
24
32
|
this.pos = { x: 0, y: 0, z: 0 }
|
|
33
|
+
// collision context of the entity that is moving: { bottom, fallDistance, walksOnPowderSnow, descending }
|
|
34
|
+
this.entity = null
|
|
35
|
+
// while an entity ticks nothing else can change the world, so column lookups are memoised
|
|
36
|
+
this.ticking = false
|
|
37
|
+
this.columns = new Map()
|
|
38
|
+
this.bottom = 0
|
|
39
|
+
this.top = 256
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
beginTick (entity = null) {
|
|
43
|
+
this.entity = entity
|
|
44
|
+
this.ticking = true
|
|
45
|
+
this.columns.clear()
|
|
46
|
+
this.bottom = this.minY
|
|
47
|
+
this.top = this.maxY
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
endTick () {
|
|
51
|
+
this.entity = null
|
|
52
|
+
this.ticking = false
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
column (cx, cz) {
|
|
56
|
+
if (!this.ticking) return this.bot.world.getColumn(cx, cz)
|
|
57
|
+
const key = cx * 4194304 + cz
|
|
58
|
+
let col = this.columns.get(key)
|
|
59
|
+
if (col === undefined) {
|
|
60
|
+
col = this.bot.world.getColumn(cx, cz) ?? null
|
|
61
|
+
this.columns.set(key, col)
|
|
62
|
+
}
|
|
63
|
+
return col
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// PowderSnowBlock#getCollisionShape
|
|
67
|
+
powderSnowShapes (y) {
|
|
68
|
+
const e = this.entity
|
|
69
|
+
if (!e) return NO_SHAPES
|
|
70
|
+
if (e.fallDistance > 2.5) return SNOW_FALLING
|
|
71
|
+
if (e.walksOnPowderSnow && e.bottom > y + 1 - ABOVE_EPSILON && !e.descending) return SNOW_FULL
|
|
72
|
+
return NO_SHAPES
|
|
25
73
|
}
|
|
26
74
|
|
|
27
75
|
get minY () { return this.bot.game?.minY ?? 0 }
|
|
28
76
|
get maxY () { return this.minY + (this.bot.game?.height ?? 256) }
|
|
29
77
|
|
|
30
78
|
hasChunk (bx, bz) {
|
|
31
|
-
return !!this.
|
|
79
|
+
return !!this.column(Math.floor(bx) >> 4, Math.floor(bz) >> 4)
|
|
32
80
|
}
|
|
33
81
|
|
|
34
82
|
// returns null when the column is not loaded
|
|
35
83
|
stateAt (x, y, z) {
|
|
36
|
-
const col = this.
|
|
84
|
+
const col = this.column(x >> 4, z >> 4)
|
|
37
85
|
if (!col) return null
|
|
38
|
-
if (y < this.minY || y >= this.maxY) return 0
|
|
86
|
+
if (this.ticking ? (y < this.bottom || y >= this.top) : (y < this.minY || y >= this.maxY)) return 0
|
|
39
87
|
this.pos.x = x & 15; this.pos.y = y; this.pos.z = z & 15
|
|
40
88
|
return col.getBlockStateId(this.pos)
|
|
41
89
|
}
|
|
42
90
|
|
|
43
91
|
info (stateId) {
|
|
44
|
-
let i = this.
|
|
45
|
-
if (i)
|
|
46
|
-
i = this._build(stateId)
|
|
47
|
-
this.cache.set(stateId, i)
|
|
92
|
+
let i = this.infos[stateId]
|
|
93
|
+
if (i == null) i = this.infos[stateId] = this._build(stateId)
|
|
48
94
|
return i
|
|
49
95
|
}
|
|
50
96
|
|
|
@@ -79,9 +125,12 @@ class WorldView {
|
|
|
79
125
|
isPowderSnow: name === 'powder_snow',
|
|
80
126
|
isScaffolding: name === 'scaffolding',
|
|
81
127
|
isFenceLike: name.endsWith('_fence') || name.endsWith('_wall') || name.endsWith('_fence_gate'),
|
|
128
|
+
isBubbleColumn: name === 'bubble_column',
|
|
129
|
+
bubbleDrag: props.drag === true || props.drag === 'true',
|
|
82
130
|
fullCube: shapes.length === 1 && shapes[0].every((v, k) => v === FULL[k]),
|
|
83
131
|
fluid: null
|
|
84
132
|
}
|
|
133
|
+
info.suffocating = info.fullCube && !(b?.transparent ?? true)
|
|
85
134
|
// fluids
|
|
86
135
|
if (name === 'water' || name === 'lava' || name === 'flowing_water' || name === 'flowing_lava') {
|
|
87
136
|
const level = Number(props.level ?? 0)
|
|
@@ -115,33 +164,49 @@ class WorldView {
|
|
|
115
164
|
|
|
116
165
|
// Collect every collision box that could touch `bb` (BlockCollisions semantics:
|
|
117
166
|
// unloaded chunks collide with nothing, outside build height is air).
|
|
118
|
-
|
|
167
|
+
// The returned list and its boxes are reused by the next call.
|
|
168
|
+
collisionBoxes (bb) {
|
|
169
|
+
this.boxes.length = 0
|
|
170
|
+
this.scan(bb, false)
|
|
171
|
+
return this.boxes
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
noCollision (bb) {
|
|
175
|
+
return !this.scan(bb, true)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// walks the blocks around bb; with test set, stops at the first box that overlaps bb
|
|
179
|
+
scan (bb, test) {
|
|
180
|
+
const pool = this.boxPool
|
|
181
|
+
const out = this.boxes
|
|
119
182
|
const x0 = Math.floor(bb.minX - 1.0e-7) - 1; const x1 = Math.floor(bb.maxX + 1.0e-7) + 1
|
|
120
183
|
const y0 = Math.floor(bb.minY - 1.0e-7) - 1; const y1 = Math.floor(bb.maxY + 1.0e-7) + 1
|
|
121
184
|
const z0 = Math.floor(bb.minZ - 1.0e-7) - 1; const z1 = Math.floor(bb.maxZ + 1.0e-7) + 1
|
|
122
185
|
for (let x = x0; x <= x1; x++) {
|
|
123
186
|
for (let z = z0; z <= z1; z++) {
|
|
124
|
-
const col = this.
|
|
187
|
+
const col = this.column(x >> 4, z >> 4)
|
|
125
188
|
if (!col) continue
|
|
189
|
+
const bottom = this.ticking ? this.bottom : this.minY
|
|
190
|
+
const top = this.ticking ? this.top : this.maxY
|
|
126
191
|
for (let y = y0; y <= y1; y++) {
|
|
127
|
-
if (y <
|
|
192
|
+
if (y < bottom || y >= top) continue
|
|
128
193
|
this.pos.x = x & 15; this.pos.y = y; this.pos.z = z & 15
|
|
129
194
|
const info = this.info(col.getBlockStateId(this.pos))
|
|
130
|
-
const shapes = info.shapes
|
|
195
|
+
const shapes = info.isPowderSnow ? this.powderSnowShapes(y) : info.shapes
|
|
131
196
|
for (let k = 0; k < shapes.length; k++) {
|
|
132
197
|
const s = shapes[k]
|
|
133
|
-
|
|
198
|
+
if (test) {
|
|
199
|
+
if (bb.intersects(s[0] + x, s[1] + y, s[2] + z, s[3] + x, s[4] + y, s[5] + z)) return true
|
|
200
|
+
continue
|
|
201
|
+
}
|
|
202
|
+
const b = pool[out.length] ?? (pool[out.length] = new Array(6))
|
|
203
|
+
b[0] = s[0] + x; b[1] = s[1] + y; b[2] = s[2] + z; b[3] = s[3] + x; b[4] = s[4] + y; b[5] = s[5] + z
|
|
204
|
+
out.push(b)
|
|
134
205
|
}
|
|
135
206
|
}
|
|
136
207
|
}
|
|
137
208
|
}
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
noCollision (bb) {
|
|
142
|
-
const boxes = this.collisionBoxes(bb)
|
|
143
|
-
for (const b of boxes) if (bb.intersectsBox(b)) return false
|
|
144
|
-
return true
|
|
209
|
+
return false
|
|
145
210
|
}
|
|
146
211
|
|
|
147
212
|
containsAnyLiquid (bb) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spectra-physics",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Vanilla-accurate client physics and movement for mineflayer (1.16.5 - 26.1)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"node": ">=22"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
+
"minecraft-data": "^3.117.0",
|
|
40
41
|
"prismarine-block": "^1.23.0",
|
|
41
42
|
"prismarine-chunk": "^1.39.0",
|
|
42
43
|
"vec3": "^0.1.10"
|