mineflayer 4.29.0 → 4.31.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
@@ -764,11 +764,11 @@ Determines what color the boss bar color is, one of `pink`, `blue`, `red`, `gree
764
764
 
765
765
  #### Particle.id
766
766
 
767
- Particle ID, as defined in the [protocol](https://wiki.vg/Protocol#Particle)
767
+ Particle ID, as defined in the [protocol](https://minecraft.wiki/w/Protocol#Particle)
768
768
 
769
769
  #### Particle.name
770
770
 
771
- Particle Name, as defined in the [protocol](https://wiki.vg/Protocol#Particle)
771
+ Particle Name, as defined in the [protocol](https://minecraft.wiki/w/Protocol#Particle)
772
772
 
773
773
  #### Particle.position
774
774
 
@@ -1139,7 +1139,7 @@ All scoreboards known to the bot in an object scoreboard displaySlot -> scoreboa
1139
1139
  * `belowName` - scoreboard placed in belowName
1140
1140
  * `sidebar` - scoreboard placed in sidebar
1141
1141
  * `list` - scoreboard placed in list
1142
- * `0-18` - slots defined in [protocol](https://wiki.vg/Protocol#Display_Scoreboard)
1142
+ * `0-18` - slots defined in [protocol](https://minecraft.wiki/w/Protocol#Display_Scoreboard)
1143
1143
 
1144
1144
  #### bot.teams
1145
1145
 
@@ -2158,7 +2158,7 @@ mode support:
2158
2158
  - drag clicks (5)
2159
2159
  - double clicks (6)
2160
2160
 
2161
- Click on the current window. See details at https://wiki.vg/Protocol#Click_Container
2161
+ Click on the current window. See details at https://minecraft.wiki/w/Protocol#Click_Container
2162
2162
 
2163
2163
  Prefer using bot.simpleClick.*
2164
2164
 
package/docs/br/api_br.md CHANGED
@@ -1920,7 +1920,7 @@ Esses são métodos de nível mais baixo para o inventário e podem ser úteis e
1920
1920
 
1921
1921
  Esta função também retorna uma `Promise`, com `void` como argumento quando concluída.
1922
1922
 
1923
- Clique na janela/interface atual; os detalhes estão em https://wiki.vg/Protocol#Click_Window
1923
+ Clique na janela/interface atual; os detalhes estão em https://minecraft.wiki/w/Protocol#Click_Window
1924
1924
  * slot - número que representa a posição na janela
1925
1925
  * mouseButton - 0 para clique esquerdo e 1 para clique direito
1926
1926
  * mode - mineflayer só tem o modo 0 disponível
package/docs/es/api_es.md CHANGED
@@ -993,7 +993,7 @@ Todos los scoreboards que el bot conoce en un object de forma casilla de visuali
993
993
  * `belowName` - scoreboard que está debajo del nombre
994
994
  * `sidebar` - scoreboard que está en la barra del lado
995
995
  * `list` - scoreboard que está en la lista
996
- * `0-18` - casillas definidas en el [protocol](https://wiki.vg/Protocol#Display_Scoreboard)
996
+ * `0-18` - casillas definidas en el [protocol](https://minecraft.wiki/w/Protocol#Display_Scoreboard)
997
997
 
998
998
  #### bot.controlState
999
999
 
@@ -1931,7 +1931,7 @@ Estos son métodos de un nivel más bajo para el inventario, pueden ser útils a
1931
1931
 
1932
1932
  Esta función también devueve un `Promise`, con `void` como argumento al finalizar.
1933
1933
 
1934
- Hacer click en la ventana/interfaz actual, los detalles están en https://wiki.vg/Protocol#Click_Window
1934
+ Hacer click en la ventana/interfaz actual, los detalles están en https://minecraft.wiki/w/Protocol#Click_Window
1935
1935
  * slot - número que representa la casilla de la ventan
1936
1936
  * mouseButton - 0 para click izquierdo, y 1 para click derecho
1937
1937
  * mode - mineflayer solo tiene disponible el modo 0
package/docs/history.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 4.31.0
2
+ * [Cursor 1 21 5 (#3701)](https://github.com/PrismarineJS/mineflayer/commit/8770129d26a85f9b077d2a8969d45436fa09c3f3) (thanks @rom1504)
3
+
4
+ ## 4.30.0
5
+ * [Update player_info handling (#3689)](https://github.com/PrismarineJS/mineflayer/commit/3f2fd6d393bc39167410df5a292759c93c9b249f) (thanks @extremeheat)
6
+ * [Bump @types/node from 22.15.33 to 24.0.6 (#3686)](https://github.com/PrismarineJS/mineflayer/commit/12e50a2e2d0a921d075ebae8aa835437672a2b29) (thanks @dependabot[bot])
7
+ * [Replace wiki.vg by minecraft.wiki. Close #3596](https://github.com/PrismarineJS/mineflayer/commit/c2794e43da71b346278818ff68acb690ec66a4fb) (thanks @rom1504)
8
+
1
9
  ## 4.29.0
2
10
  * [Sound test (#3657)](https://github.com/PrismarineJS/mineflayer/commit/51495665bbc3789ddc4284403c1ef288fea18ddc) (thanks @rom1504)
3
11
  * [Add boss bar test (#3655)](https://github.com/PrismarineJS/mineflayer/commit/b6950e9c42324c0f6fba6f2f802d0c87973a8c92) (thanks @rom1504)
package/docs/ru/api_ru.md CHANGED
@@ -773,11 +773,11 @@ UUID существа, который определяется боссом.
773
773
 
774
774
  #### Particle.id
775
775
 
776
- Идентификатор частицы, который прописан в [протоколе](https://wiki.vg/Protocol#Particle).
776
+ Идентификатор частицы, который прописан в [протоколе](https://minecraft.wiki/w/Protocol#Particle).
777
777
 
778
778
  #### Particle.name
779
779
 
780
- Название частицы, которое прописано в [протоколе](https://wiki.vg/Protocol#Particle).
780
+ Название частицы, которое прописано в [протоколе](https://minecraft.wiki/w/Protocol#Particle).
781
781
 
782
782
  #### Particle.position
783
783
 
@@ -1170,7 +1170,7 @@ UUID существа, который определяется боссом.
1170
1170
  * `belowName` - Cкорборд размещен снизу никнейма.
1171
1171
  * `sidebar` - Cкорборд размещен на боковой панели.
1172
1172
  * `list` - Cкорборд помещен в список игроков.
1173
- * `0-18` - Cлоты, определённые в [протоколе](https://wiki.vg/Protocol#Display_Scoreboard).
1173
+ * `0-18` - Cлоты, определённые в [протоколе](https://minecraft.wiki/w/Protocol#Display_Scoreboard).
1174
1174
 
1175
1175
  #### bot.teams
1176
1176
 
@@ -2120,7 +2120,7 @@ bot.once('login', () => {
2120
2120
 
2121
2121
  Единственное действительное значение для `mode` - 0. Нажатие с шифтом или перемещение через мышь не реализовано.
2122
2122
 
2123
- Нажимает на текущее окно. Подробнее - https://wiki.vg/Protocol#Click_Container
2123
+ Нажимает на текущее окно. Подробнее - https://minecraft.wiki/w/Protocol#Click_Container
2124
2124
 
2125
2125
  Рекомендуется использовать `bot.simpleClick.*`
2126
2126
 
@@ -0,0 +1,342 @@
1
+ # Mineflayer 1.21.5 Support Plan
2
+
3
+ ## 🚩 Latest Progress (July 2025)
4
+
5
+ - ✅ **Chunk loading/parsing is now fixed** in both `node_modules` and the local `prismarine-chunk` repo. The fix was applied to `PaletteChunkSection.js` and `BitArrayNoSpan.js`.
6
+ - 🔗 **Local development uses `npm link` to the local prismarine-chunk repo** for immediate testing of fixes.
7
+ - 🛠️ **BitArrayNoSpan.js** now validates the buffer size and logs a warning if it is invalid (e.g., Infinity), preventing crashes.
8
+ - 🤖 **The bot can now spawn and interact with the world** in 1.21.5. Chunk parsing errors are resolved.
9
+ - ✅ **12 tests pass** for 1.21.5, confirming core protocol and chunk logic is working.
10
+ - ❌ **4 tests fail**, but these are due to higher-level Mineflayer/game logic (timeouts, creative set slot, etc.), not chunk/protocol errors.
11
+ - 🚧 **Current blockers:**
12
+ - Creative set slot protocol changes (UntrustedSlot)
13
+ - declare_commands packet parsing (PartialReadError)
14
+
15
+ ---
16
+
17
+ ## Current Status
18
+
19
+ As of July 2025, Mineflayer has partial 1.21.5 support with several critical issues remaining. The version is already listed in `testedVersions` but tests are failing due to protocol changes in 1.21.5.
20
+
21
+ ## Key Issues Identified
22
+
23
+ Based on the analysis of pull requests and issues, the main problems for 1.21.5 support are:
24
+
25
+ ### 1. Chunk Protocol Changes (✅ FIXED)
26
+ - **Issue**: Network has small changes to chunk format where size is now auto-computed to save a byte
27
+ - **Status**: **RESOLVED** - Fixed size computation formula in prismarine-chunk
28
+ - **Fix Applied**: Changed from `Math.ceil(constants.BLOCK_SECTION_VOLUME * bitsPerValue / 64)` to `Math.ceil(constants.BLOCK_SECTION_VOLUME / Math.floor(64 / bitsPerValue))`
29
+ - **Impact**: Chunk loading now works correctly for 1.21.5
30
+ - **Files Modified**:
31
+ - `prismarine-chunk/src/pc/common/PaletteContainer.js` (both DirectPaletteContainer and IndirectPaletteContainer)
32
+ - **Dependencies**: Updated package.json to point to fixed prismarine-chunk branch
33
+
34
+ ### 2. Creative Set Slot Packet Behavior
35
+ - **Issue**: Creative set slot packet behavior is the main breaking change (not working right now)
36
+ - **Status**: Critical issue affecting creative mode functionality
37
+ - **Impact**: `bot.creative.setInventorySlot()` fails
38
+ - **Location**: `lib/plugins/creative.js`
39
+
40
+ ### 3. Item Format Changes
41
+ - **Issue**: New concepts of hashed items and unsecure items (related to components)
42
+ - **Status**: Protocol changes need investigation
43
+ - **Impact**: Item handling and inventory management
44
+ - **Dependencies**: minecraft-data and minecraft-protocol updates needed
45
+
46
+ ### 4. Entity Metadata Changes
47
+ - **Issue**: Entity metadata may have changed
48
+ - **Status**: Could cause issues with various listeners in mineflayer
49
+ - **Impact**: Entity tracking and interaction
50
+ - **Location**: `lib/plugins/entities.js`
51
+
52
+ ## Detailed Action Plan
53
+
54
+ ### Phase 1: Dependency Updates and Investigation
55
+
56
+ #### 1.1 Investigate Chunk Protocol Issues
57
+ - **Task**: Manually dump and decode chunk packets to understand the new format
58
+ - **Tools**: Use packet analyzers or debug tools
59
+ - **Expected Outcome**: Identify exact changes in chunk size computation
60
+ - **Files to Modify**: `lib/plugins/blocks.js` (chunk handling)
61
+
62
+ #### 1.2 Analyze Creative Set Slot Issues
63
+ - **Task**: Debug creative set slot packet failures
64
+ - **Method**: Compare packet structure between 1.21.4 and 1.21.5
65
+ - **Files to Modify**: `lib/plugins/creative.js`
66
+ - **Test**: `test/externalTests/creative.js`
67
+
68
+ ### Phase 2: Protocol Implementation
69
+
70
+ #### 2.1 Fix Chunk Loading
71
+ ```javascript
72
+ // In lib/plugins/blocks.js
73
+ // Update chunk loading logic to handle auto-computed size
74
+ bot._client.on('map_chunk', (packet) => {
75
+ // Handle new chunk format with auto-computed size
76
+ // May need to adjust data parsing based on new format
77
+ })
78
+ ```
79
+
80
+ #### 2.2 Fix Creative Set Slot
81
+ ```javascript
82
+ // In lib/plugins/creative.js
83
+ // Update setInventorySlot to handle new packet format
84
+ async function setInventorySlot (slot, item, waitTimeout = 400) {
85
+ // Investigate and fix packet structure changes
86
+ // May need new packet format or different handling
87
+ }
88
+ ```
89
+
90
+ #### 2.3 Update Item Handling
91
+ ```javascript
92
+ // In lib/plugins/inventory.js
93
+ // Handle new hashed items and unsecure items concepts
94
+ // Update Item.fromNotch and Item.toNotch methods
95
+ ```
96
+
97
+ #### 2.4 Fix Entity Metadata
98
+ ```javascript
99
+ // In lib/plugins/entities.js
100
+ // Update entity metadata parsing for 1.21.5 changes
101
+ bot._client.on('entity_metadata', (packet) => {
102
+ // Handle new metadata format
103
+ })
104
+ ```
105
+
106
+ ### Phase 3: Testing and Validation
107
+
108
+ #### 3.1 Create 1.21.5 Specific Tests
109
+ ```javascript
110
+ // Add to test/externalTests/
111
+ // Create tests that specifically validate 1.21.5 functionality
112
+ ```
113
+
114
+ #### 3.2 Update Existing Tests
115
+ - **Task**: Fix failing tests for 1.21.5
116
+ - **Focus**: Creative mode, chunk loading, entity handling
117
+ - **Method**: Run `npm run mocha_test -- -g "mineflayer_external 1.21.5v"`
118
+
119
+ #### 3.3 Manual Testing
120
+ - **Task**: Test core functionality manually
121
+ - **Areas**: World loading, inventory management, entity interaction
122
+ - **Tools**: Use examples in `examples/` directory
123
+
124
+ ### Phase 4: Documentation and Cleanup
125
+
126
+ #### 4.1 Update Documentation
127
+ - **Task**: Update README and API docs for 1.21.5
128
+ - **Files**: `docs/README.md`, `docs/api.md`
129
+ - **Content**: Document any new features or breaking changes
130
+
131
+ #### 4.2 Update Version Support
132
+ - **Task**: Ensure 1.21.5 is properly listed as supported
133
+ - **Files**: `lib/version.js`, `package.json`
134
+
135
+ ## Analysis of Current Fix Status
136
+
137
+ ### ✅ **Good News: Fix Already Implemented**
138
+ The [prismarine-chunk PR #289](https://github.com/PrismarineJS/prismarine-chunk/pull/289/files) has already implemented the 1.21.5 chunk protocol fix:
139
+
140
+ **Key Changes in PR #289:**
141
+ 1. **Added `noSizePrefix` detection**: Uses `mcData.version['>=']('1.21.5')` to detect 1.21.5+
142
+ 2. **Modified chunk reading**: All palette containers now handle the `noSizePrefix` option
143
+ 3. **Dynamic size computation**: When `noSizePrefix` is true, size is computed as `Math.ceil(constants.BLOCK_SECTION_VOLUME * bitsPerValue / 64)`
144
+
145
+ ### 🔍 **Current Status Check**
146
+ Mineflayer is already using the experimental branches:
147
+ - `prismarine-chunk`: `extremeheat/prismarine-chunk#pc1.21.5` ✅
148
+ - `minecraft-protocol`: `extremeheat/node-minecraft-protocol#pcp1.21.5` ✅
149
+
150
+ ### ✅ **Chunk Loading Issue RESOLVED**
151
+ **FIXED**: The chunk loading issue has been resolved by correcting the size computation formula.
152
+
153
+ **Root Cause Analysis:**
154
+ 1. ✅ **Fix is implemented**: `noSizePrefix` detection and logic is present in the code
155
+ 2. ✅ **Version detection works**: `mcData.version['>=']('1.21.5')` returns `true` correctly
156
+ 3. ✅ **Size computation fixed**: Changed from `Math.ceil(constants.BLOCK_SECTION_VOLUME * bitsPerValue / 64)` to `Math.ceil(constants.BLOCK_SECTION_VOLUME / Math.floor(64 / bitsPerValue))`
157
+ 4. ✅ **Buffer reading works**: No more "Target offset is beyond the bounds of the internal SmartBuffer data" errors
158
+
159
+ **The Solution:**
160
+ The issue was in the `readBuffer` method in `PaletteContainer.js`. The formula needed to calculate the number of longs based on the actual BitArray logic used in the constructor.
161
+
162
+ ## Current Test Status
163
+
164
+ ### ✅ **Chunk Loading Fixed**
165
+ - **Status**: Chunk loading now works correctly for 1.21.5
166
+ - **Evidence**: No more "Target offset is beyond the bounds of the internal SmartBuffer data" errors
167
+ - **Next**: Focus on remaining test failures
168
+
169
+ ### 🚨 **New Test Failures Identified**
170
+ After fixing chunk loading, new issues emerged:
171
+
172
+ 1. **Test Setup Timeout**: "Event message did not fire within timeout of 5000ms" in "before each" hook for "bed"
173
+ 2. **Server Shutdown Issues**: "Server shutdown took too long. Killing process."
174
+ 3. **Potential Protocol Changes**: Other 1.21.5 protocol changes may be affecting test functionality
175
+
176
+ ## Next Priority Issues
177
+
178
+ ### 1. **Investigate Test Setup Failures** (High Priority)
179
+ - **Issue**: Tests are timing out during setup phase
180
+ - **Location**: `test/externalTests/plugins/testCommon.js:127:21` - `clearInventory` function
181
+ - **Possible Causes**:
182
+ - Creative set slot packet changes
183
+ - Inventory protocol changes
184
+ - Entity metadata changes
185
+
186
+ ### 2. **Debug Creative Set Slot** (High Priority - PROTOCOL CHANGE IDENTIFIED)
187
+ - **Issue**: Creative mode functionality broken due to protocol change
188
+ - **Location**: `lib/plugins/creative.js`
189
+ - **Test**: `test/externalTests/creative.js`
190
+ - **Root Cause**: `set_creative_slot` packet changed from `Slot` to `UntrustedSlot` type
191
+ - **Key Changes**:
192
+ - **1.21.4**: `packet_set_creative_slot.item` type: `Slot`
193
+ - **1.21.5**: `packet_set_creative_slot.item` type: `UntrustedSlot`
194
+ - `UntrustedSlot` has `present` boolean field first
195
+ - Uses `UntrustedSlotComponent` instead of `SlotComponent`
196
+ - New component system with `addedComponentCount` and `removedComponentCount`
197
+ - **Files to Modify**: `lib/plugins/creative.js` (creative set slot handling)
198
+
199
+ ### 3. **Check Item Format Changes** (Medium Priority - PROTOCOL CHANGES IDENTIFIED)
200
+ - **Issue**: New hashed items and unsecure items concepts
201
+ - **Location**: `lib/plugins/inventory.js`
202
+ - **Impact**: Item handling and inventory management
203
+ - **Protocol Changes Found**:
204
+ - **New `vec3i` type**: Added for 3D integer vectors
205
+ - **Item component system**: New component-based item system
206
+ - **Component reordering**: Item component IDs have been reordered (e.g., `hide_additional_tooltip` → `tooltip_display`)
207
+ - **New components**: Added `blocks_attacks`, `weapon` components
208
+ - **Entity metadata**: `item_stack` type still uses `Slot` but may have component changes
209
+
210
+ ### 4. **Entity Metadata Changes** (Medium Priority - MINIMAL CHANGES)
211
+ - **Issue**: Entity metadata format changes
212
+ - **Location**: `lib/plugins/entities.js`
213
+ - **Impact**: Entity tracking and interaction
214
+ - **Protocol Analysis**:
215
+ - **Good news**: `entity_metadata` packet structure unchanged
216
+ - **Good news**: `item_stack` type in metadata still uses `Slot` (not `UntrustedSlot`)
217
+ - **Minimal impact**: Entity metadata changes appear to be minimal for 1.21.5
218
+
219
+ ## Protocol Analysis Summary
220
+
221
+ Based on the [minecraft-data PR #1029](https://github.com/PrismarineJS/minecraft-data/pull/1029/files) analysis, here are the key protocol changes for 1.21.5:
222
+
223
+ ### 🔥 **Critical Changes (Blocking Issues)**
224
+
225
+ 1. **Creative Set Slot Packet**:
226
+ - **Change**: `packet_set_creative_slot.item` type changed from `Slot` to `UntrustedSlot`
227
+ - **Impact**: Creative mode inventory management completely broken
228
+ - **Fix Required**: Update `lib/plugins/creative.js` to handle `UntrustedSlot` format
229
+
230
+ 2. **New Packet Types**:
231
+ - **Added**: `set_test_block` (0x39) and `test_instance_block_action` (0x3c)
232
+ - **Impact**: May affect block interaction tests
233
+
234
+ ### 📦 **Item System Changes**
235
+
236
+ 1. **Component System**:
237
+ - **New**: `UntrustedSlot` with component-based system
238
+ - **Components**: `addedComponentCount`, `removedComponentCount`, `UntrustedSlotComponent`
239
+ - **Impact**: Item serialization/deserialization needs updates
240
+
241
+ 2. **Component Reordering**:
242
+ - **Changed**: Component IDs reordered (e.g., `hide_additional_tooltip` → `tooltip_display`)
243
+ - **Added**: New components like `blocks_attacks`, `weapon`
244
+
245
+ ### 🎯 **Minimal Impact Changes**
246
+
247
+ 1. **Entity Metadata**:
248
+ - **Status**: Unchanged - still uses `Slot` for `item_stack`
249
+ - **Impact**: Minimal - no changes needed
250
+
251
+ 2. **New Types**:
252
+ - **Added**: `vec3i` type for 3D integer vectors
253
+ - **Impact**: May be used in new packets but not critical
254
+
255
+ ## Implementation Steps
256
+ ```bash
257
+ cd /media/documents/Documents/programmation/interlangage/minecraft/mineflayer
258
+ npm install
259
+ ```
260
+
261
+ ### Step 2: Run Current Tests
262
+ ```bash
263
+ # Test current 1.21.5 status
264
+ npm run mocha_test -- -g "mineflayer_external 1.21.5v"
265
+ ```
266
+
267
+ ### Step 3: Investigate Specific Issues
268
+ ```bash
269
+ # Debug chunk loading
270
+ DEBUG="minecraft-protocol" npm run mocha_test -- -g "mineflayer_external 1.21.5v.*blocks"
271
+
272
+ # Debug creative mode
273
+ npm run mocha_test -- -g "mineflayer_external 1.21.5v.*creative"
274
+ ```
275
+
276
+ ### Step 4: Implement Fixes
277
+ 1. Start with chunk protocol fixes
278
+ 2. Fix creative set slot issues
279
+ 3. Update item handling
280
+ 4. Fix entity metadata
281
+
282
+ ### Step 5: Validate Fixes
283
+ ```bash
284
+ # Run all 1.21.5 tests
285
+ npm run mocha_test -- -g "mineflayer_external 1.21.5v"
286
+
287
+ # Run specific functionality tests
288
+ npm run mocha_test -- -g "mineflayer_external 1.21.5v.*inventory"
289
+ npm run mocha_test -- -g "mineflayer_external 1.21.5v.*entities"
290
+ ```
291
+
292
+ ## Success Criteria
293
+
294
+ 1. All 1.21.5 tests pass
295
+ 2. Core functionality works (world loading, inventory, entities)
296
+ 3. Creative mode functions properly
297
+ 4. No regressions in other versions
298
+ 5. Documentation is updated
299
+
300
+ ## Risk Mitigation
301
+
302
+ 1. **Backward Compatibility**: Ensure fixes don't break older versions
303
+ 2. **Incremental Testing**: Test each fix individually
304
+ 3. **Fallback Mechanisms**: Implement fallbacks for protocol changes
305
+ 4. **Version Detection**: Use `bot.supportFeature()` for version-specific code
306
+
307
+ ## Resources Needed
308
+
309
+ 1. **Minecraft 1.21.5 Server**: For testing
310
+ 2. **Packet Analyzer**: For debugging protocol changes
311
+ 3. **Documentation**: Minecraft 1.21.5 protocol changes
312
+ 4. **Time**: 1-2 weeks of focused development
313
+
314
+ ## Contributing Guidelines
315
+
316
+ For anyone wanting to contribute to 1.21.5 support:
317
+
318
+ 1. **Read the Documentation**: `docs/llm_contribute.md` and `docs/README.md`
319
+ 2. **Understand the Test System**: `test/externalTests/`
320
+ 3. **Focus on One Issue**: Pick one specific problem to solve
321
+ 4. **Test Thoroughly**: Run tests for multiple versions
322
+ 5. **Document Changes**: Update relevant documentation
323
+
324
+ ## Updated Timeline
325
+
326
+ - **Phase 1**: ✅ COMPLETED (chunk protocol fix)
327
+ - **Phase 2**: 2-3 days (investigate and fix test setup failures)
328
+ - **Phase 3**: 2-3 days (fix creative set slot and other protocol issues)
329
+ - **Phase 4**: 1-2 days (testing and validation)
330
+ - **Phase 5**: 1 day (documentation and cleanup)
331
+
332
+ **Total Estimated Time**: 6-9 days remaining
333
+
334
+ **Note**: Chunk loading is now fixed! Focus is on remaining protocol changes and test failures.
335
+
336
+ ## References
337
+
338
+ - [PrismarineJS/prismarine-chunk#289](https://github.com/PrismarineJS/prismarine-chunk/pull/289)
339
+ - [PrismarineJS/mineflayer#3691](https://github.com/PrismarineJS/mineflayer/pull/3691)
340
+ - [PrismarineJS/mineflayer#3641](https://github.com/PrismarineJS/mineflayer/issues/3641)
341
+ - [PrismarineJS/minecraft-data#1029](https://github.com/PrismarineJS/minecraft-data/pull/1029)
342
+ - [PrismarineJS/node-minecraft-protocol#1408](https://github.com/PrismarineJS/node-minecraft-protocol/pull/1408)
package/docs/zh/api.md CHANGED
@@ -737,8 +737,8 @@ Determines what color the boss bar color is, `pink`, `blue`, `red`, `green`, `y
737
737
  * port : 端口,默认为 25565
738
738
  * password : 可以省略 (如果token也被省略,那么它将尝试以离线模式连接)
739
739
  * host : 默认为 localhost
740
- * version : 默认为自动猜测服务器的版本。值示例:“1.12.2
741
- * auth : 默认为“mojang”,也可以是“microsoft
740
+ * version : 默认为自动猜测服务器的版本。值示例:"1.12.2"
741
+ * auth : 默认为"mojang",也可以是"microsoft"
742
742
  * clientToken : 如果给定密码,则生成
743
743
  * accessToken : 如果给定密码,则生成
744
744
  * logErrors : 默认情况下为true,捕获错误并记录它们
@@ -1041,7 +1041,7 @@ All scoreboards known to the bot in an object scoreboard displaySlot -> scoreboa
1041
1041
  * `belowName` - scoreboard placed in belowName
1042
1042
  * `sidebar` - scoreboard placed in sidebar
1043
1043
  * `list` - scoreboard placed in list
1044
- * `0-18` - slots defined in [protocol](https://wiki.vg/Protocol#Display_Scoreboard)
1044
+ * `0-18` - slots defined in [protocol](https://minecraft.wiki/w/Protocol#Display_Scoreboard)
1045
1045
 
1046
1046
  #### bot.teams
1047
1047
 
@@ -2022,7 +2022,7 @@ These are lower level methods for the inventory, they can be useful sometimes bu
2022
2022
 
2023
2023
  This function also returns a `Promise`, with `void` as its argument upon completion.
2024
2024
 
2025
- Click on the current window. See details at https://wiki.vg/Protocol#Click_Window
2025
+ Click on the current window. See details at https://minecraft.wiki/w/Protocol#Click_Window
2026
2026
 
2027
2027
  #### bot.putSelectedItemRange(start, end, window, slot)
2028
2028
 
@@ -6,7 +6,7 @@ const PI_2 = Math.PI * 2
6
6
  const TO_RAD = PI / 180
7
7
  const TO_DEG = 1 / TO_RAD
8
8
  const FROM_NOTCH_BYTE = 360 / 256
9
- // From wiki.vg: Velocity is believed to be in units of 1/8000 of a block per server tick (50ms)
9
+ // From minecraft.wiki: Velocity is believed to be in units of 1/8000 of a block per server tick (50ms)
10
10
  const FROM_NOTCH_VEL = 1 / 8000
11
11
 
12
12
  exports.toRadians = toRadians
@@ -146,9 +146,10 @@ function inject (bot) {
146
146
  }
147
147
  }
148
148
 
149
+ // We need to register the listener before actually going to sleep to avoid race conditions
150
+ const waitingPromise = waitUntilSleep()
149
151
  bot.activateBlock(bedBlock)
150
-
151
- await waitUntilSleep()
152
+ await waitingPromise
152
153
  }
153
154
  }
154
155
 
@@ -103,7 +103,7 @@ function inject (bot) {
103
103
  const entity = bot.entities[packet.entityId]
104
104
 
105
105
  if (destroyStage < 0 || destroyStage > 9) {
106
- // http://wiki.vg/Protocol#Block_Break_Progress
106
+ // http://minecraft.wiki/w/Protocol#Block_Break_Progress
107
107
  // "0-9 to set it, any other value to remove it"
108
108
  bot.emit('blockBreakProgressEnd', block, entity)
109
109
  } else {
@@ -118,7 +118,7 @@ function inject (bot, options) {
118
118
  target: data.targetName ? JSON.parse(data.targetName) : undefined,
119
119
  content: message ? JSON.parse(message) : { text: data.plainMessage }
120
120
  }
121
- const registryIndex = data.type.registryIndex ? data.type.registryIndex : data.type
121
+ const registryIndex = data.type.chatType != null ? data.type.chatType : data.type
122
122
  msg = ChatMessage.fromNetwork(registryIndex, parameters)
123
123
 
124
124
  if (data.unsignedContent) {
@@ -232,6 +232,8 @@ function inject (bot) {
232
232
  bot.emit('entitySpawn', entity)
233
233
  })
234
234
 
235
+ // spawn_entity_experience_orb packet was removed in 1.21.5+
236
+ // XP orbs are now handled through the general spawn_entity packet
235
237
  bot._client.on('spawn_entity_experience_orb', (packet) => {
236
238
  const entity = fetchEntity(packet.entityId)
237
239
  entity.type = 'orb'
@@ -599,201 +601,139 @@ function inject (bot) {
599
601
  bot.emit('entitySpawn', bot.entity)
600
602
  })
601
603
 
602
- bot._client.on('player_info', (packet) => {
603
- // player list item(s)
604
+ function handlePlayerInfoBitfield (packet) {
605
+ for (const item of packet.data) {
606
+ let player = bot._playerFromUUID(item.uuid)
607
+ const newPlayer = !player
604
608
 
605
- if (typeof packet.action !== 'number') {
606
- // the features checks below this will be un-needed with https://github.com/PrismarineJS/minecraft-data/pull/948
607
- for (const update of packet.data) {
608
- let player = bot.uuidToUsername[update.uuid] ? bot.players[bot.uuidToUsername[update.uuid]] : null
609
- let newPlayer = false
610
-
611
- const obj = {
612
- uuid: update.uuid
613
- }
614
-
615
- if (!player) newPlayer = true
616
-
617
- player ||= obj
618
-
619
- if (packet.action.add_player) {
620
- obj.username = update.player.name
621
- obj.displayName = player.displayName || new ChatMessage({ text: '', extra: [{ text: update.player.name }] })
622
- obj.skinData = extractSkinInformation(update.player.properties)
623
- }
624
-
625
- if (packet.action.update_game_mode) {
626
- obj.gamemode = update.gamemode
627
- }
628
-
629
- if (packet.action.update_latency) {
630
- obj.ping = update.latency
631
- }
609
+ if (newPlayer) {
610
+ player = { uuid: item.uuid }
611
+ }
632
612
 
633
- if (update.displayName) {
634
- obj.displayName = ChatMessage.fromNotch(update.displayName)
613
+ if (packet.action.add_player) {
614
+ player.username = item.player.name
615
+ player.displayName = new ChatMessage({ text: '', extra: [{ text: item.player.name }] })
616
+ player.skinData = extractSkinInformation(item.player.properties)
617
+ }
618
+ if (packet.action.initialize_chat && item.chatSession) {
619
+ player.chatSession = {
620
+ publicKey: item.chatSession.publicKey,
621
+ sessionUuid: item.chatSession.uuid
635
622
  }
623
+ }
624
+ if (packet.action.update_game_mode) {
625
+ player.gamemode = item.gamemode
626
+ }
627
+ if (packet.action.update_listed) {
628
+ player.listed = item.listed
629
+ }
630
+ if (packet.action.update_latency) {
631
+ player.ping = item.latency
632
+ }
633
+ if (packet.action.update_display_name) {
634
+ player.displayName = item.displayName ? ChatMessage.fromNotch(item.displayName) : new ChatMessage({ text: '', extra: [{ text: player.username }] })
635
+ }
636
636
 
637
- if (newPlayer) {
638
- if (!obj.username) continue // Should be unreachable
639
- player = bot.players[obj.username] = obj
640
- bot.uuidToUsername[obj.uuid] = obj.username
641
- } else {
642
- Object.assign(player, obj)
643
- }
637
+ if (newPlayer) {
638
+ if (!player.username) continue // Should be unreachable if add_player is always sent for new players
639
+ bot.players[player.username] = player
640
+ bot.uuidToUsername[player.uuid] = player.username
641
+ }
644
642
 
645
- const playerEntity = Object.values(bot.entities).find(e => e.type === 'player' && e.username === player.username)
646
- player.entity = playerEntity
643
+ const playerEntity = Object.values(bot.entities).find(e => e.type === 'player' && e.username === player.username)
644
+ player.entity = playerEntity
647
645
 
648
- if (playerEntity === bot.entity) {
649
- bot.player = player
650
- }
646
+ if (playerEntity === bot.entity) {
647
+ bot.player = player
648
+ }
651
649
 
652
- if (newPlayer) {
653
- bot.emit('playerJoined', player)
654
- } else {
655
- bot.emit('playerUpdated', player)
656
- }
650
+ if (newPlayer) {
651
+ bot.emit('playerJoined', player)
652
+ } else {
653
+ bot.emit('playerUpdated', player)
657
654
  }
658
- return
659
655
  }
656
+ }
660
657
 
661
- if (bot.supportFeature('playerInfoActionIsBitfield')) {
662
- for (const item of packet.data) {
663
- let player = bot.uuidToUsername[item.uuid] ? bot.players[bot.uuidToUsername[item.uuid]] : null
664
- let newPlayer = false
665
-
666
- const obj = {
667
- uuid: item.uuid
668
- }
669
-
670
- if (!player) newPlayer = true
671
-
672
- player = player || obj
673
-
674
- if (packet.action & 1) {
675
- obj.username = item.player.name
676
- obj.displayName = player.displayName || new ChatMessage({ text: '', extra: [{ text: item.player.name }] })
677
- obj.skinData = extractSkinInformation(item.player.properties)
678
- }
679
-
680
- if (packet.action & 4) {
681
- obj.gamemode = item.gamemode
682
- }
683
-
684
- if (packet.action & 16) {
685
- obj.ping = item.latency
686
- }
687
-
688
- if (item.displayName) {
689
- obj.displayName = ChatMessage.fromNotch(item.displayName)
690
- } else if (packet.action & 32) obj.displayName = new ChatMessage({ text: '', extra: [{ text: player.username || obj.username }] })
691
-
692
- if (newPlayer) {
693
- if (!obj.username) continue // Should be unreachable
694
- player = bot.players[obj.username] = obj
695
- bot.uuidToUsername[obj.uuid] = obj.username
696
- } else {
697
- Object.assign(player, obj)
698
- }
699
-
700
- const playerEntity = Object.values(bot.entities).find(e => e.type === 'player' && e.username === player.username)
701
- player.entity = playerEntity
702
-
703
- if (playerEntity === bot.entity) {
704
- bot.player = player
705
- }
706
-
707
- if (newPlayer) {
708
- bot.emit('playerJoined', player)
709
- } else {
710
- bot.emit('playerUpdated', player)
711
- }
712
- }
713
- } else {
714
- for (const item of packet.data) {
715
- let player = bot.uuidToUsername[item.UUID] ? bot.players[bot.uuidToUsername[item.UUID]] : null
716
- if (packet.action === 0) {
717
- let newPlayer = false
658
+ function handlePlayerInfoLegacy (packet) {
659
+ for (const item of packet.data) {
660
+ let player = bot._playerFromUUID(item.uuid)
718
661
 
719
- // New Player
720
- if (!player) {
662
+ switch (packet.action) {
663
+ case 'add_player': {
664
+ const newPlayer = !player
665
+ if (newPlayer) {
721
666
  player = bot.players[item.name] = {
722
667
  username: item.name,
723
- ping: item.ping,
724
- uuid: item.UUID,
725
- displayName: new ChatMessage({ text: '', extra: [{ text: item.name }] }),
726
- skinData: extractSkinInformation(item.properties),
727
- profileKeys: item.crypto
728
- ? {
729
- publicKey: item.crypto.publicKey, // DER-encoded public key
730
- signature: item.crypto.signature // Signature
731
- }
732
- : null
668
+ uuid: item.uuid
733
669
  }
670
+ bot.uuidToUsername[item.uuid] = item.name
671
+ }
734
672
 
735
- bot.uuidToUsername[item.UUID] = item.name
736
- bot.emit('playerJoined', player)
737
- newPlayer = true
738
- } else {
739
- // Just an Update
740
- player.gamemode = item.gamemode
741
- player.ping = item.ping
673
+ player.ping = item.ping
674
+ player.gamemode = item.gamemode
675
+ player.displayName = item.displayName ? ChatMessage.fromNotch(item.displayName) : new ChatMessage({ text: '', extra: [{ text: item.name }] })
676
+ if (item.properties) {
742
677
  player.skinData = extractSkinInformation(item.properties)
743
- if (item.crypto) {
744
- player.profileKeys = {
745
- publicKey: item.crypto.publicKey,
746
- signature: item.crypto.signature
747
- }
748
- }
749
678
  }
750
-
751
- if (item.displayName) {
752
- player.displayName = ChatMessage.fromNotch(item.displayName)
679
+ if (item.crypto) {
680
+ player.profileKeys = {
681
+ publicKey: item.crypto.publicKey,
682
+ signature: item.crypto.signature
683
+ }
753
684
  }
754
685
 
755
686
  const playerEntity = Object.values(bot.entities).find(e => e.type === 'player' && e.username === item.name)
756
687
  player.entity = playerEntity
757
-
758
688
  if (playerEntity === bot.entity) {
759
689
  bot.player = player
760
690
  }
761
691
 
762
- if (!newPlayer) {
692
+ if (newPlayer) bot.emit('playerJoined', player)
693
+ else bot.emit('playerUpdated', player)
694
+ break
695
+ }
696
+ case 'update_gamemode': {
697
+ if (player) {
698
+ player.gamemode = item.gamemode
763
699
  bot.emit('playerUpdated', player)
764
700
  }
765
- } else if (player) {
766
- if (packet.action === 1) {
767
- player.gamemode = item.gamemode
768
- } else if (packet.action === 2) {
701
+ break
702
+ }
703
+ case 'update_latency': {
704
+ if (player) {
769
705
  player.ping = item.ping
770
- } else if (packet.action === 3 && !item.displayName) {
771
- player.displayName = new ChatMessage({ text: '', extra: [{ text: player.username }] })
772
- } else if (packet.action === 3 && item.displayName) {
773
- player.displayName = ChatMessage.fromNotch(item.displayName)
774
- } else if (packet.action === 4) {
706
+ bot.emit('playerUpdated', player)
707
+ }
708
+ break
709
+ }
710
+ case 'update_display_name': {
711
+ if (player) {
712
+ player.displayName = item.displayName ? ChatMessage.fromNotch(item.displayName) : new ChatMessage({ text: '', extra: [{ text: player.username }] })
713
+ bot.emit('playerUpdated', player)
714
+ }
715
+ break
716
+ }
717
+ case 'remove_player': {
718
+ if (player) {
775
719
  if (player.entity === bot.entity) continue
776
-
777
720
  player.entity = null
778
721
  delete bot.players[player.username]
779
- delete bot.uuidToUsername[item.UUID]
722
+ delete bot.uuidToUsername[item.uuid]
780
723
  bot.emit('playerLeft', player)
781
- continue
782
- } else {
783
- continue
784
724
  }
785
-
786
- bot.emit('playerUpdated', player)
725
+ break
787
726
  }
788
727
  }
789
728
  }
790
- })
729
+ }
791
730
 
792
- // (1.19.3) player(s) leave the game
731
+ bot._client.on('player_info', bot.supportFeature('playerInfoActionIsBitfield') ? handlePlayerInfoBitfield : handlePlayerInfoLegacy)
732
+
733
+ // 1.19.3+ - player(s) leave the game
793
734
  bot._client.on('player_remove', (packet) => {
794
735
  for (const uuid of packet.players) {
795
- const player = bot.uuidToUsername[uuid] ? bot.players[bot.uuidToUsername[uuid]] : null
796
-
736
+ const player = bot._playerFromUUID(uuid)
797
737
  if (!player || player.entity === bot.entity) continue
798
738
 
799
739
  player.entity = null
@@ -354,38 +354,36 @@ function inject (bot, { physicsEnabled, maxCatchupTicks }) {
354
354
  // e.g. when crouching/crawling/swimming. Can someone confirm?
355
355
  bot.entity.height = 1.8
356
356
 
357
- // Velocity is reset if the x, y, z flags are not set
358
357
  const vel = bot.entity.velocity
359
- // If the x, y, z flags are not set, the position is absolute
360
358
  const pos = bot.entity.position
361
-
362
- // TODO: this current mineflayer logic maybe incorrect. New (maybe even older) versions of minecraft have flag values for
363
- // dx/dy/dz but mineflayer is assuming that 0b111 applies for both velocity and position.
364
-
365
359
  let newYaw, newPitch
366
360
 
367
- if (bot.registry.version['>=']('1.21.3')) {
368
- // flags is now an object with keys
369
- // "flags": ["x", "y", "z", "yaw", "pitch", "dx", "dy", "dz", "yawDelta"]
370
- const flags = packet.flags
361
+ // Note: 1.20.5+ uses a bitflags object, older versions use a bitmask number
362
+ if (typeof packet.flags === 'object') {
363
+ // Modern path with bitflags object
364
+ // Velocity is only set to 0 if the flag is not set, otherwise keep current velocity
371
365
  vel.set(
372
- flags.x ? vel.x : 0,
373
- flags.y ? vel.y : 0,
374
- flags.z ? vel.z : 0
366
+ packet.flags.x ? vel.x : 0,
367
+ packet.flags.y ? vel.y : 0,
368
+ packet.flags.z ? vel.z : 0
375
369
  )
370
+ // If flag is set, then the corresponding value is relative, else it is absolute
376
371
  pos.set(
377
- flags.x ? (pos.x + packet.x) : packet.x,
378
- flags.y ? (pos.y + packet.y) : packet.y,
379
- flags.z ? (pos.z + packet.z) : packet.z
372
+ packet.flags.x ? (pos.x + packet.x) : packet.x,
373
+ packet.flags.y ? (pos.y + packet.y) : packet.y,
374
+ packet.flags.z ? (pos.z + packet.z) : packet.z
380
375
  )
381
- newYaw = (flags.yaw ? conv.toNotchianYaw(bot.entity.yaw) : 0) + packet.yaw
382
- newPitch = (flags.pitch ? conv.toNotchianPitch(bot.entity.pitch) : 0) + packet.pitch
376
+ newYaw = (packet.flags.yaw ? conv.toNotchianYaw(bot.entity.yaw) : 0) + packet.yaw
377
+ newPitch = (packet.flags.pitch ? conv.toNotchianPitch(bot.entity.pitch) : 0) + packet.pitch
383
378
  } else {
379
+ // Legacy path with bitmask number
380
+ // Velocity is only set to 0 if the flag is not set, otherwise keep current velocity
384
381
  vel.set(
385
382
  packet.flags & 1 ? vel.x : 0,
386
383
  packet.flags & 2 ? vel.y : 0,
387
384
  packet.flags & 4 ? vel.z : 0
388
385
  )
386
+ // If flag is set, then the corresponding value is relative, else it is absolute
389
387
  pos.set(
390
388
  packet.flags & 1 ? (pos.x + packet.x) : packet.x,
391
389
  packet.flags & 2 ? (pos.y + packet.y) : packet.y,
@@ -11,7 +11,6 @@ module.exports = (bot) => {
11
11
  }
12
12
 
13
13
  bot.blockInSight = (maxSteps = 256, vectorLength = 5 / 16) => {
14
- console.warn('[deprecated] use bot.blockAtCursor instead')
15
14
  const block = bot.blockAtCursor(maxSteps * vectorLength)
16
15
  if (block) return block
17
16
  }
@@ -3,8 +3,6 @@ const { Vec3 } = require('vec3')
3
3
  module.exports = inject
4
4
 
5
5
  function inject (bot) {
6
- const mcData = require('minecraft-data')(bot.version)
7
-
8
6
  bot._client.on('named_sound_effect', (packet) => {
9
7
  const soundName = packet.soundName
10
8
  const pt = new Vec3(packet.x / 8, packet.y / 8, packet.z / 8)
@@ -24,20 +22,27 @@ function inject (bot) {
24
22
  })
25
23
 
26
24
  bot._client.on('sound_effect', (packet) => {
27
- const soundId = packet.soundId
28
25
  const soundCategory = packet.soundCategory
29
26
  const pt = new Vec3(packet.x / 8, packet.y / 8, packet.z / 8)
30
27
  const volume = packet.volume
31
28
  const pitch = packet.pitch
32
29
 
33
- // Try to resolve sound name from mcData
34
- let soundName = soundId
35
- if (mcData.sounds && mcData.sounds[soundId]) {
36
- soundName = mcData.sounds[soundId].name
30
+ let soundId, soundName
31
+
32
+ if (packet.sound) { // ItemSoundHolder
33
+ if (packet.sound.data) soundName = packet.sound.data.soundName
34
+ else soundId = packet.sound.soundId // Sound specified by ID (registry reference)
35
+ } else { // Legacy packet
36
+ soundId = packet.soundId
37
37
  }
38
38
 
39
- // Emit both events for compatibility
40
- bot.emit('hardcodedSoundEffectHeard', soundId, soundCategory, pt, volume, pitch)
41
- bot.emit('soundEffectHeard', soundName, pt, volume, pitch)
39
+ // If we have an ID but no name yet, try to look it up in the registry
40
+ soundName ??= bot.registry?.sounds?.[soundId]?.name
41
+
42
+ if (soundName) {
43
+ bot.emit('soundEffectHeard', soundName, pt, volume, pitch)
44
+ } else if (soundId !== null) {
45
+ bot.emit('hardcodedSoundEffectHeard', soundId, soundCategory, pt, volume, pitch)
46
+ }
42
47
  })
43
48
  }
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const testedVersions = ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1', '1.18.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20.1', '1.20.2', '1.20.4', '1.20.6', '1.21.1', '1.21.3', '1.21.4']
1
+ const testedVersions = ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1', '1.18.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20.1', '1.20.2', '1.20.4', '1.20.6', '1.21.1', '1.21.3', '1.21.4', '1.21.5']
2
2
  module.exports = {
3
3
 
4
4
  testedVersions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mineflayer",
3
- "version": "4.29.0",
3
+ "version": "4.31.0",
4
4
  "description": "create minecraft bots with a stable, high level API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -22,13 +22,13 @@
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
24
  "minecraft-data": "^3.76.0",
25
- "minecraft-protocol": "^1.51.0",
25
+ "minecraft-protocol": "^1.60.0",
26
26
  "prismarine-biome": "^1.1.1",
27
- "prismarine-block": "^1.17.0",
27
+ "prismarine-block": "^1.22.0",
28
28
  "prismarine-chat": "^1.7.1",
29
- "prismarine-chunk": "^1.36.0",
29
+ "prismarine-chunk": "^1.39.0",
30
30
  "prismarine-entity": "^2.5.0",
31
- "prismarine-item": "^1.15.0",
31
+ "prismarine-item": "^1.17.0",
32
32
  "prismarine-nbt": "^2.0.0",
33
33
  "prismarine-physics": "^1.9.0",
34
34
  "prismarine-recipe": "^1.3.0",
@@ -40,7 +40,7 @@
40
40
  "vec3": "^0.1.7"
41
41
  },
42
42
  "devDependencies": {
43
- "@types/node": "^22.1.0",
43
+ "@types/node": "^24.0.6",
44
44
  "doctoc": "^2.0.1",
45
45
  "minecraft-wrap": "^1.3.0",
46
46
  "mineflayer": "file:",