mineflayer 4.12.0 → 4.14.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/api.md +24 -1
- package/docs/history.md +12 -0
- package/docs/mineflayer.ipynb +21 -18
- package/examples/armor_stand.js +1 -1
- package/examples/chatterbox.js +5 -5
- package/examples/elytra.js +66 -0
- package/examples/guard.js +1 -1
- package/examples/jumper.js +2 -2
- package/examples/python/chatterbox.py +5 -5
- package/index.d.ts +7 -1
- package/index.js +2 -2
- package/lib/plugins/entities.js +113 -12
- package/lib/plugins/physics.js +41 -3
- package/package.json +4 -4
- 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/api.md
CHANGED
|
@@ -136,6 +136,7 @@
|
|
|
136
136
|
- [bot.foodSaturation](#botfoodsaturation)
|
|
137
137
|
- [bot.oxygenLevel](#botoxygenlevel)
|
|
138
138
|
- [bot.physics](#botphysics)
|
|
139
|
+
- [bot.fireworkRocketDuration](#botfireworkrocketduration)
|
|
139
140
|
- [bot.simpleClick.leftMouse (slot)](#botsimpleclickleftmouse-slot)
|
|
140
141
|
- [bot.simpleClick.rightMouse (slot)](#botsimpleclickrightmouse-slot)
|
|
141
142
|
- [bot.time.doDaylightCycle](#bottimedodaylightcycle)
|
|
@@ -197,6 +198,7 @@
|
|
|
197
198
|
- ["entityEquip" (entity)](#entityequip-entity)
|
|
198
199
|
- ["entitySleep" (entity)](#entitysleep-entity)
|
|
199
200
|
- ["entitySpawn" (entity)](#entityspawn-entity)
|
|
201
|
+
- ["entityElytraFlew" (entity)](#entityelytraflew-entity)
|
|
200
202
|
- ["itemDrop" (entity)](#itemdrop-entity)
|
|
201
203
|
- ["playerCollect" (collector, collected)](#playercollect-collector-collected)
|
|
202
204
|
- ["entityGone" (entity)](#entitygone-entity)
|
|
@@ -223,6 +225,7 @@
|
|
|
223
225
|
- ["blockBreakProgressEnd" (block, entity)](#blockbreakprogressend-block-entity)
|
|
224
226
|
- ["diggingCompleted" (block)](#diggingcompleted-block)
|
|
225
227
|
- ["diggingAborted" (block)](#diggingaborted-block)
|
|
228
|
+
- ["usedFirework"](#usedfirework)
|
|
226
229
|
- ["move"](#move)
|
|
227
230
|
- ["forcedMove"](#forcedmove)
|
|
228
231
|
- ["mount"](#mount)
|
|
@@ -293,6 +296,7 @@
|
|
|
293
296
|
- [bot.unequip(destination)](#botunequipdestination)
|
|
294
297
|
- [bot.tossStack(item)](#bottossstackitem)
|
|
295
298
|
- [bot.toss(itemType, metadata, count)](#bottossitemtype-metadata-count)
|
|
299
|
+
- [bot.elytraFly()](#botelytrafly)
|
|
296
300
|
- [bot.dig(block, [forceLook = true], [digFace])](#botdigblock-forcelook--true-digface)
|
|
297
301
|
- [bot.stopDigging()](#botstopdigging)
|
|
298
302
|
- [bot.digTime(block)](#botdigtimeblock)
|
|
@@ -1037,6 +1041,10 @@ Number in the range [0, 20] respresenting the number of water-icons known as oxy
|
|
|
1037
1041
|
Edit these numbers to tweak gravity, jump speed, terminal velocity, etc.
|
|
1038
1042
|
Do this at your own risk.
|
|
1039
1043
|
|
|
1044
|
+
#### bot.fireworkRocketDuration
|
|
1045
|
+
|
|
1046
|
+
How many physics ticks worth of firework rocket boost are left.
|
|
1047
|
+
|
|
1040
1048
|
#### bot.simpleClick.leftMouse (slot)
|
|
1041
1049
|
|
|
1042
1050
|
abstraction over `bot.clickWindow(slot, 0, 0)`
|
|
@@ -1301,6 +1309,10 @@ Fires when an attribute of an entity changes.
|
|
|
1301
1309
|
#### "entityEquip" (entity)
|
|
1302
1310
|
#### "entitySleep" (entity)
|
|
1303
1311
|
#### "entitySpawn" (entity)
|
|
1312
|
+
#### "entityElytraFlew" (entity)
|
|
1313
|
+
|
|
1314
|
+
An entity started elytra flying.
|
|
1315
|
+
|
|
1304
1316
|
#### "itemDrop" (entity)
|
|
1305
1317
|
#### "playerCollect" (collector, collected)
|
|
1306
1318
|
|
|
@@ -1417,6 +1429,10 @@ This occurs whether the process was completed or aborted.
|
|
|
1417
1429
|
|
|
1418
1430
|
* `block` - the block that still exists
|
|
1419
1431
|
|
|
1432
|
+
#### "usedfirework"
|
|
1433
|
+
|
|
1434
|
+
Fires when the bot uses a firework while elytra flying.
|
|
1435
|
+
|
|
1420
1436
|
#### "move"
|
|
1421
1437
|
|
|
1422
1438
|
Fires when the bot moves. If you want the current position, use
|
|
@@ -1851,6 +1867,11 @@ This function returns a `Promise`, with `void` as its argument once tossing is c
|
|
|
1851
1867
|
to match any metadata
|
|
1852
1868
|
* `count` - how many you want to toss. `null` is an alias for `1`.
|
|
1853
1869
|
|
|
1870
|
+
#### bot.elytraFly()
|
|
1871
|
+
|
|
1872
|
+
This function returns a `Promise`, with `void` as its argument once activating
|
|
1873
|
+
elytra flight is complete. It will throw an Error if it fails.
|
|
1874
|
+
|
|
1854
1875
|
#### bot.dig(block, [forceLook = true], [digFace])
|
|
1855
1876
|
|
|
1856
1877
|
This function returns a `Promise`, with `void` as its argument when the block is broken or you are interrupted.
|
|
@@ -1946,7 +1967,9 @@ Use fishing rod
|
|
|
1946
1967
|
|
|
1947
1968
|
#### bot.activateItem(offHand=false)
|
|
1948
1969
|
|
|
1949
|
-
Activates the currently held item. This is how you eat, shoot bows, throw an
|
|
1970
|
+
Activates the currently held item. This is how you eat, shoot bows, throw an
|
|
1971
|
+
egg, activate firework rockets, etc.
|
|
1972
|
+
|
|
1950
1973
|
Optional parameter is `false` for main hand and `true` for off hand.
|
|
1951
1974
|
|
|
1952
1975
|
#### bot.deactivateItem()
|
package/docs/history.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 4.14.0
|
|
2
|
+
* [Update Jupyter notebook to install node 18, update the server in example (#3176)](https://github.com/PrismarineJS/mineflayer/commit/e8a967d4e832f72d665781492c037d26169ae5a0) (thanks @extremeheat)
|
|
3
|
+
* [Update index.d.ts (#3175)](https://github.com/PrismarineJS/mineflayer/commit/d4db3991c135344180937b69621c0ee31daa39f0) (thanks @StayWithMeSenpai)
|
|
4
|
+
* [Add elytra flying support and rocket support (#3163)](https://github.com/PrismarineJS/mineflayer/commit/010460e9dd752a56195d8a48f35a62e704dcf99f) (thanks @lkwilson)
|
|
5
|
+
|
|
6
|
+
## 4.13.0
|
|
7
|
+
* [Switch to entity.displayName (#3168)](https://github.com/PrismarineJS/mineflayer/commit/2409ad458b952173de669a7d9cfaeb770effe3ae) (thanks @lkwilson)
|
|
8
|
+
* [Update readme auth doc (#3169)](https://github.com/PrismarineJS/mineflayer/commit/f5d4a288a768ca6717fa4d22c72fb0267428c684) (thanks @extremeheat)
|
|
9
|
+
* [Add OpenDeliveryBot to "Projects Using Mineflayer" (#3162)](https://github.com/PrismarineJS/mineflayer/commit/ab3c0cf25d0cc28ccba89640b2ceff6ab6b4dace) (thanks @SilkePilon)
|
|
10
|
+
* [Use node 18 on CI (#3157)](https://github.com/PrismarineJS/mineflayer/commit/d3df34dcaa804a71bf0d8cc50a419990d4a2dce3) (thanks @extremeheat)
|
|
11
|
+
* [Fix ambigious function naming (#3161)](https://github.com/PrismarineJS/mineflayer/commit/9ecdf201794bfa350486839a01e318dfd94b3bfb) (thanks @frej4189)
|
|
12
|
+
|
|
1
13
|
## 4.12.0
|
|
2
14
|
* [Mineflayer physics refactor (#2492)](https://github.com/PrismarineJS/mineflayer/commit/d0eb3a1afe6cda7b04ae2f88052cd868ba0c0c4f) (thanks @U5B)
|
|
3
15
|
|
package/docs/mineflayer.ipynb
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"source": [
|
|
37
37
|
"# Using mineflayer in Python\n",
|
|
38
38
|
"\n",
|
|
39
|
-
"This is a tutorial on how to use mineflayer in Python. This example will connect you to the PrismarineJS test server. You can join it with prismarine-viewer or your Minecraft client at server IP **
|
|
39
|
+
"This is a tutorial on how to use mineflayer in Python. This example will connect you to the PrismarineJS test server. You can join it with prismarine-viewer or your Minecraft client at server IP **pjs.deptofcraft.com:25565**.\n",
|
|
40
40
|
"\n",
|
|
41
41
|
"If you're new to Jupyter Notebooks, you can press the \"Play\" button at the left of each code block to run it. Make sure that you run the blocks in a correct order."
|
|
42
42
|
]
|
|
@@ -56,32 +56,35 @@
|
|
|
56
56
|
"id": "K2ol06QOhL6s"
|
|
57
57
|
},
|
|
58
58
|
"source": [
|
|
59
|
-
"First, make sure you have Python version 3.
|
|
59
|
+
"First, make sure you have Python version 3.10 and Node.js version 18 or newer installed. You can get Node.js 18 it from https://nodejs.org/en/download or use [Node.js version managers](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm#using-a-node-version-manager-to-install-nodejs-and-npm) like [`nvm`](https://github.com/creationix/nvm) or [`n`](https://github.com/tj/n) to install via the command line. Here we'll use `n` to install Node.js v18, then check our Node and Python versions:"
|
|
60
60
|
]
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
"cell_type": "code",
|
|
64
|
+
"execution_count": 1,
|
|
64
65
|
"metadata": {
|
|
65
66
|
"colab": {
|
|
66
67
|
"base_uri": "https://localhost:8080/"
|
|
67
68
|
},
|
|
68
69
|
"id": "8zCSpx8Bif5m",
|
|
69
|
-
"outputId": "
|
|
70
|
+
"outputId": "90ebac14-fc75-4136-f81d-34c5b2033da0"
|
|
70
71
|
},
|
|
71
|
-
"source": [
|
|
72
|
-
"!python --version\n",
|
|
73
|
-
"!node --version"
|
|
74
|
-
],
|
|
75
|
-
"execution_count": null,
|
|
76
72
|
"outputs": [
|
|
77
73
|
{
|
|
74
|
+
"name": "stdout",
|
|
78
75
|
"output_type": "stream",
|
|
79
76
|
"text": [
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
]
|
|
83
|
-
"name": "stdout"
|
|
77
|
+
"v18.17.1\n",
|
|
78
|
+
"Python 3.10.12\n"
|
|
79
|
+
]
|
|
84
80
|
}
|
|
81
|
+
],
|
|
82
|
+
"source": [
|
|
83
|
+
"# Use `n` to install nodejs 18, if it's not already installed:\n",
|
|
84
|
+
"!curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n | bash -s lts > /dev/null\n",
|
|
85
|
+
"# Now write the Node.js and Python version to the console\n",
|
|
86
|
+
"!node --version\n",
|
|
87
|
+
"!python --version"
|
|
85
88
|
]
|
|
86
89
|
},
|
|
87
90
|
{
|
|
@@ -121,7 +124,7 @@
|
|
|
121
124
|
"source": [
|
|
122
125
|
"If all is well, we can import the `javascript` library. We can then import the `require` function which works similarly to the `require` function in Node.js, but does the dependency management for us.\n",
|
|
123
126
|
"\n",
|
|
124
|
-
"You may notice the extra imports : On, Once, off and AsyncTask. These will be discussed later on
|
|
127
|
+
"You may notice the extra imports : On, Once, off and AsyncTask. These will be discussed later on.\n",
|
|
125
128
|
"\n",
|
|
126
129
|
"\n"
|
|
127
130
|
]
|
|
@@ -170,21 +173,21 @@
|
|
|
170
173
|
},
|
|
171
174
|
{
|
|
172
175
|
"cell_type": "code",
|
|
176
|
+
"execution_count": null,
|
|
173
177
|
"metadata": {
|
|
174
178
|
"id": "1gfZSAUCDVMg"
|
|
175
179
|
},
|
|
180
|
+
"outputs": [],
|
|
176
181
|
"source": [
|
|
177
182
|
"random_number = id([]) % 1000 # Give us a random number upto 1000\n",
|
|
178
183
|
"BOT_USERNAME = f'colab_{random_number}'\n",
|
|
179
184
|
"\n",
|
|
180
|
-
"bot = mineflayer.createBot({ 'host': '
|
|
185
|
+
"bot = mineflayer.createBot({ 'host': 'pjs.deptofcraft.com', 'port': 25565, 'username': BOT_USERNAME, 'hideErrors': False })\n",
|
|
181
186
|
"\n",
|
|
182
|
-
"# The spawn event
|
|
187
|
+
"# The spawn event\n",
|
|
183
188
|
"once(bot, 'login')\n",
|
|
184
189
|
"bot.chat('I spawned')"
|
|
185
|
-
]
|
|
186
|
-
"execution_count": null,
|
|
187
|
-
"outputs": []
|
|
190
|
+
]
|
|
188
191
|
},
|
|
189
192
|
{
|
|
190
193
|
"cell_type": "markdown",
|
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) => {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// This example will shoot the player that said "fire" in chat, when it is said in chat.
|
|
2
|
+
const mineflayer = require('mineflayer')
|
|
3
|
+
|
|
4
|
+
if (process.argv.length < 4 || process.argv.length > 6) {
|
|
5
|
+
console.log('Usage : node elytra.js <host> <port> [<name>] [<password>]')
|
|
6
|
+
process.exit(1)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const bot = mineflayer.createBot({
|
|
10
|
+
host: process.argv[2],
|
|
11
|
+
port: parseInt(process.argv[3]),
|
|
12
|
+
username: process.argv[4] ? process.argv[4] : 'elytraer',
|
|
13
|
+
password: process.argv[5]
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
bot.on('error', err => {
|
|
17
|
+
console.log(err)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
bot.on('kicked', err => {
|
|
21
|
+
console.log(err)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
bot.on('spawn', async function () {
|
|
25
|
+
bot.chat(`/give ${bot.username} minecraft:elytra`)
|
|
26
|
+
bot.chat(`/give ${bot.username} minecraft:firework_rocket 64`)
|
|
27
|
+
|
|
28
|
+
await sleep(1000)
|
|
29
|
+
const elytraItem = bot.inventory.slots.find(item => item?.name === 'elytra')
|
|
30
|
+
if (elytraItem == null) {
|
|
31
|
+
console.log('no elytra')
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
await bot.equip(elytraItem, 'torso')
|
|
35
|
+
const fireworkItem = bot.inventory.slots.find(item => item?.name === 'firework_rocket')
|
|
36
|
+
if (fireworkItem == null) {
|
|
37
|
+
console.log('no fireworks')
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
await bot.equip(fireworkItem, 'hand')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
bot.on('chat', async (username, message) => {
|
|
44
|
+
if (message === 'fly') {
|
|
45
|
+
await bot.look(bot.entity.yaw, 50 * Math.PI / 180)
|
|
46
|
+
bot.setControlState('jump', true)
|
|
47
|
+
bot.setControlState('jump', false)
|
|
48
|
+
await sleep(50)
|
|
49
|
+
|
|
50
|
+
// try to fly
|
|
51
|
+
try {
|
|
52
|
+
await bot.elytraFly()
|
|
53
|
+
} catch (err) {
|
|
54
|
+
bot.chat(`Failed to fly: ${err}`)
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
await sleep(50)
|
|
58
|
+
|
|
59
|
+
// use rocket
|
|
60
|
+
bot.activateItem()
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
function sleep (ms) {
|
|
65
|
+
return new Promise(resolve => setTimeout(resolve, ms))
|
|
66
|
+
}
|
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.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { Recipe } from 'prismarine-recipe'
|
|
|
8
8
|
import { Block } from 'prismarine-block'
|
|
9
9
|
import { Entity } from 'prismarine-entity'
|
|
10
10
|
import { ChatMessage } from 'prismarine-chat'
|
|
11
|
+
import { world } from 'prismarine-world'
|
|
11
12
|
import { Registry } from 'prismarine-registry'
|
|
12
13
|
|
|
13
14
|
export function createBot (options: { client: Client } & Partial<BotOptions>): Bot
|
|
@@ -92,6 +93,8 @@ export interface BotEvents {
|
|
|
92
93
|
entityEquip: (entity: Entity) => Promise<void> | void
|
|
93
94
|
entitySleep: (entity: Entity) => Promise<void> | void
|
|
94
95
|
entitySpawn: (entity: Entity) => Promise<void> | void
|
|
96
|
+
entityElytraFlew: (entity: Entity) => Promise<void> | void
|
|
97
|
+
usedFirework: () => Promise<void> | void
|
|
95
98
|
itemDrop: (entity: Entity) => Promise<void> | void
|
|
96
99
|
playerCollect: (collector: Entity, collected: Entity) => Promise<void> | void
|
|
97
100
|
entityAttributes: (entity: Entity) => Promise<void> | void
|
|
@@ -164,6 +167,7 @@ export interface Bot extends TypedEmitter<BotEvents> {
|
|
|
164
167
|
version: string
|
|
165
168
|
entity: Entity
|
|
166
169
|
entities: { [id: string]: Entity }
|
|
170
|
+
fireworkRocketDuration: number
|
|
167
171
|
spawnPoint: Vec3
|
|
168
172
|
game: GameState
|
|
169
173
|
player: Player
|
|
@@ -189,7 +193,7 @@ export interface Bot extends TypedEmitter<BotEvents> {
|
|
|
189
193
|
teamMap: { [name: string]: Team }
|
|
190
194
|
controlState: ControlStateStatus
|
|
191
195
|
creative: creativeMethods
|
|
192
|
-
world:
|
|
196
|
+
world: world.World
|
|
193
197
|
_client: Client
|
|
194
198
|
heldItem: Item | null
|
|
195
199
|
usingHeldItem: boolean
|
|
@@ -260,6 +264,8 @@ export interface Bot extends TypedEmitter<BotEvents> {
|
|
|
260
264
|
|
|
261
265
|
wake: () => Promise<void>
|
|
262
266
|
|
|
267
|
+
elytraFly: () => Promise<void>
|
|
268
|
+
|
|
263
269
|
setControlState: (control: ControlState, state: boolean) => void
|
|
264
270
|
|
|
265
271
|
getControlState: (control: ControlState) => boolean
|
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'
|
|
@@ -361,6 +358,70 @@ function inject (bot) {
|
|
|
361
358
|
}
|
|
362
359
|
})
|
|
363
360
|
|
|
361
|
+
bot.fireworkRocketDuration = 0
|
|
362
|
+
function setElytraFlyingState (entity, elytraFlying) {
|
|
363
|
+
let startedFlying = false
|
|
364
|
+
if (elytraFlying) {
|
|
365
|
+
startedFlying = !entity.elytraFlying
|
|
366
|
+
entity.elytraFlying = true
|
|
367
|
+
} else if (entity.elytraFlying) {
|
|
368
|
+
entity.elytraFlying = false
|
|
369
|
+
}
|
|
370
|
+
if (bot.fireworkRocketDuration !== 0 && entity.id === bot.entity?.id && !elytraFlying) {
|
|
371
|
+
bot.fireworkRocketDuration = 0
|
|
372
|
+
knownFireworks.splice(0, knownFireworks.length)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (startedFlying) {
|
|
376
|
+
bot.emit('entityElytraFlew', entity)
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const knownFireworks = []
|
|
381
|
+
function handleBotUsedFireworkRocket (fireworkEntityId, fireworkInfo) {
|
|
382
|
+
if (knownFireworks.includes(fireworkEntityId)) return
|
|
383
|
+
knownFireworks.push(fireworkEntityId)
|
|
384
|
+
let flightDur = 1
|
|
385
|
+
if (fireworkInfo?.nbtData != null) {
|
|
386
|
+
let nbt = fireworkInfo.nbtData
|
|
387
|
+
if (nbt.type === 'compound' && nbt.value.Fireworks != null) {
|
|
388
|
+
nbt = nbt.value.Fireworks
|
|
389
|
+
if (nbt.type === 'compound' && nbt.value.Flight != null) {
|
|
390
|
+
nbt = nbt.value.Flight
|
|
391
|
+
if (nbt.type === 'int') {
|
|
392
|
+
flightDur += nbt.value
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
const baseDuration = 10 * flightDur
|
|
398
|
+
const randomDuration = Math.floor(Math.random() * 6) + Math.floor(Math.random() * 7)
|
|
399
|
+
bot.fireworkRocketDuration = baseDuration + randomDuration
|
|
400
|
+
|
|
401
|
+
bot.emit('usedFirework')
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
let fireworkEntityName
|
|
405
|
+
if (bot.supportFeature('fireworkNamePlural')) {
|
|
406
|
+
fireworkEntityName = 'fireworks_rocket'
|
|
407
|
+
} else if (bot.supportFeature('fireworkNameSingular')) {
|
|
408
|
+
fireworkEntityName = 'firework_rocket'
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
let fireworkMetadataIdx
|
|
412
|
+
let fireworkMetadataIsOpt
|
|
413
|
+
if (bot.supportFeature('fireworkMetadataVarInt7')) {
|
|
414
|
+
fireworkMetadataIdx = 7
|
|
415
|
+
fireworkMetadataIsOpt = false
|
|
416
|
+
} else if (bot.supportFeature('fireworkMetadataOptVarInt8')) {
|
|
417
|
+
fireworkMetadataIdx = 8
|
|
418
|
+
fireworkMetadataIsOpt = true
|
|
419
|
+
} else if (bot.supportFeature('fireworkMetadataOptVarInt9')) {
|
|
420
|
+
fireworkMetadataIdx = 9
|
|
421
|
+
fireworkMetadataIsOpt = true
|
|
422
|
+
}
|
|
423
|
+
const hasFireworkSupport = fireworkEntityName !== undefined && fireworkMetadataIdx !== undefined && fireworkMetadataIsOpt !== undefined
|
|
424
|
+
|
|
364
425
|
bot._client.on('entity_metadata', (packet) => {
|
|
365
426
|
// entity metadata
|
|
366
427
|
const entity = fetchEntity(packet.entityId)
|
|
@@ -377,7 +438,25 @@ function inject (bot) {
|
|
|
377
438
|
if (metas.sleeping_pos || metas.pose === 2) {
|
|
378
439
|
bot.emit('entitySleep', entity)
|
|
379
440
|
}
|
|
441
|
+
|
|
442
|
+
if (hasFireworkSupport && fireworkEntityName === entity.name && metas.attached_to_target !== undefined) {
|
|
443
|
+
// fireworkMetadataOptVarInt9 and later is implied by
|
|
444
|
+
// mcDataHasEntityMetadata, so no need to check metadata index and type
|
|
445
|
+
// (eg fireworkMetadataOptVarInt8)
|
|
446
|
+
if (metas.attached_to_target !== 0) {
|
|
447
|
+
const entityId = metas.attached_to_target - 1
|
|
448
|
+
if (entityId === bot.entity?.id) {
|
|
449
|
+
handleBotUsedFireworkRocket(entity.id, metas.fireworks_item)
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
380
454
|
if (metas.shared_flags != null) {
|
|
455
|
+
if (bot.supportFeature('hasElytraFlying')) {
|
|
456
|
+
const elytraFlying = metas.shared_flags & 0x80
|
|
457
|
+
setElytraFlyingState(entity, Boolean(elytraFlying))
|
|
458
|
+
}
|
|
459
|
+
|
|
381
460
|
if (metas.shared_flags & 2) {
|
|
382
461
|
entity.crouching = true
|
|
383
462
|
bot.emit('entityCrouch', entity)
|
|
@@ -399,16 +478,38 @@ function inject (bot) {
|
|
|
399
478
|
bot.emit('entitySleep', entity)
|
|
400
479
|
}
|
|
401
480
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
481
|
+
if (hasFireworkSupport && fireworkEntityName === entity.name) {
|
|
482
|
+
const attachedToTarget = packet.metadata.find(e => e.key === fireworkMetadataIdx)
|
|
483
|
+
if (attachedToTarget !== undefined) {
|
|
484
|
+
let entityId
|
|
485
|
+
if (fireworkMetadataIsOpt) {
|
|
486
|
+
if (attachedToTarget.value !== 0) {
|
|
487
|
+
entityId = attachedToTarget.value - 1
|
|
488
|
+
} // else, not attached to an entity
|
|
489
|
+
} else {
|
|
490
|
+
entityId = attachedToTarget.value
|
|
491
|
+
}
|
|
492
|
+
if (entityId !== undefined && entityId === bot.entity?.id) {
|
|
493
|
+
const fireworksItem = packet.metadata.find(e => e.key === (fireworkMetadataIdx - 1))
|
|
494
|
+
handleBotUsedFireworkRocket(entity.id, fireworksItem?.value)
|
|
495
|
+
}
|
|
496
|
+
}
|
|
405
497
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
498
|
+
|
|
499
|
+
const bitField = packet.metadata.find(p => p.key === 0)
|
|
500
|
+
if (bitField !== undefined) {
|
|
501
|
+
if (bot.supportFeature('hasElytraFlying')) {
|
|
502
|
+
const elytraFlying = bitField.value & 0x80
|
|
503
|
+
setElytraFlyingState(entity, Boolean(elytraFlying))
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if ((bitField.value & 2) !== 0) {
|
|
507
|
+
entity.crouching = true
|
|
508
|
+
bot.emit('entityCrouch', entity)
|
|
509
|
+
} else if (entity.crouching) { // prevent the initial entity_metadata packet from firing off an uncrouch event
|
|
510
|
+
entity.crouching = false
|
|
511
|
+
bot.emit('entityUncrouch', entity)
|
|
512
|
+
}
|
|
412
513
|
}
|
|
413
514
|
}
|
|
414
515
|
})
|
package/lib/plugins/physics.js
CHANGED
|
@@ -138,8 +138,8 @@ function inject (bot, { physicsEnabled, maxCatchupTicks }) {
|
|
|
138
138
|
return dYaw
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
// returns false if
|
|
142
|
-
function
|
|
141
|
+
// returns false if bot should send position packets
|
|
142
|
+
function isEntityRemoved () {
|
|
143
143
|
if (bot.isAlive === true) deadTicks = 0
|
|
144
144
|
if (bot.isAlive === false && deadTicks <= 20) deadTicks++
|
|
145
145
|
if (deadTicks >= 20) return true
|
|
@@ -148,7 +148,7 @@ function inject (bot, { physicsEnabled, maxCatchupTicks }) {
|
|
|
148
148
|
|
|
149
149
|
function updatePosition (now) {
|
|
150
150
|
// Only send updates for 20 ticks after death
|
|
151
|
-
if (
|
|
151
|
+
if (isEntityRemoved()) return
|
|
152
152
|
|
|
153
153
|
// Increment the yaw in baby steps so that notchian clients (not the server) can keep up.
|
|
154
154
|
const dYaw = deltaYaw(bot.entity.yaw, lastSentYaw)
|
|
@@ -192,6 +192,44 @@ function inject (bot, { physicsEnabled, maxCatchupTicks }) {
|
|
|
192
192
|
|
|
193
193
|
bot.physics = physics
|
|
194
194
|
|
|
195
|
+
function getEffectLevel (mcData, effectName, effects) {
|
|
196
|
+
const effectDescriptor = mcData.effectsByName[effectName]
|
|
197
|
+
if (!effectDescriptor) {
|
|
198
|
+
return 0
|
|
199
|
+
}
|
|
200
|
+
const effectInfo = effects[effectDescriptor.id]
|
|
201
|
+
if (!effectInfo) {
|
|
202
|
+
return 0
|
|
203
|
+
}
|
|
204
|
+
return effectInfo.amplifier + 1
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
bot.elytraFly = async () => {
|
|
208
|
+
if (bot.entity.elytraFlying) {
|
|
209
|
+
throw new Error('Already elytra flying')
|
|
210
|
+
} else if (bot.entity.onGround) {
|
|
211
|
+
throw new Error('Unable to fly from ground')
|
|
212
|
+
} else if (bot.entity.isInWater) {
|
|
213
|
+
throw new Error('Unable to elytra fly while in water')
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const mcData = require('minecraft-data')(bot.version)
|
|
217
|
+
if (getEffectLevel(mcData, 'Levitation', bot.entity.effects) > 0) {
|
|
218
|
+
throw new Error('Unable to elytra fly with levitation effect')
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const torsoSlot = bot.getEquipmentDestSlot('torso')
|
|
222
|
+
const item = bot.inventory.slots[torsoSlot]
|
|
223
|
+
if (item == null || item.name !== 'elytra') {
|
|
224
|
+
throw new Error('Elytra must be equip to start flying')
|
|
225
|
+
}
|
|
226
|
+
bot._client.write('entity_action', {
|
|
227
|
+
entityId: bot.entity.id,
|
|
228
|
+
actionId: 8,
|
|
229
|
+
jumpBoost: 0
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
|
|
195
233
|
bot.setControlState = (control, state) => {
|
|
196
234
|
assert.ok(control in controlState, `invalid control: ${control}`)
|
|
197
235
|
assert.ok(typeof state === 'boolean', `invalid state: ${state}`)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mineflayer",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.14.0",
|
|
4
4
|
"description": "create minecraft bots with a stable, high level API",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -21,16 +21,16 @@
|
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"minecraft-data": "^3.
|
|
24
|
+
"minecraft-data": "^3.44.0",
|
|
25
25
|
"minecraft-protocol": "^1.44.0",
|
|
26
26
|
"prismarine-biome": "^1.1.1",
|
|
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
|
-
"prismarine-physics": "^1.
|
|
33
|
+
"prismarine-physics": "^1.8.0",
|
|
34
34
|
"prismarine-recipe": "^1.3.0",
|
|
35
35
|
"prismarine-registry": "^1.5.0",
|
|
36
36
|
"prismarine-windows": "^2.8.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
|