mineflayer 4.11.0 → 4.13.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/.github/workflows/ci.yml +3 -3
- package/.github/workflows/npm-publish.yml +1 -1
- package/.gitpod.yml +0 -2
- package/README.md +23 -2
- package/docs/README.md +23 -2
- package/docs/history.md +10 -0
- package/examples/armor_stand.js +1 -1
- package/examples/chatterbox.js +5 -5
- package/examples/guard.js +1 -1
- package/examples/jumper.js +2 -2
- package/examples/python/chatterbox.py +5 -5
- package/index.js +2 -2
- package/lib/plugins/entities.js +0 -3
- package/lib/plugins/physics.js +73 -31
- package/package.json +2 -2
- package/.gitpod.DockerFile +0 -11
package/.github/workflows/ci.yml
CHANGED
|
@@ -12,10 +12,10 @@ jobs:
|
|
|
12
12
|
|
|
13
13
|
steps:
|
|
14
14
|
- uses: actions/checkout@v2
|
|
15
|
-
- name: Use Node.js
|
|
15
|
+
- name: Use Node.js 18.x
|
|
16
16
|
uses: actions/setup-node@v1.4.4
|
|
17
17
|
with:
|
|
18
|
-
node-version:
|
|
18
|
+
node-version: 18.x
|
|
19
19
|
- run: npm i && npm run lint
|
|
20
20
|
|
|
21
21
|
MinecraftServer:
|
|
@@ -46,7 +46,7 @@ jobs:
|
|
|
46
46
|
- name: Use Node.js ${{ matrix.node-version }}
|
|
47
47
|
uses: actions/setup-node@v1.4.4
|
|
48
48
|
with:
|
|
49
|
-
node-version:
|
|
49
|
+
node-version: 18.x
|
|
50
50
|
- name: Setup Java JDK
|
|
51
51
|
uses: actions/setup-java@v1.4.3
|
|
52
52
|
with:
|
package/.gitpod.yml
CHANGED
package/README.md
CHANGED
|
@@ -80,11 +80,11 @@ const mineflayer = require('mineflayer')
|
|
|
80
80
|
|
|
81
81
|
const bot = mineflayer.createBot({
|
|
82
82
|
host: 'localhost', // minecraft server ip
|
|
83
|
-
username: '
|
|
83
|
+
username: 'Bot', // username or email, switch if you want to change accounts
|
|
84
84
|
auth: 'microsoft' // for offline mode servers, you can set this to 'offline'
|
|
85
85
|
// port: 25565, // only set if you need a port that isn't 25565
|
|
86
86
|
// version: false, // only set if you need a specific version or snapshot (ie: "1.8.9" or "1.16.5"), otherwise it's set automatically
|
|
87
|
-
// password: '12345678' // set if you want to use password-based auth (may be unreliable)
|
|
87
|
+
// password: '12345678' // set if you want to use password-based auth (may be unreliable). If specified, the `username` must be an email
|
|
88
88
|
})
|
|
89
89
|
|
|
90
90
|
bot.on('chat', (username, message) => {
|
|
@@ -97,6 +97,26 @@ bot.on('kicked', console.log)
|
|
|
97
97
|
bot.on('error', console.log)
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
+
If `auth` is set to `microsoft`, you will be prompted to login to microsoft.com with a code in your browser. After signing in on your browser,
|
|
101
|
+
the bot will automatically obtain and cache authentication tokens in the local file system so you don't have to sign-in again.
|
|
102
|
+
To switch the account, update the supplied `username`. By default, cached tokens will be stored in your user's .minecraft folder.
|
|
103
|
+
For more information on these options and others, see node-minecraft-protocol's [API doc](https://github.com/PrismarineJS/node-minecraft-protocol/blob/master/docs/API.md#mccreateclientoptions).
|
|
104
|
+
|
|
105
|
+
#### Connecting to a Realm
|
|
106
|
+
|
|
107
|
+
To join a Realm that your Minecraft account has been invited to, you can pass a `realms` object with a selector function like below.
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
const client = mineflayer.createBot({
|
|
111
|
+
username: 'email@example.com', // minecraft username
|
|
112
|
+
realms: {
|
|
113
|
+
// This function is called with an array of Realms the account can join. It should return the one it wants to join.
|
|
114
|
+
pickRealm: (realms) => realms[0]
|
|
115
|
+
},
|
|
116
|
+
auth: 'microsoft'
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
100
120
|
### See what your bot is doing
|
|
101
121
|
|
|
102
122
|
Thanks to the [prismarine-viewer](https://github.com/PrismarineJS/prismarine-viewer) project, it's possible to display in a browser window what your bot is doing.
|
|
@@ -220,6 +240,7 @@ The most updated and useful are :
|
|
|
220
240
|
* [Chaoscraft](https://github.com/schematical/chaoscraft) - Minecraft bot using genetic algorithms, see [its youtube videos](https://www.youtube.com/playlist?list=PLLkpLgU9B5xJ7Qy4kOyBJl5J6zsDIMceH)
|
|
221
241
|
* [hexatester/minetelegram](https://github.com/hexatester/minetelegram) - Minecraft - Telegram bridge, build on top of mineflayer & telegraf.
|
|
222
242
|
* [PrismarineJS/mineflayer-builder](https://github.com/PrismarineJS/mineflayer-builder) - Prints minecraft schematics in survival, keeping orientation
|
|
243
|
+
* [SilkePilon/OpenDeliveryBot](https://github.com/SilkePilon/OpenDeliveryBot) - Minecraft bot in python to deliver items from place to place.
|
|
223
244
|
* [and hundreds more](https://github.com/PrismarineJS/mineflayer/network/dependents) - All the projects that github detected are using mineflayer
|
|
224
245
|
|
|
225
246
|
|
package/docs/README.md
CHANGED
|
@@ -80,11 +80,11 @@ const mineflayer = require('mineflayer')
|
|
|
80
80
|
|
|
81
81
|
const bot = mineflayer.createBot({
|
|
82
82
|
host: 'localhost', // minecraft server ip
|
|
83
|
-
username: '
|
|
83
|
+
username: 'Bot', // username or email, switch if you want to change accounts
|
|
84
84
|
auth: 'microsoft' // for offline mode servers, you can set this to 'offline'
|
|
85
85
|
// port: 25565, // only set if you need a port that isn't 25565
|
|
86
86
|
// version: false, // only set if you need a specific version or snapshot (ie: "1.8.9" or "1.16.5"), otherwise it's set automatically
|
|
87
|
-
// password: '12345678' // set if you want to use password-based auth (may be unreliable)
|
|
87
|
+
// password: '12345678' // set if you want to use password-based auth (may be unreliable). If specified, the `username` must be an email
|
|
88
88
|
})
|
|
89
89
|
|
|
90
90
|
bot.on('chat', (username, message) => {
|
|
@@ -97,6 +97,26 @@ bot.on('kicked', console.log)
|
|
|
97
97
|
bot.on('error', console.log)
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
+
If `auth` is set to `microsoft`, you will be prompted to login to microsoft.com with a code in your browser. After signing in on your browser,
|
|
101
|
+
the bot will automatically obtain and cache authentication tokens in the local file system so you don't have to sign-in again.
|
|
102
|
+
To switch the account, update the supplied `username`. By default, cached tokens will be stored in your user's .minecraft folder.
|
|
103
|
+
For more information on these options and others, see node-minecraft-protocol's [API doc](https://github.com/PrismarineJS/node-minecraft-protocol/blob/master/docs/API.md#mccreateclientoptions).
|
|
104
|
+
|
|
105
|
+
#### Connecting to a Realm
|
|
106
|
+
|
|
107
|
+
To join a Realm that your Minecraft account has been invited to, you can pass a `realms` object with a selector function like below.
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
const client = mineflayer.createBot({
|
|
111
|
+
username: 'email@example.com', // minecraft username
|
|
112
|
+
realms: {
|
|
113
|
+
// This function is called with an array of Realms the account can join. It should return the one it wants to join.
|
|
114
|
+
pickRealm: (realms) => realms[0]
|
|
115
|
+
},
|
|
116
|
+
auth: 'microsoft'
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
100
120
|
### See what your bot is doing
|
|
101
121
|
|
|
102
122
|
Thanks to the [prismarine-viewer](https://github.com/PrismarineJS/prismarine-viewer) project, it's possible to display in a browser window what your bot is doing.
|
|
@@ -220,6 +240,7 @@ The most updated and useful are :
|
|
|
220
240
|
* [Chaoscraft](https://github.com/schematical/chaoscraft) - Minecraft bot using genetic algorithms, see [its youtube videos](https://www.youtube.com/playlist?list=PLLkpLgU9B5xJ7Qy4kOyBJl5J6zsDIMceH)
|
|
221
241
|
* [hexatester/minetelegram](https://github.com/hexatester/minetelegram) - Minecraft - Telegram bridge, build on top of mineflayer & telegraf.
|
|
222
242
|
* [PrismarineJS/mineflayer-builder](https://github.com/PrismarineJS/mineflayer-builder) - Prints minecraft schematics in survival, keeping orientation
|
|
243
|
+
* [SilkePilon/OpenDeliveryBot](https://github.com/SilkePilon/OpenDeliveryBot) - Minecraft bot in python to deliver items from place to place.
|
|
223
244
|
* [and hundreds more](https://github.com/PrismarineJS/mineflayer/network/dependents) - All the projects that github detected are using mineflayer
|
|
224
245
|
|
|
225
246
|
|
package/docs/history.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 4.13.0
|
|
2
|
+
* [Switch to entity.displayName (#3168)](https://github.com/PrismarineJS/mineflayer/commit/2409ad458b952173de669a7d9cfaeb770effe3ae) (thanks @lkwilson)
|
|
3
|
+
* [Update readme auth doc (#3169)](https://github.com/PrismarineJS/mineflayer/commit/f5d4a288a768ca6717fa4d22c72fb0267428c684) (thanks @extremeheat)
|
|
4
|
+
* [Add OpenDeliveryBot to "Projects Using Mineflayer" (#3162)](https://github.com/PrismarineJS/mineflayer/commit/ab3c0cf25d0cc28ccba89640b2ceff6ab6b4dace) (thanks @SilkePilon)
|
|
5
|
+
* [Use node 18 on CI (#3157)](https://github.com/PrismarineJS/mineflayer/commit/d3df34dcaa804a71bf0d8cc50a419990d4a2dce3) (thanks @extremeheat)
|
|
6
|
+
* [Fix ambigious function naming (#3161)](https://github.com/PrismarineJS/mineflayer/commit/9ecdf201794bfa350486839a01e318dfd94b3bfb) (thanks @frej4189)
|
|
7
|
+
|
|
8
|
+
## 4.12.0
|
|
9
|
+
* [Mineflayer physics refactor (#2492)](https://github.com/PrismarineJS/mineflayer/commit/d0eb3a1afe6cda7b04ae2f88052cd868ba0c0c4f) (thanks @U5B)
|
|
10
|
+
|
|
1
11
|
## 4.11.0
|
|
2
12
|
* [Import changedSlots computation from prismarine-windows (#3134)](https://github.com/PrismarineJS/mineflayer/commit/e5b5eeecf1133c1c80c0ef48d6e72fed77d84834) (thanks @kaduvert)
|
|
3
13
|
* [Make the place block success check ignore block updates received with no block type changes (#3090)](https://github.com/PrismarineJS/mineflayer/commit/bbdd93afe2e31d1f1e899176e7edf8e73af5d5d3) (thanks @PondWader)
|
package/examples/armor_stand.js
CHANGED
|
@@ -26,7 +26,7 @@ bot.on('chat', async (username, message) => {
|
|
|
26
26
|
const [mainCommand, subCommand] = message.split(' ')
|
|
27
27
|
if (mainCommand !== 'equip' && mainCommand !== 'unequip') return
|
|
28
28
|
|
|
29
|
-
const armorStand = bot.nearestEntity(e => e.
|
|
29
|
+
const armorStand = bot.nearestEntity(e => e.displayName === 'Armor Stand' && bot.entity.position.distanceTo(e.position) < 4)
|
|
30
30
|
if (!armorStand) {
|
|
31
31
|
bot.chat('No armor stands nearby!')
|
|
32
32
|
return
|
package/examples/chatterbox.js
CHANGED
|
@@ -176,11 +176,11 @@ bot.on('playerCollect', (collector, collected) => {
|
|
|
176
176
|
|
|
177
177
|
bot.on('entitySpawn', (entity) => {
|
|
178
178
|
if (entity.type === 'mob') {
|
|
179
|
-
console.log(`Look out! A ${entity.
|
|
179
|
+
console.log(`Look out! A ${entity.displayName} spawned at ${entity.position}`)
|
|
180
180
|
} else if (entity.type === 'player') {
|
|
181
181
|
bot.chat(`Look who decided to show up: ${entity.username}`)
|
|
182
182
|
} else if (entity.type === 'object') {
|
|
183
|
-
console.log(`There's a ${entity.
|
|
183
|
+
console.log(`There's a ${entity.displayName} at ${entity.position}`)
|
|
184
184
|
} else if (entity.type === 'global') {
|
|
185
185
|
bot.chat('Ooh lightning!')
|
|
186
186
|
} else if (entity.type === 'orb') {
|
|
@@ -189,7 +189,7 @@ bot.on('entitySpawn', (entity) => {
|
|
|
189
189
|
})
|
|
190
190
|
bot.on('entityHurt', (entity) => {
|
|
191
191
|
if (entity.type === 'mob') {
|
|
192
|
-
bot.chat(`Haha! The ${entity.
|
|
192
|
+
bot.chat(`Haha! The ${entity.displayName} got hurt!`)
|
|
193
193
|
} else if (entity.type === 'player') {
|
|
194
194
|
bot.chat(`Aww, poor ${entity.username} got hurt. Maybe you shouldn't have a ping of ${bot.players[entity.username].ping}`)
|
|
195
195
|
}
|
|
@@ -214,12 +214,12 @@ bot.on('entityEat', (entity) => {
|
|
|
214
214
|
})
|
|
215
215
|
bot.on('entityAttach', (entity, vehicle) => {
|
|
216
216
|
if (entity.type === 'player' && vehicle.type === 'object') {
|
|
217
|
-
bot.chat(`Sweet, ${entity.username} is riding that ${vehicle.
|
|
217
|
+
bot.chat(`Sweet, ${entity.username} is riding that ${vehicle.displayName}`)
|
|
218
218
|
}
|
|
219
219
|
})
|
|
220
220
|
bot.on('entityDetach', (entity, vehicle) => {
|
|
221
221
|
if (entity.type === 'player' && vehicle.type === 'object') {
|
|
222
|
-
bot.chat(`Lame, ${entity.username} stopped riding the ${vehicle.
|
|
222
|
+
bot.chat(`Lame, ${entity.username} stopped riding the ${vehicle.displayName}`)
|
|
223
223
|
}
|
|
224
224
|
})
|
|
225
225
|
bot.on('entityEquipmentChange', (entity) => {
|
package/examples/guard.js
CHANGED
|
@@ -59,7 +59,7 @@ bot.on('physicsTick', () => {
|
|
|
59
59
|
|
|
60
60
|
// Only look for mobs within 16 blocks
|
|
61
61
|
const filter = e => e.type === 'mob' && e.position.distanceTo(bot.entity.position) < 16 &&
|
|
62
|
-
e.
|
|
62
|
+
e.displayName !== 'Armor Stand' // Mojang classifies armor stands as mobs for some reason?
|
|
63
63
|
|
|
64
64
|
const entity = bot.nearestEntity(filter)
|
|
65
65
|
if (entity) {
|
package/examples/jumper.js
CHANGED
|
@@ -108,9 +108,9 @@ bot.once('spawn', () => {
|
|
|
108
108
|
})
|
|
109
109
|
|
|
110
110
|
bot.on('mount', () => {
|
|
111
|
-
bot.chat(`mounted ${bot.vehicle.
|
|
111
|
+
bot.chat(`mounted ${bot.vehicle.displayName}`)
|
|
112
112
|
})
|
|
113
113
|
|
|
114
114
|
bot.on('dismount', (vehicle) => {
|
|
115
|
-
bot.chat(`dismounted ${vehicle.
|
|
115
|
+
bot.chat(`dismounted ${vehicle.displayName}`)
|
|
116
116
|
})
|
|
@@ -224,12 +224,12 @@ def playerCollect(this, collector, collected):
|
|
|
224
224
|
def entitySpawn(this, entity):
|
|
225
225
|
if entity.type == "mob":
|
|
226
226
|
p = entity.position
|
|
227
|
-
console.log(f"Look out! A {entity.
|
|
227
|
+
console.log(f"Look out! A {entity.displayName} spawned at {p.toString()}")
|
|
228
228
|
elif entity.type == "player":
|
|
229
229
|
bot.chat(f"Look who decided to show up: {entity.username}")
|
|
230
230
|
elif entity.type == "object":
|
|
231
231
|
p = entity.position
|
|
232
|
-
console.log(f"There's a {entity.
|
|
232
|
+
console.log(f"There's a {entity.displayName} at {p.toString()}")
|
|
233
233
|
elif entity.type == "global":
|
|
234
234
|
bot.chat("Ooh lightning!")
|
|
235
235
|
elif entity.type == "orb":
|
|
@@ -239,7 +239,7 @@ def entitySpawn(this, entity):
|
|
|
239
239
|
@On(bot, "entityHurt")
|
|
240
240
|
def entityHurt(this, entity):
|
|
241
241
|
if entity.type == "mob":
|
|
242
|
-
bot.chat(f"Haha! The ${entity.
|
|
242
|
+
bot.chat(f"Haha! The ${entity.displayName} got hurt!")
|
|
243
243
|
elif entity.type == "player":
|
|
244
244
|
if entity.username in bot.players:
|
|
245
245
|
ping = bot.players[entity.username].ping
|
|
@@ -279,13 +279,13 @@ def entityEat(this, entity):
|
|
|
279
279
|
@On(bot, "entityAttach")
|
|
280
280
|
def entityAttach(this, entity, vehicle):
|
|
281
281
|
if entity.type == "player" and vehicle.type == "object":
|
|
282
|
-
print(f"Sweet, {entity.username} is riding that {vehicle.
|
|
282
|
+
print(f"Sweet, {entity.username} is riding that {vehicle.displayName}")
|
|
283
283
|
|
|
284
284
|
|
|
285
285
|
@On(bot, "entityDetach")
|
|
286
286
|
def entityDetach(this, entity, vehicle):
|
|
287
287
|
if entity.type == "player" and vehicle.type == "object":
|
|
288
|
-
print(f"Lame, {entity.username} stopped riding the {vehicle.
|
|
288
|
+
print(f"Lame, {entity.username} stopped riding the {vehicle.displayName}")
|
|
289
289
|
|
|
290
290
|
|
|
291
291
|
@On(bot, "entityEquipmentChange")
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
if (typeof process !== 'undefined' && parseInt(process.versions.node.split('.')[0]) <
|
|
1
|
+
if (typeof process !== 'undefined' && parseInt(process.versions.node.split('.')[0]) < 18) {
|
|
2
2
|
console.error('Your node version is currently', process.versions.node)
|
|
3
|
-
console.error('Please update it to a version >=
|
|
3
|
+
console.error('Please update it to a version >= 18.x.x from https://nodejs.org/')
|
|
4
4
|
process.exit(1)
|
|
5
5
|
}
|
|
6
6
|
|
package/lib/plugins/entities.js
CHANGED
|
@@ -176,8 +176,6 @@ function inject (bot) {
|
|
|
176
176
|
entityData = entitiesArray.find(entity => entity.internalId === type)
|
|
177
177
|
}
|
|
178
178
|
if (entityData) {
|
|
179
|
-
entity.mobType = entityData.displayName
|
|
180
|
-
entity.objectType = entityData.displayName
|
|
181
179
|
entity.displayName = entityData.displayName
|
|
182
180
|
entity.entityType = entityData.id
|
|
183
181
|
entity.name = entityData.name
|
|
@@ -188,7 +186,6 @@ function inject (bot) {
|
|
|
188
186
|
// unknown entity
|
|
189
187
|
entity.type = 'other'
|
|
190
188
|
entity.entityType = type
|
|
191
|
-
entity.mobType = 'unknown'
|
|
192
189
|
entity.displayName = 'unknown'
|
|
193
190
|
entity.name = 'unknown'
|
|
194
191
|
entity.kind = 'unknown'
|
package/lib/plugins/physics.js
CHANGED
|
@@ -12,9 +12,10 @@ module.exports = inject
|
|
|
12
12
|
const PI = Math.PI
|
|
13
13
|
const PI_2 = Math.PI * 2
|
|
14
14
|
const PHYSICS_INTERVAL_MS = 50
|
|
15
|
-
const PHYSICS_TIMESTEP = PHYSICS_INTERVAL_MS / 1000
|
|
15
|
+
const PHYSICS_TIMESTEP = PHYSICS_INTERVAL_MS / 1000 // 0.05
|
|
16
16
|
|
|
17
|
-
function inject (bot, { physicsEnabled }) {
|
|
17
|
+
function inject (bot, { physicsEnabled, maxCatchupTicks }) {
|
|
18
|
+
const PHYSICS_CATCHUP_TICKS = maxCatchupTicks ?? 4
|
|
18
19
|
const world = { getBlock: (pos) => { return bot.blockAt(pos, false) } }
|
|
19
20
|
const physics = Physics(bot.registry, world)
|
|
20
21
|
|
|
@@ -38,6 +39,7 @@ function inject (bot, { physicsEnabled }) {
|
|
|
38
39
|
let lastPhysicsFrameTime = null
|
|
39
40
|
let shouldUsePhysics = false
|
|
40
41
|
bot.physicsEnabled = physicsEnabled ?? true
|
|
42
|
+
let deadTicks = 21
|
|
41
43
|
|
|
42
44
|
const lastSent = {
|
|
43
45
|
x: 0,
|
|
@@ -51,25 +53,44 @@ function inject (bot, { physicsEnabled }) {
|
|
|
51
53
|
|
|
52
54
|
// This function should be executed each tick (every 0.05 seconds)
|
|
53
55
|
// How it works: https://gafferongames.com/post/fix_your_timestep/
|
|
56
|
+
|
|
57
|
+
// WARNING: THIS IS NOT ACCURATE ON WINDOWS (15.6 Timer Resolution)
|
|
58
|
+
// use WSL or switch to Linux
|
|
59
|
+
// see: https://discord.com/channels/413438066984747026/519952494768685086/901948718255833158
|
|
54
60
|
let timeAccumulator = 0
|
|
61
|
+
let catchupTicks = 0
|
|
55
62
|
function doPhysics () {
|
|
56
63
|
const now = performance.now()
|
|
57
64
|
const deltaSeconds = (now - lastPhysicsFrameTime) / 1000
|
|
58
65
|
lastPhysicsFrameTime = now
|
|
59
66
|
|
|
60
67
|
timeAccumulator += deltaSeconds
|
|
61
|
-
|
|
68
|
+
catchupTicks = 0
|
|
62
69
|
while (timeAccumulator >= PHYSICS_TIMESTEP) {
|
|
63
|
-
|
|
64
|
-
physics.simulatePlayer(new PlayerState(bot, controlState), world).apply(bot)
|
|
65
|
-
bot.emit('physicsTick')
|
|
66
|
-
bot.emit('physicTick') // Deprecated, only exists to support old plugins. May be removed in the future
|
|
67
|
-
}
|
|
68
|
-
updatePosition(PHYSICS_TIMESTEP)
|
|
70
|
+
tickPhysics(now)
|
|
69
71
|
timeAccumulator -= PHYSICS_TIMESTEP
|
|
72
|
+
catchupTicks++
|
|
73
|
+
if (catchupTicks >= PHYSICS_CATCHUP_TICKS) break
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function tickPhysics (now) {
|
|
78
|
+
if (bot.blockAt(bot.entity.position) == null) return // check if chunk is unloaded
|
|
79
|
+
if (bot.physicsEnabled && shouldUsePhysics) {
|
|
80
|
+
physics.simulatePlayer(new PlayerState(bot, controlState), world).apply(bot)
|
|
81
|
+
bot.emit('physicsTick')
|
|
82
|
+
bot.emit('physicTick') // Deprecated, only exists to support old plugins. May be removed in the future
|
|
83
|
+
}
|
|
84
|
+
if (shouldUsePhysics) {
|
|
85
|
+
updatePosition(now)
|
|
70
86
|
}
|
|
71
87
|
}
|
|
72
88
|
|
|
89
|
+
// remove this when 'physicTick' is removed
|
|
90
|
+
bot.on('newListener', (name) => {
|
|
91
|
+
if (name === 'physicTick') console.warn('Mineflayer detected that you are using a deprecated event (physicTick)! Please use this event (physicsTick) instead.')
|
|
92
|
+
})
|
|
93
|
+
|
|
73
94
|
function cleanup () {
|
|
74
95
|
clearInterval(doPhysicsTimer)
|
|
75
96
|
doPhysicsTimer = null
|
|
@@ -117,17 +138,25 @@ function inject (bot, { physicsEnabled }) {
|
|
|
117
138
|
return dYaw
|
|
118
139
|
}
|
|
119
140
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (
|
|
141
|
+
// returns false if bot should send position packets
|
|
142
|
+
function isEntityRemoved () {
|
|
143
|
+
if (bot.isAlive === true) deadTicks = 0
|
|
144
|
+
if (bot.isAlive === false && deadTicks <= 20) deadTicks++
|
|
145
|
+
if (deadTicks >= 20) return true
|
|
146
|
+
return false
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function updatePosition (now) {
|
|
150
|
+
// Only send updates for 20 ticks after death
|
|
151
|
+
if (isEntityRemoved()) return
|
|
123
152
|
|
|
124
153
|
// Increment the yaw in baby steps so that notchian clients (not the server) can keep up.
|
|
125
154
|
const dYaw = deltaYaw(bot.entity.yaw, lastSentYaw)
|
|
126
155
|
const dPitch = bot.entity.pitch - (lastSentPitch || 0)
|
|
127
156
|
|
|
128
157
|
// Vanilla doesn't clamp yaw, so we don't want to do it either
|
|
129
|
-
const maxDeltaYaw =
|
|
130
|
-
const maxDeltaPitch =
|
|
158
|
+
const maxDeltaYaw = PHYSICS_TIMESTEP * physics.yawSpeed
|
|
159
|
+
const maxDeltaPitch = PHYSICS_TIMESTEP * physics.pitchSpeed
|
|
131
160
|
lastSentYaw += math.clamp(-maxDeltaYaw, dYaw, maxDeltaYaw)
|
|
132
161
|
lastSentPitch += math.clamp(-maxDeltaPitch, dPitch, maxDeltaPitch)
|
|
133
162
|
|
|
@@ -137,24 +166,28 @@ function inject (bot, { physicsEnabled }) {
|
|
|
137
166
|
const onGround = bot.entity.onGround
|
|
138
167
|
|
|
139
168
|
// Only send a position update if necessary, select the appropriate packet
|
|
140
|
-
const positionUpdated = lastSent.x !== position.x || lastSent.y !== position.y || lastSent.z !== position.z
|
|
169
|
+
const positionUpdated = lastSent.x !== position.x || lastSent.y !== position.y || lastSent.z !== position.z ||
|
|
170
|
+
// Send a position update every second, even if no other update was made
|
|
171
|
+
// This function rounds to the nearest 50ms (or PHYSICS_INTERVAL_MS) and checks if a second has passed.
|
|
172
|
+
(Math.round((now - lastSent.time) / PHYSICS_INTERVAL_MS) * PHYSICS_INTERVAL_MS) >= 1000
|
|
141
173
|
const lookUpdated = lastSent.yaw !== yaw || lastSent.pitch !== pitch
|
|
142
174
|
|
|
143
|
-
if (positionUpdated && lookUpdated
|
|
175
|
+
if (positionUpdated && lookUpdated) {
|
|
144
176
|
sendPacketPositionAndLook(position, yaw, pitch, onGround)
|
|
145
|
-
|
|
177
|
+
lastSent.time = now // only reset if positionUpdated is true
|
|
178
|
+
} else if (positionUpdated) {
|
|
146
179
|
sendPacketPosition(position, onGround)
|
|
147
|
-
|
|
180
|
+
lastSent.time = now // only reset if positionUpdated is true
|
|
181
|
+
} else if (lookUpdated) {
|
|
148
182
|
sendPacketLook(yaw, pitch, onGround)
|
|
149
|
-
} else if (
|
|
150
|
-
// Send a position packet every second, even if no update was made
|
|
151
|
-
sendPacketPosition(position, onGround)
|
|
152
|
-
lastSent.time = performance.now()
|
|
153
|
-
} else if (positionUpdateSentEveryTick && bot.isAlive) {
|
|
183
|
+
} else if (positionUpdateSentEveryTick || onGround !== lastSent.onGround) {
|
|
154
184
|
// For versions < 1.12, one player packet should be sent every tick
|
|
155
185
|
// for the server to update health correctly
|
|
186
|
+
// For versions >= 1.12, onGround !== lastSent.onGround should be used, but it doesn't ever trigger outside of login
|
|
156
187
|
bot._client.write('flying', { onGround: bot.entity.onGround })
|
|
157
188
|
}
|
|
189
|
+
|
|
190
|
+
lastSent.onGround = bot.entity.onGround // onGround is always set
|
|
158
191
|
}
|
|
159
192
|
|
|
160
193
|
bot.physics = physics
|
|
@@ -262,7 +295,14 @@ function inject (bot, { physicsEnabled }) {
|
|
|
262
295
|
// player position and look (clientbound)
|
|
263
296
|
bot._client.on('position', (packet) => {
|
|
264
297
|
bot.entity.height = 1.62
|
|
265
|
-
|
|
298
|
+
|
|
299
|
+
// Velocity is only set to 0 if the flag is not set, otherwise keep current velocity
|
|
300
|
+
const vel = bot.entity.velocity
|
|
301
|
+
vel.set(
|
|
302
|
+
packet.flags & 1 ? vel.x : 0,
|
|
303
|
+
packet.flags & 2 ? vel.y : 0,
|
|
304
|
+
packet.flags & 4 ? vel.z : 0
|
|
305
|
+
)
|
|
266
306
|
|
|
267
307
|
// If flag is set, then the corresponding value is relative, else it is absolute
|
|
268
308
|
const pos = bot.entity.position
|
|
@@ -280,19 +320,14 @@ function inject (bot, { physicsEnabled }) {
|
|
|
280
320
|
|
|
281
321
|
if (bot.supportFeature('teleportUsesOwnPacket')) {
|
|
282
322
|
bot._client.write('teleport_confirm', { teleportId: packet.teleportId })
|
|
283
|
-
// Force send an extra packet to be like vanilla client
|
|
284
|
-
sendPacketPositionAndLook(pos, newYaw, newPitch, bot.entity.onGround)
|
|
285
323
|
}
|
|
286
324
|
sendPacketPositionAndLook(pos, newYaw, newPitch, bot.entity.onGround)
|
|
287
325
|
|
|
288
326
|
shouldUsePhysics = true
|
|
289
|
-
bot.
|
|
327
|
+
bot.jumpTicks = 0
|
|
290
328
|
lastSentYaw = bot.entity.yaw
|
|
329
|
+
lastSentPitch = bot.entity.pitch
|
|
291
330
|
|
|
292
|
-
if (doPhysicsTimer === null) {
|
|
293
|
-
lastPhysicsFrameTime = performance.now()
|
|
294
|
-
doPhysicsTimer = setInterval(doPhysics, PHYSICS_INTERVAL_MS)
|
|
295
|
-
}
|
|
296
331
|
bot.emit('forcedMove')
|
|
297
332
|
})
|
|
298
333
|
|
|
@@ -313,5 +348,12 @@ function inject (bot, { physicsEnabled }) {
|
|
|
313
348
|
|
|
314
349
|
bot.on('mount', () => { shouldUsePhysics = false })
|
|
315
350
|
bot.on('respawn', () => { shouldUsePhysics = false })
|
|
351
|
+
bot.on('login', () => {
|
|
352
|
+
shouldUsePhysics = false
|
|
353
|
+
if (doPhysicsTimer === null) {
|
|
354
|
+
lastPhysicsFrameTime = performance.now()
|
|
355
|
+
doPhysicsTimer = setInterval(doPhysics, PHYSICS_INTERVAL_MS)
|
|
356
|
+
}
|
|
357
|
+
})
|
|
316
358
|
bot.on('end', cleanup)
|
|
317
359
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mineflayer",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.13.0",
|
|
4
4
|
"description": "create minecraft bots with a stable, high level API",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"prismarine-block": "^1.17.0",
|
|
28
28
|
"prismarine-chat": "^1.7.1",
|
|
29
29
|
"prismarine-chunk": "^1.34.0",
|
|
30
|
-
"prismarine-entity": "^2.
|
|
30
|
+
"prismarine-entity": "^2.3.0",
|
|
31
31
|
"prismarine-item": "^1.14.0",
|
|
32
32
|
"prismarine-nbt": "^2.0.0",
|
|
33
33
|
"prismarine-physics": "^1.7.0",
|
package/.gitpod.DockerFile
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
FROM gitpod/workspace-full:latest
|
|
2
|
-
|
|
3
|
-
RUN bash -c ". /home/gitpod/.sdkman/bin/sdkman-init.sh \
|
|
4
|
-
&& sdk install java"
|
|
5
|
-
|
|
6
|
-
RUN bash -c ". .nvm/nvm.sh \
|
|
7
|
-
&& nvm install 14 \
|
|
8
|
-
&& nvm use 14 \
|
|
9
|
-
&& nvm alias default 14"
|
|
10
|
-
|
|
11
|
-
RUN echo "nvm use default &>/dev/null" >> ~/.bashrc.d/51-nvm-fix
|