mineflayer 4.13.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/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 egg, etc.
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,8 @@
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
+
1
6
  ## 4.13.0
2
7
  * [Switch to entity.displayName (#3168)](https://github.com/PrismarineJS/mineflayer/commit/2409ad458b952173de669a7d9cfaeb770effe3ae) (thanks @lkwilson)
3
8
  * [Update readme auth doc (#3169)](https://github.com/PrismarineJS/mineflayer/commit/f5d4a288a768ca6717fa4d22c72fb0267428c684) (thanks @extremeheat)
@@ -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 **95.111.249.143:10000**.\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 **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.7 and Node.js version 14 or newer installed"
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": "f8888a33-03e7-4497-9776-ef6c34d9d337"
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
- "Python 3.7.11\n",
81
- "v14.16.0\n"
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. \n",
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': '95.111.249.143', 'port': 10000, 'username': BOT_USERNAME, 'hideErrors': False })\n",
185
+ "bot = mineflayer.createBot({ 'host': 'pjs.deptofcraft.com', 'port': 25565, 'username': BOT_USERNAME, 'hideErrors': False })\n",
181
186
  "\n",
182
- "# The spawn event \n",
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",
@@ -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/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: any
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
@@ -358,6 +358,70 @@ function inject (bot) {
358
358
  }
359
359
  })
360
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
+
361
425
  bot._client.on('entity_metadata', (packet) => {
362
426
  // entity metadata
363
427
  const entity = fetchEntity(packet.entityId)
@@ -374,7 +438,25 @@ function inject (bot) {
374
438
  if (metas.sleeping_pos || metas.pose === 2) {
375
439
  bot.emit('entitySleep', entity)
376
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
+
377
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
+
378
460
  if (metas.shared_flags & 2) {
379
461
  entity.crouching = true
380
462
  bot.emit('entityCrouch', entity)
@@ -396,16 +478,38 @@ function inject (bot) {
396
478
  bot.emit('entitySleep', entity)
397
479
  }
398
480
 
399
- const bitField = packet.metadata.find(p => p.key === 0)
400
- if (bitField === undefined) {
401
- return
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
+ }
402
497
  }
403
- if ((bitField.value & 2) !== 0) {
404
- entity.crouching = true
405
- bot.emit('entityCrouch', entity)
406
- } else if (entity.crouching) { // prevent the initial entity_metadata packet from firing off an uncrouch event
407
- entity.crouching = false
408
- bot.emit('entityUncrouch', entity)
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
+ }
409
513
  }
410
514
  }
411
515
  })
@@ -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.13.0",
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,7 +21,7 @@
21
21
  },
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
- "minecraft-data": "^3.37.0",
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",
@@ -30,7 +30,7 @@
30
30
  "prismarine-entity": "^2.3.0",
31
31
  "prismarine-item": "^1.14.0",
32
32
  "prismarine-nbt": "^2.0.0",
33
- "prismarine-physics": "^1.7.0",
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",