mineflayer 3.13.1 → 3.16.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.
@@ -0,0 +1,45 @@
1
+ /*
2
+ *
3
+ * A bot that attacks the player that sends a message or the nearest entity (excluding players)
4
+ *
5
+ */
6
+ const mineflayer = require('mineflayer')
7
+
8
+ if (process.argv.length < 4 || process.argv.length > 6) {
9
+ console.log('Usage : node attack.js <host> <port> [<name>] [<password>]')
10
+ process.exit(1)
11
+ }
12
+
13
+ const bot = mineflayer.createBot({
14
+ host: process.argv[2],
15
+ port: parseInt(process.argv[3]),
16
+ username: process.argv[4] ? process.argv[4] : 'attack',
17
+ password: process.argv[5]
18
+ })
19
+
20
+ bot.on('spawn', () => {
21
+ bot.on('chat', (username, message) => {
22
+ if (message === 'attack me') attackPlayer(username)
23
+ else if (message === 'attack') attackEntity()
24
+ })
25
+ })
26
+
27
+ function attackPlayer (username) {
28
+ const player = bot.players[username]
29
+ if (!player || !player.entity) {
30
+ bot.chat('I can\'t see you')
31
+ } else {
32
+ bot.chat(`Attacking ${player.username}`)
33
+ bot.attack(player.entity)
34
+ }
35
+ }
36
+
37
+ function attackEntity () {
38
+ const entity = bot.nearestEntity()
39
+ if (!entity) {
40
+ bot.chat('No nearby entities')
41
+ } else {
42
+ bot.chat(`Attacking ${entity.name ?? entity.username}`)
43
+ bot.attack(entity)
44
+ }
45
+ }
package/index.d.ts CHANGED
@@ -189,6 +189,7 @@ export interface Bot extends TypedEmitter<BotEvents> {
189
189
  heldItem: Item | null
190
190
  currentWindow: Window | null
191
191
  simpleClick: simpleClick
192
+ tablist: Tablist
192
193
 
193
194
  connect: (options: BotOptions) => void
194
195
 
@@ -343,6 +344,8 @@ export interface Bot extends TypedEmitter<BotEvents> {
343
344
  callback?: (err?: Error) => void
344
345
  ) => Promise<void>
345
346
 
347
+ openContainer: (chest: Block | Entity) => Promise<Chest | Furnace | Dispenser>
348
+
346
349
  openChest: (chest: Block | Entity) => Promise<Chest>
347
350
 
348
351
  openFurnace: (furnace: Block) => Promise<Furnace>
@@ -425,6 +428,11 @@ export interface simpleClick {
425
428
  rightMouse: (slot: number) => Promise<void>
426
429
  }
427
430
 
431
+ export interface Tablist {
432
+ header: ChatMessage
433
+ footer: ChatMessage
434
+ }
435
+
428
436
  export interface chatPatternOptions {
429
437
  repeat: boolean
430
438
  parse: boolean
@@ -740,13 +748,18 @@ export class Villager extends (EventEmitter as new () => TypedEmitter<Conditiona
740
748
  }
741
749
 
742
750
  export interface VillagerTrade {
743
- firstInput: Item
744
- output: Item
745
- hasSecondItem: boolean
746
- secondaryInput: Item | null
747
- disabled: boolean
748
- tooluses: number
749
- maxTradeuses: number
751
+ inputItem1: Item
752
+ outputItem: Item
753
+ inputItem2: Item | null
754
+ hasItem2: boolean
755
+ tradeDisabled: boolean
756
+ nbTradeUses: number
757
+ maximumNbTradeUses: number
758
+ xp?: number
759
+ specialPrice?: number
760
+ priceMultiplier?: number
761
+ demand?: number
762
+ realPrice?: number
750
763
  }
751
764
 
752
765
  export class ScoreBoard {
@@ -789,7 +802,7 @@ export class Team {
789
802
 
790
803
  update (name: string, friendlyFire: boolean, nameTagVisibility: string, collisionRule: string, formatting: number, prefix: string, suffix: string): void;
791
804
 
792
- displayName (member: string);
805
+ displayName (member: string): ChatMessage;
793
806
  }
794
807
 
795
808
  export type DisplaySlot =
package/lib/features.json CHANGED
@@ -7,7 +7,7 @@
7
7
  {
8
8
  "name": "spawner",
9
9
  "description": "spawner is called spawner",
10
- "versions": ["1.13", "1.17.1"]
10
+ "versions": ["1.13", "1.18.1"]
11
11
  },
12
12
  {
13
13
  "name": "blockMetadata",
@@ -17,12 +17,12 @@
17
17
  {
18
18
  "name": "blockStateId",
19
19
  "description": "block metadata is encoded as state id",
20
- "versions": ["1.13", "1.17.1"]
20
+ "versions": ["1.13", "1.18.1"]
21
21
  },
22
22
  {
23
23
  "name": "creativeSleepNearMobs",
24
24
  "description": "can sleep near mobs in creative",
25
- "versions": ["1.13", "1.17.1"]
25
+ "versions": ["1.13", "1.18.1"]
26
26
  },
27
27
  {
28
28
  "name": "fixedPointPosition",
@@ -32,7 +32,7 @@
32
32
  {
33
33
  "name": "doublePosition",
34
34
  "description": "Entity positions are represented with double",
35
- "versions": ["1.9", "1.17.1"]
35
+ "versions": ["1.9", "1.18.1"]
36
36
  },
37
37
  {
38
38
  "name": "fixedPointDelta",
@@ -42,7 +42,7 @@
42
42
  {
43
43
  "name": "fixedPointDelta128",
44
44
  "description": "Delta of position are represented with fixed point numbers times 128",
45
- "versions": ["1.9", "1.17.1"]
45
+ "versions": ["1.9", "1.18.1"]
46
46
  },
47
47
  {
48
48
  "name": "customChannelMCPrefixed",
@@ -52,12 +52,12 @@
52
52
  {
53
53
  "name": "customChannelIdentifier",
54
54
  "description": "custom channel is an identifier starting in minecraft namespace",
55
- "versions": ["1.13", "1.17.1"]
55
+ "versions": ["1.13", "1.18.1"]
56
56
  },
57
57
  {
58
58
  "name": "dimensionDataIsAvailable",
59
59
  "description": "dimensionData is available, providing an additional information about the current dimension",
60
- "versions": ["1.17", "1.17.1"]
60
+ "versions": ["1.17", "1.18.1"]
61
61
  },
62
62
  {
63
63
  "name": "useItemWithBlockPlace",
@@ -67,7 +67,7 @@
67
67
  {
68
68
  "name": "useItemWithOwnPacket",
69
69
  "description": "use item is done with its own packet",
70
- "versions": ["1.9", "1.17.1"]
70
+ "versions": ["1.9", "1.18.1"]
71
71
  },
72
72
  {
73
73
  "name": "blockPlaceHasHeldItem",
@@ -87,7 +87,7 @@
87
87
  {
88
88
  "name": "blockPlaceHasInsideBlock",
89
89
  "description": "block_place packet has inside block",
90
- "versions": ["1.14", "1.17.1"]
90
+ "versions": ["1.14", "1.18.1"]
91
91
  },
92
92
  {
93
93
  "name": "teleportUsesPositionPacket",
@@ -102,7 +102,7 @@
102
102
  {
103
103
  "name": "teleportUsesOwnPacket",
104
104
  "description": "teleport is done using its own packet",
105
- "versions": ["1.9", "1.17.1"]
105
+ "versions": ["1.9", "1.18.1"]
106
106
  },
107
107
  {
108
108
  "name": "oneBlockForSeveralVariations",
@@ -112,7 +112,7 @@
112
112
  {
113
113
  "name": "blockSchemeIsFlat",
114
114
  "description": "all variations of a packet have their own id",
115
- "versions": ["1.13", "1.17.1"]
115
+ "versions": ["1.13", "1.18.1"]
116
116
  },
117
117
  {
118
118
  "name": "tabCompleteHasNoToolTip",
@@ -122,7 +122,7 @@
122
122
  {
123
123
  "name": "tabCompleteHasAToolTip",
124
124
  "description": "tab complete has a tool tip",
125
- "versions": ["1.13", "1.17.1"]
125
+ "versions": ["1.13", "1.18.1"]
126
126
  },
127
127
  {
128
128
  "name": "effectAreMinecraftPrefixed",
@@ -132,7 +132,7 @@
132
132
  {
133
133
  "name": "effectAreNotPrefixed",
134
134
  "description": "effect are not prefixed",
135
- "versions": ["1.13", "1.17.1"]
135
+ "versions": ["1.13", "1.18.1"]
136
136
  },
137
137
  {
138
138
  "name": "itemsAreAlsoBlocks",
@@ -142,12 +142,12 @@
142
142
  {
143
143
  "name": "itemsAreNotBlocks",
144
144
  "description": "items are not block",
145
- "versions": ["1.13", "1.17.1"]
145
+ "versions": ["1.13", "1.18.1"]
146
146
  },
147
147
  {
148
148
  "name": "fishingBobberCorrectlyNamed",
149
149
  "description": "the fishing hook entity is named fishing_bobber",
150
- "versions": ["1.14", "1.17.1"]
150
+ "versions": ["1.14", "1.18.1"]
151
151
  },
152
152
  {
153
153
  "name": "editBookIsPluginChannel",
@@ -157,7 +157,7 @@
157
157
  {
158
158
  "name": "hasEditBookPacket",
159
159
  "description": "book editing is handled through a packet",
160
- "versions": ["1.13", "1.17.1"]
160
+ "versions": ["1.13", "1.18.1"]
161
161
  },
162
162
  {
163
163
  "name": "clientUpdateBookIdWhenSign",
@@ -197,12 +197,12 @@
197
197
  {
198
198
  "name": "dimensionIsAWorld",
199
199
  "description": "description is a world name (string)",
200
- "versions": ["1.16.2", "1.17.1"]
200
+ "versions": ["1.16.2", "1.18.1"]
201
201
  },
202
202
  {
203
203
  "name": "dimensionDataIsAvailable",
204
204
  "description": "dimensionData is available, describing additional dimension information",
205
- "versions": ["1.17", "1.17.1"]
205
+ "versions": ["1.17", "1.18.1"]
206
206
  },
207
207
  {
208
208
  "name": "doesntHaveChestType",
@@ -227,22 +227,22 @@
227
227
  {
228
228
  "name": "hasAttackCooldown",
229
229
  "description": "if there is a cooldown after attacks to deal full damage",
230
- "versions": ["1.9", "1.17.1"]
230
+ "versions": ["1.9", "1.18.1"]
231
231
  },
232
232
  {
233
233
  "name": "usesLoginPacket",
234
234
  "description": "uses the login packet as defined in mcData",
235
- "versions": ["1.16", "1.17.1"]
235
+ "versions": ["1.16", "1.18.1"]
236
236
  },
237
237
  {
238
238
  "name": "usesMultiblockSingleLong",
239
239
  "description": "in the multi_block_change packet is stored as a single number",
240
- "versions": ["1.16.2", "1.17.1"]
240
+ "versions": ["1.16.2", "1.18.1"]
241
241
  },
242
242
  {
243
243
  "name": "usesMultiblock3DChunkCoords",
244
244
  "description": "in the multi_block_change packet, all 3 axis coords are defined",
245
- "versions": ["1.16.2", "1.17.1"]
245
+ "versions": ["1.16.2", "1.18.1"]
246
246
  },
247
247
  {
248
248
  "name": "setBlockUsesMetadataNumber",
@@ -257,7 +257,7 @@
257
257
  {
258
258
  "name": "selectingTradeMovesItems",
259
259
  "description": "selecting a trade automatically puts the required items into trading slots",
260
- "versions": ["1.14", "1.17.1"]
260
+ "versions": ["1.14", "1.18.1"]
261
261
  },
262
262
  {
263
263
  "name": "resourcePackUsesHash",
@@ -272,7 +272,7 @@
272
272
  {
273
273
  "name": "teamUsesChatComponents",
274
274
  "description": "teams use chatcomponents for formatting",
275
- "versions": ["1.13", "1.17.1"]
275
+ "versions": ["1.13", "1.18.1"]
276
276
  },
277
277
  {
278
278
  "name": "teamUsesScoreboard",
@@ -287,7 +287,7 @@
287
287
  {
288
288
  "name": "enderCrystalNameNoCapsWithUnderscore",
289
289
  "description": "this is when the end_crystal's entity name is end_crystal",
290
- "versions": ["1.14", "1.17.1"]
290
+ "versions": ["1.14", "1.18.1"]
291
291
  },
292
292
  {
293
293
  "name": "entityNameUpperCaseNoUnderscore",
@@ -307,7 +307,7 @@
307
307
  {
308
308
  "name": "stateIdUsed",
309
309
  "description": "starting in 1.17.1, actionId has been replaced with stateId",
310
- "versions": ["1.17.1", "1.17.1"]
310
+ "versions": ["1.17.1", "1.18.1"]
311
311
  },
312
312
  {
313
313
  "name": "actionIdUsed",
@@ -317,6 +317,21 @@
317
317
  {
318
318
  "name": "setSlotAsTransaction",
319
319
  "description": "use setslot as transaction instead of just hoping it'll work",
320
- "versions": ["1.17", "1.17.1"]
320
+ "versions": ["1.17", "1.18.1"]
321
+ },
322
+ {
323
+ "name": "armAnimationBeforeUse",
324
+ "description": "arm animation packet sent before use entity packet",
325
+ "versions": ["1.8", "1.8.9"]
326
+ },
327
+ {
328
+ "name": "tallWorld",
329
+ "description": "world starts at -64 and ends at 384",
330
+ "versions": ["1.18", "1.18.1"]
331
+ },
332
+ {
333
+ "name": "sendStringifiedSignText",
334
+ "description": "sign text send when updating signs is send as stringified strings",
335
+ "versions": ["1.8", "1.8.9"]
321
336
  }
322
337
  ]
package/lib/loader.js CHANGED
@@ -63,7 +63,7 @@ function createBot (options = {}) {
63
63
  options.username = options.username ?? 'Player'
64
64
  options.version = options.version ?? false
65
65
  options.plugins = options.plugins ?? {}
66
- options.hideErrors = options.hideErrors ?? true
66
+ options.hideErrors = options.hideErrors ?? false
67
67
  options.logErrors = options.logErrors ?? true
68
68
  options.loadInternalPlugins = options.loadInternalPlugins ?? true
69
69
  options.client = options.client ?? null
@@ -21,17 +21,12 @@ const dimensionNames = {
21
21
  }
22
22
 
23
23
  function inject (bot, { version, storageBuilder }) {
24
- const nbt = require('prismarine-nbt')
25
24
  const Block = require('prismarine-block')(version)
26
25
  const Chunk = require('prismarine-chunk')(version)
27
- const ChatMessage = require('prismarine-chat')(version)
28
26
  const World = require('prismarine-world')(version)
29
- const signs = {}
30
27
  const paintingsByPos = {}
31
28
  const paintingsById = {}
32
29
 
33
- const blockEntities = new Map()
34
-
35
30
  function addPainting (painting) {
36
31
  paintingsById[painting.id] = painting
37
32
  paintingsByPos[painting.position] = painting
@@ -42,41 +37,6 @@ function inject (bot, { version, storageBuilder }) {
42
37
  delete paintingsByPos[painting.position]
43
38
  }
44
39
 
45
- function addBlockEntity (nbtData) {
46
- const blockEntity = nbt.simplify(nbtData)
47
- const pos = new Vec3(blockEntity.x, blockEntity.y, blockEntity.z).floored()
48
- // Set raw nbt of blockEntity
49
- blockEntity.raw = nbtData
50
- // Handle signs
51
- if (blockEntity.id === 'minecraft:sign' || blockEntity.id === 'Sign') {
52
- const prepareJson = (i) => {
53
- const data = blockEntity[`Text${i}`]
54
-
55
- if (data === null || data === '') return ''
56
-
57
- const json = JSON.parse(data)
58
- if (json === null || !('text' in json)) return ''
59
-
60
- json.text = json.text.replace(/^"|"$/g, '')
61
- return json
62
- }
63
-
64
- blockEntity.Text1 = new ChatMessage(prepareJson(1))
65
- blockEntity.Text2 = new ChatMessage(prepareJson(2))
66
- blockEntity.Text3 = new ChatMessage(prepareJson(3))
67
- blockEntity.Text4 = new ChatMessage(prepareJson(4))
68
-
69
- signs[pos] = [
70
- blockEntity.Text1.toString(),
71
- blockEntity.Text2.toString(),
72
- blockEntity.Text3.toString(),
73
- blockEntity.Text4.toString()
74
- ].join('\n')
75
- }
76
-
77
- blockEntities[pos] = blockEntity
78
- }
79
-
80
40
  function delColumn (chunkX, chunkZ) {
81
41
  bot.world.unloadColumn(chunkX, chunkZ)
82
42
  }
@@ -90,11 +50,7 @@ function inject (bot, { version, storageBuilder }) {
90
50
  let column = bot.world.getColumn(args.x, args.z)
91
51
  if (!column) {
92
52
  // Allocates new chunk object while taking world's custom min/max height into account
93
- if (bot.supportFeature('dimensionDataIsAvailable')) {
94
- column = new Chunk({ minY: bot.game.dimensionData.min_y, worldHeight: bot.game.dimensionData.height })
95
- } else {
96
- column = new Chunk()
97
- }
53
+ column = new Chunk({ minY: bot.game.minY, worldHeight: bot.game.height })
98
54
  }
99
55
 
100
56
  try {
@@ -102,6 +58,9 @@ function inject (bot, { version, storageBuilder }) {
102
58
  if (args.biomes !== undefined) {
103
59
  column.loadBiomes(args.biomes)
104
60
  }
61
+ if (args.skyLight !== undefined) {
62
+ column.loadParsedLight(args.skyLight, args.blockLight, args.skyLightMask, args.blockLightMask, args.emptySkyLightMask, args.emptyBlockLightMask)
63
+ }
105
64
  bot.world.setColumn(args.x, args.z, column)
106
65
  } catch (e) {
107
66
  bot.emit('error', e)
@@ -206,13 +165,17 @@ function inject (bot, { version, storageBuilder }) {
206
165
  let next = start
207
166
  while (next) {
208
167
  const column = bot.world.getColumn(next.x, next.z)
209
- if (next.y >= 0 && next.y < 16 && column && !visitedSections.has(next.toString())) {
210
- const section = column.sections[next.y]
168
+ const sectionY = next.y + Math.abs(bot.game.minY >> 4)
169
+ const totalSections = bot.game.height >> 4
170
+ if (sectionY >= 0 && sectionY < totalSections && column && !visitedSections.has(next.toString())) {
171
+ const section = column.sections[sectionY]
211
172
  if (useExtraInfo === true || isBlockInSection(section, matcher)) {
212
- const cursor = new Vec3(0, 0, 0)
213
- for (cursor.x = next.x * 16; cursor.x < next.x * 16 + 16; cursor.x++) {
214
- for (cursor.y = next.y * 16; cursor.y < next.y * 16 + 16; cursor.y++) {
215
- for (cursor.z = next.z * 16; cursor.z < next.z * 16 + 16; cursor.z++) {
173
+ const begin = new Vec3(next.x * 16, sectionY * 16 + bot.game.minY, next.z * 16)
174
+ const cursor = begin.clone()
175
+ const end = cursor.offset(16, 16, 16)
176
+ for (cursor.x = begin.x; cursor.x < end.x; cursor.x++) {
177
+ for (cursor.y = begin.y; cursor.y < end.y; cursor.y++) {
178
+ for (cursor.z = begin.z; cursor.z < end.z; cursor.z++) {
216
179
  if (fullMatcher(cursor) && cursor.distanceTo(point) <= maxDistance) blocks.push(cursor.clone())
217
180
  }
218
181
  }
@@ -249,9 +212,7 @@ function inject (bot, { version, storageBuilder }) {
249
212
  if (!block) return null
250
213
 
251
214
  if (extraInfos) {
252
- block.signText = signs[block.position]
253
215
  block.painting = paintingsByPos[block.position]
254
- block.blockEntity = blockEntities[block.position]
255
216
  }
256
217
 
257
218
  return block
@@ -288,9 +249,6 @@ function inject (bot, { version, storageBuilder }) {
288
249
  }
289
250
  if (oldBlock.type !== newBlock.type) {
290
251
  const pos = point.floored()
291
- delete blockEntities[pos]
292
- delete signs[pos]
293
-
294
252
  const painting = paintingsByPos[pos]
295
253
  if (painting) deletePainting(painting)
296
254
  }
@@ -299,11 +257,7 @@ function inject (bot, { version, storageBuilder }) {
299
257
  bot._client.on('update_light', (packet) => {
300
258
  let column = bot.world.getColumn(packet.chunkX, packet.chunkZ)
301
259
  if (!column) {
302
- if (bot.supportFeature('dimensionDataIsAvailable')) {
303
- column = new Chunk({ minY: bot.game.dimensionData.min_y, worldHeight: bot.game.dimensionData.height })
304
- } else {
305
- column = new Chunk()
306
- }
260
+ column = new Chunk({ minY: bot.game.minY, worldHeight: bot.game.height })
307
261
  bot.world.setColumn(packet.chunkX, packet.chunkZ, column)
308
262
  }
309
263
 
@@ -323,12 +277,25 @@ function inject (bot, { version, storageBuilder }) {
323
277
  biomes: packet.biomes,
324
278
  skyLightSent: bot.game.dimension === 'minecraft:overworld',
325
279
  groundUp: packet.groundUp,
326
- data: packet.chunkData
280
+ data: packet.chunkData,
281
+ trustEdges: packet.trustEdges,
282
+ skyLightMask: packet.skyLightMask,
283
+ blockLightMask: packet.blockLightMask,
284
+ emptySkyLightMask: packet.emptySkyLightMask,
285
+ emptyBlockLightMask: packet.emptyBlockLightMask,
286
+ skyLight: packet.skyLight,
287
+ blockLight: packet.blockLight
327
288
  })
328
289
 
329
290
  if (typeof packet.blockEntities !== 'undefined') {
330
- for (const nbtData of packet.blockEntities) {
331
- addBlockEntity(nbtData)
291
+ const column = bot.world.getColumn(packet.x, packet.z)
292
+ for (const blockEntity of packet.blockEntities) {
293
+ if (blockEntity.x !== undefined) { // 1.17+
294
+ column.setBlockEntity(blockEntity, blockEntity.nbtData)
295
+ } else {
296
+ const pos = new Vec3(blockEntity.value.x.value & 0xf, blockEntity.value.y.value, blockEntity.value.z.value & 0xf)
297
+ column.setBlockEntity(pos, blockEntity)
298
+ }
332
299
  }
333
300
  }
334
301
  })
@@ -422,33 +389,34 @@ function inject (bot, { version, storageBuilder }) {
422
389
  })
423
390
 
424
391
  bot._client.on('update_sign', (packet) => {
425
- const pos = new Vec3(packet.location.x, packet.location.y, packet.location.z)
426
-
427
- const prepareString = (i) => {
428
- let text = packet[`text${i}`]
429
-
430
- if (text === 'null' || text === '') {
431
- text = '""'
432
- }
392
+ const pos = new Vec3(packet.location.x & 0xf, packet.location.y, packet.location.z & 0xf)
433
393
 
434
- const json = JSON.parse(text)
435
- if (json.text) {
436
- json.text = json.text.replace(/^"|"$/g, '')
437
- }
438
-
439
- return new ChatMessage(json)
394
+ // TODO: warn if out of loaded world?
395
+ const column = bot.world.getColumn(packet.location.x >> 4, packet.location.z >> 4)
396
+ if (!column) {
397
+ return
440
398
  }
441
399
 
442
- signs[pos] = [
443
- prepareString(1),
444
- prepareString(2),
445
- prepareString(3),
446
- prepareString(4)
447
- ].join('\n')
400
+ const blockAt = column.getBlock(pos)
401
+
402
+ blockAt.signText = [packet.text1, packet.text2, packet.text3, packet.text4].map(text => {
403
+ if (text === 'null' || text === '') return ''
404
+ return JSON.parse(text)
405
+ })
406
+ column.setBlock(pos, blockAt)
448
407
  })
449
408
 
450
409
  bot._client.on('tile_entity_data', (packet) => {
451
- addBlockEntity(packet.nbtData)
410
+ if (packet.location !== undefined) {
411
+ const column = bot.world.getColumn(packet.location.x >> 4, packet.location.z >> 4)
412
+ const pos = new Vec3(packet.location.x & 0xf, packet.location.y, packet.location.z & 0xf)
413
+ column.setBlockEntity(pos, packet.nbtData)
414
+ } else {
415
+ const tag = packet.nbtData
416
+ const column = bot.world.getColumn(tag.value.x.value >> 4, tag.value.z.value >> 4)
417
+ const pos = new Vec3(tag.value.x.value & 0xf, tag.value.y.value, tag.value.z.value & 0xf)
418
+ column.setBlockEntity(pos, tag)
419
+ }
452
420
  })
453
421
 
454
422
  bot.updateSign = (block, text) => {
@@ -464,12 +432,25 @@ function inject (bot, { version, storageBuilder }) {
464
432
  }
465
433
  }
466
434
 
435
+ let signData
436
+ if (bot.supportFeature('sendStringifiedSignText')) {
437
+ signData = {
438
+ text1: lines[0] ? JSON.stringify(lines[0]) : '""',
439
+ text2: lines[1] ? JSON.stringify(lines[1]) : '""',
440
+ text3: lines[2] ? JSON.stringify(lines[2]) : '""',
441
+ text4: lines[3] ? JSON.stringify(lines[3]) : '""'
442
+ }
443
+ } else {
444
+ signData = {
445
+ text1: lines[0] ?? '',
446
+ text2: lines[1] ?? '',
447
+ text3: lines[2] ?? '',
448
+ text4: lines[3] ?? ''
449
+ }
450
+ }
467
451
  bot._client.write('update_sign', {
468
452
  location: block.position,
469
- text1: JSON.stringify(lines[0]),
470
- text2: JSON.stringify(lines[1]),
471
- text3: JSON.stringify(lines[2]),
472
- text4: JSON.stringify(lines[3])
453
+ ...signData
473
454
  })
474
455
  }
475
456
 
@@ -567,7 +548,6 @@ function inject (bot, { version, storageBuilder }) {
567
548
  bot.canSeeBlock = canSeeBlock
568
549
  bot.blockAt = blockAt
569
550
  bot._updateBlockState = updateBlockState
570
- bot._blockEntities = blockEntities
571
551
  bot.waitForChunksToLoad = callbackify(waitForChunksToLoad)
572
552
  }
573
553
 
@@ -1,5 +1,4 @@
1
1
  const { Vec3 } = require('vec3')
2
- const Entity = require('prismarine-entity')
3
2
  const conv = require('../conversions')
4
3
  const NAMED_ENTITY_HEIGHT = 1.62
5
4
  const NAMED_ENTITY_WIDTH = 0.6
@@ -26,6 +25,7 @@ const entityStatusEvents = {
26
25
  }
27
26
 
28
27
  function inject (bot, { version }) {
28
+ const Entity = require('prismarine-entity')(version)
29
29
  const objects = require('minecraft-data')(version).objects
30
30
  const mobs = require('minecraft-data')(version).mobs
31
31
  const entitiesArray = require('minecraft-data')(version).entitiesArray
@@ -548,11 +548,18 @@ function inject (bot, { version }) {
548
548
  }
549
549
 
550
550
  function attack (target, swing = true) {
551
- // arm animation comes before the use_entity packet
552
- if (swing) {
553
- swingArm()
551
+ // arm animation comes before the use_entity packet on 1.8
552
+ if (bot.supportFeature('armAnimationBeforeUse')) {
553
+ if (swing) {
554
+ swingArm()
555
+ }
556
+ useEntity(target, 1)
557
+ } else {
558
+ useEntity(target, 1)
559
+ if (swing) {
560
+ swingArm()
561
+ }
554
562
  }
555
- useEntity(target, 1)
556
563
  }
557
564
 
558
565
  function mount (target) {
@@ -37,7 +37,12 @@ function inject (bot, options) {
37
37
  }
38
38
 
39
39
  if (bot.supportFeature('dimensionDataIsAvailable')) {
40
- bot.game.dimensionData = nbt.simplify(packet.dimension)
40
+ const dimensionData = nbt.simplify(packet.dimension)
41
+ bot.game.minY = dimensionData.min_y
42
+ bot.game.height = dimensionData.height
43
+ } else {
44
+ bot.game.minY = 0
45
+ bot.game.height = 256
41
46
  }
42
47
  if (packet.difficulty) {
43
48
  bot.game.difficulty = difficultyNames[packet.difficulty]
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  module.exports = {
2
- supportedVersions: ['1.8', '1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16', '1.17'],
3
- 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']
2
+ supportedVersions: ['1.8', '1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16', '1.17', '1.18'],
3
+ 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.1']
4
4
  } // when updating testedVersions, make sure to update CI.yml