mineflayer 4.6.0 → 4.8.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 +4 -0
- package/README.md +3 -2
- package/docs/README.md +3 -2
- package/docs/api.md +3 -2
- package/docs/history.md +11 -1
- package/docs/ru/README_RU.md +2 -2
- package/examples/discord.js +32 -28
- package/examples/telegram.js +43 -0
- package/index.d.ts +3 -0
- package/lib/plugins/blocks.js +5 -1
- package/lib/plugins/chat.js +33 -45
- package/lib/plugins/entities.js +125 -56
- package/lib/version.js +1 -1
- package/package.json +3 -3
package/.github/workflows/ci.yml
CHANGED
package/README.md
CHANGED
|
@@ -189,8 +189,9 @@ The most updated and useful are :
|
|
|
189
189
|
* [Auto Crystal](https://github.com/link-discord/mineflayer-autocrystal) - Automatic placing & breaking of end crystals.
|
|
190
190
|
* [Tool](https://github.com/TheDudeFromCI/mineflayer-tool) - A utility for automatic tool/weapon selection with a high level API.
|
|
191
191
|
* [Hawkeye](https://github.com/sefirosweb/minecraftHawkEye) - A utility for using auto-aim with bows.
|
|
192
|
-
* [GUI](https://github.com/firejoust/mineflayer-GUI) -
|
|
193
|
-
* [Projectile](https://github.com/firejoust/mineflayer-projectile) -
|
|
192
|
+
* [GUI](https://github.com/firejoust/mineflayer-GUI) - Interact with nested GUI windows using async/await
|
|
193
|
+
* [Projectile](https://github.com/firejoust/mineflayer-projectile) - Get the required launch angle for projectiles
|
|
194
|
+
* [Movement](https://github.com/firejoust/mineflayer-movement) - Smooth and realistic player movement, best suited for PvP
|
|
194
195
|
|
|
195
196
|
|
|
196
197
|
But also check out :
|
package/docs/README.md
CHANGED
|
@@ -189,8 +189,9 @@ The most updated and useful are :
|
|
|
189
189
|
* [Auto Crystal](https://github.com/link-discord/mineflayer-autocrystal) - Automatic placing & breaking of end crystals.
|
|
190
190
|
* [Tool](https://github.com/TheDudeFromCI/mineflayer-tool) - A utility for automatic tool/weapon selection with a high level API.
|
|
191
191
|
* [Hawkeye](https://github.com/sefirosweb/minecraftHawkEye) - A utility for using auto-aim with bows.
|
|
192
|
-
* [GUI](https://github.com/firejoust/mineflayer-GUI) -
|
|
193
|
-
* [Projectile](https://github.com/firejoust/mineflayer-projectile) -
|
|
192
|
+
* [GUI](https://github.com/firejoust/mineflayer-GUI) - Interact with nested GUI windows using async/await
|
|
193
|
+
* [Projectile](https://github.com/firejoust/mineflayer-projectile) - Get the required launch angle for projectiles
|
|
194
|
+
* [Movement](https://github.com/firejoust/mineflayer-movement) - Smooth and realistic player movement, best suited for PvP
|
|
194
195
|
|
|
195
196
|
|
|
196
197
|
But also check out :
|
package/docs/api.md
CHANGED
|
@@ -1156,7 +1156,8 @@ Emitted for every server message which appears on the Action Bar.
|
|
|
1156
1156
|
|
|
1157
1157
|
Emitted for every server message, including chats.
|
|
1158
1158
|
|
|
1159
|
-
* `jsonMsg` -
|
|
1159
|
+
* `jsonMsg` - [ChatMessage](https://github.com/PrismarineJS/prismarine-chat) object containing the formatted chat message. Might additionally have the following properties:
|
|
1160
|
+
* unsigned - Unsigned ChatMessage object. Only present in 1.19.2+, and only when the server allows insecure chat and the server modified the chat message without the user's signature
|
|
1160
1161
|
|
|
1161
1162
|
* `position` - (>= 1.8.1): position of Chat message can be
|
|
1162
1163
|
* chat
|
|
@@ -1169,7 +1170,7 @@ Emitted for every server message, including chats.
|
|
|
1169
1170
|
|
|
1170
1171
|
#### "messagestr" (message, messagePosition, jsonMsg, sender, verified)
|
|
1171
1172
|
|
|
1172
|
-
Alias for the "message" event but it calls .toString() on the message object to get a string for the message before emitting.
|
|
1173
|
+
Alias for the "message" event but it calls .toString() on the prismarine-message object to get a string for the message before emitting.
|
|
1173
1174
|
|
|
1174
1175
|
* `sender` - UUID of sender if known (1.16+), else null
|
|
1175
1176
|
|
package/docs/history.md
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
4.
|
|
1
|
+
## 4.8.0
|
|
2
|
+
|
|
3
|
+
* Update chat parsing (@frej4189)
|
|
4
|
+
* Fix message event not including chat position (@frej4189)
|
|
5
|
+
* 1.19.3 (@frej4189)
|
|
6
|
+
|
|
7
|
+
## 4.7.0
|
|
8
|
+
|
|
9
|
+
* 1.19.2 support (@frej4189)
|
|
10
|
+
|
|
11
|
+
## 4.6.0
|
|
2
12
|
|
|
3
13
|
* Fix unhandled promise rejection in onceWithCleanup (@IceTank) [#2833](https://github.com/PrismarineJS/mineflayer/pull/2833)
|
|
4
14
|
* Extend every window that is opened with mineflayer specific window functions (@IceTank) [#2768][https://github.com/PrismarineJS/mineflayer/pull/2768]
|
package/docs/ru/README_RU.md
CHANGED
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
| <sub>EN</sub> [English](../README.md) | <sub>RU</sub> [русский](../ru/README_RU.md) | <sub>ES</sub> [Español](../es/README_ES.md) | <sub>FR</sub> [Français](../fr/README_FR.md) | <sub>TR</sub> [Türkçe](../tr/README_TR.md) | <sub>ZH</sub> [中文](../zh/README_ZH_CN.md) |
|
|
13
13
|
|-------------------------|----------------------------|----------------------------|----------------------------|----------------------------|----------------------------|
|
|
14
14
|
|
|
15
|
-
Создавайте ботов Minecraft с помощью мощного, стабильного и высокоуровневого JavaScript [API](api.md)
|
|
15
|
+
Создавайте ботов Minecraft с помощью мощного, стабильного и высокоуровневого JavaScript [API](api.md), также можете использовать Python
|
|
16
16
|
|
|
17
|
-
Первый раз используете Node.js? Начните с [этого](tutorial.md).
|
|
17
|
+
Первый раз используете Node.js? Начните с [этого](tutorial.md). Любите гонять змею? Зацените [Python примеры](https://github.com/PrismarineJS/mineflayer/tree/master/examples/python) и попробуйте колабнуться в [Mineflayer Google коллабе](https://colab.research.google.com/github/PrismarineJS/mineflayer/blob/master/docs/mineflayer.ipynb).
|
|
18
18
|
|
|
19
19
|
## Возможности
|
|
20
20
|
|
package/examples/discord.js
CHANGED
|
@@ -1,57 +1,64 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* This example is a very simple way how to connect a discord bot with a mineflayer bot.
|
|
3
3
|
* For this example you will need discord.js installed. You can install with: npm install discord.js
|
|
4
|
-
* This example uses discord.js
|
|
4
|
+
* This example uses discord.js v14
|
|
5
5
|
* You need to do this before running this example:
|
|
6
|
-
* - You need to get a discord token
|
|
6
|
+
* - You need to get a discord bot token
|
|
7
7
|
* - You need to get the id of the channel you want to use
|
|
8
|
-
|
|
8
|
+
*
|
|
9
|
+
* Original credit to U9G, updated by Jovan04 12/19/2022
|
|
10
|
+
*/
|
|
9
11
|
|
|
10
12
|
if (process.argv.length < 6 || process.argv.length > 8) {
|
|
11
|
-
console.log('Usage : node discord.js <discord bot token> <channel id> <host> <port> [<name>] [<
|
|
13
|
+
console.log('Usage : node discord.js <discord bot token> <channel id> <host> <port> [<name>] [<auth>]')
|
|
12
14
|
process.exit(1)
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
//
|
|
16
|
-
const {
|
|
17
|
-
|
|
18
|
-
Intents
|
|
19
|
-
} = require('discord.js')
|
|
20
|
-
// Create Discord intentions, required in v13
|
|
21
|
-
const intents = new Intents(['GUILDS', 'GUILD_MESSAGES'])
|
|
22
|
-
// Create Discord client
|
|
23
|
-
const client = new Client({
|
|
24
|
-
intents
|
|
25
|
-
})
|
|
17
|
+
// load discord.js
|
|
18
|
+
const { Client, GatewayIntentBits } = require('discord.js')
|
|
19
|
+
const { MessageContent, GuildMessages, Guilds } = GatewayIntentBits
|
|
26
20
|
|
|
27
21
|
let channel = process.argv[3]
|
|
22
|
+
const token = process.argv[2]
|
|
23
|
+
|
|
24
|
+
// create new discord client that can see what servers the bot is in, as well as the messages in those servers
|
|
25
|
+
const client = new Client({ intents: [Guilds, GuildMessages, MessageContent] })
|
|
26
|
+
client.login(token)
|
|
28
27
|
|
|
29
|
-
//
|
|
28
|
+
// load mineflayer
|
|
30
29
|
const mineflayer = require('mineflayer')
|
|
31
|
-
|
|
30
|
+
|
|
31
|
+
// bot options
|
|
32
|
+
const options = {
|
|
32
33
|
host: process.argv[4],
|
|
33
34
|
port: parseInt(process.argv[5]),
|
|
34
35
|
username: process.argv[6] || 'discord',
|
|
35
|
-
|
|
36
|
+
auth: process.argv[7] || 'offline'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// join server
|
|
40
|
+
const bot = mineflayer.createBot(options)
|
|
41
|
+
bot.on('spawn', () => {
|
|
42
|
+
console.log(`Mineflayer bot logged in as ${bot.username}`)
|
|
36
43
|
})
|
|
37
44
|
|
|
38
|
-
client
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
// when discord client is ready, send login message
|
|
46
|
+
client.once('ready', (c) => {
|
|
47
|
+
console.log(`Discord bot logged in as ${c.user.tag}`)
|
|
41
48
|
channel = client.channels.cache.get(channel)
|
|
42
49
|
if (!channel) {
|
|
43
|
-
console.log(`I could not find the channel (${process.argv[3]})
|
|
50
|
+
console.log(`I could not find the channel (${process.argv[3]})!`)
|
|
51
|
+
console.log('Usage : node discord.js <discord bot token> <channel id> <host> <port> [<name>] [<auth>]')
|
|
44
52
|
process.exit(1)
|
|
45
53
|
}
|
|
46
54
|
})
|
|
47
55
|
|
|
48
|
-
|
|
49
|
-
client.on('messageCreate', message => {
|
|
56
|
+
client.on('messageCreate', (message) => {
|
|
50
57
|
// Only handle messages in specified channel
|
|
51
58
|
if (message.channel.id !== channel.id) return
|
|
52
59
|
// Ignore messages from the bot itself
|
|
53
60
|
if (message.author.id === client.user.id) return
|
|
54
|
-
|
|
61
|
+
// console.log(message)
|
|
55
62
|
bot.chat(`${message.author.username}: ${message.content}`)
|
|
56
63
|
})
|
|
57
64
|
|
|
@@ -62,6 +69,3 @@ bot.on('chat', (username, message) => {
|
|
|
62
69
|
|
|
63
70
|
channel.send(`${username}: ${message}`)
|
|
64
71
|
})
|
|
65
|
-
|
|
66
|
-
// Login Discord bot
|
|
67
|
-
client.login(process.argv[2])
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This example is a very simple way of connecting to a telegram group
|
|
3
|
+
* For this example you'll need Telegraf installed. This can be done with `npm install telegraf`
|
|
4
|
+
* You need to do this before running this example:
|
|
5
|
+
* - You need to get a telegram bot token from @botfather
|
|
6
|
+
* - You need to get the id of the group you want to use
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
if (process.argv.length < 6 || process.argv.length > 8) {
|
|
10
|
+
console.log('Usage : node telegram.js <telegram bot token> <group id> <host> <port> [<name>] [<password>]')
|
|
11
|
+
process.exit(1)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Load Telegraf
|
|
15
|
+
const { Telegraf } = require('telegraf')
|
|
16
|
+
const telegram = new Telegraf(process.argv[2])
|
|
17
|
+
|
|
18
|
+
// Load mineflayer
|
|
19
|
+
const mineflayer = require('mineflayer')
|
|
20
|
+
const bot = mineflayer.createBot({
|
|
21
|
+
host: process.argv[4],
|
|
22
|
+
port: parseInt(process.argv[5]),
|
|
23
|
+
username: process.argv[6] || 'telegram',
|
|
24
|
+
password: process.argv[7]
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
telegram.on('text', async (ctx) => {
|
|
28
|
+
// check if message was reveived from chosen group
|
|
29
|
+
if (ctx.update.message.chat.id.toString() === process.argv[3]) {
|
|
30
|
+
// send message to mc server
|
|
31
|
+
bot.chat(`${ctx.update.message.from.first_name} ${ctx.update.message.from.last_name}: ${ctx.update.message.text}`)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
// Redirect in-game messages to telegram group
|
|
36
|
+
bot.on('chat', (username, message) => {
|
|
37
|
+
// Ignore messages from the bot itself
|
|
38
|
+
if (username === bot.username) return
|
|
39
|
+
telegram.telegram.sendMessage(process.argv[3], username + ': ' + message)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Login telegram bot
|
|
43
|
+
telegram.launch()
|
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 { Registry } from 'prismarine-registry'
|
|
11
12
|
|
|
12
13
|
export function createBot (options: { client: Client } & Partial<BotOptions>): Bot
|
|
13
14
|
export function createBot (options: BotOptions): Bot
|
|
@@ -192,6 +193,7 @@ export interface Bot extends TypedEmitter<BotEvents> {
|
|
|
192
193
|
currentWindow: Window | null
|
|
193
194
|
simpleClick: simpleClick
|
|
194
195
|
tablist: Tablist
|
|
196
|
+
registry: Registry
|
|
195
197
|
|
|
196
198
|
connect: (options: BotOptions) => void
|
|
197
199
|
|
|
@@ -565,6 +567,7 @@ export interface TransferOptions {
|
|
|
565
567
|
window: Window
|
|
566
568
|
itemType: number
|
|
567
569
|
metadata: number | null
|
|
570
|
+
count?: number,
|
|
568
571
|
sourceStart: number
|
|
569
572
|
sourceEnd: number
|
|
570
573
|
destStart: number
|
package/lib/plugins/blocks.js
CHANGED
|
@@ -20,7 +20,7 @@ const dimensionNames = {
|
|
|
20
20
|
1: 'minecraft:end'
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function inject (bot, { version, storageBuilder }) {
|
|
23
|
+
function inject (bot, { version, storageBuilder, hideErrors }) {
|
|
24
24
|
const Block = require('prismarine-block')(bot.registry)
|
|
25
25
|
const Chunk = require('prismarine-chunk')(bot.registry)
|
|
26
26
|
const World = require('prismarine-world')(bot.registry)
|
|
@@ -289,6 +289,10 @@ function inject (bot, { version, storageBuilder }) {
|
|
|
289
289
|
|
|
290
290
|
if (typeof packet.blockEntities !== 'undefined') {
|
|
291
291
|
const column = bot.world.getColumn(packet.x, packet.z)
|
|
292
|
+
if (!column) {
|
|
293
|
+
if (!hideErrors) console.warn('Ignoring block entities as chunk failed to load at', packet.x, packet.z)
|
|
294
|
+
return
|
|
295
|
+
}
|
|
292
296
|
for (const blockEntity of packet.blockEntities) {
|
|
293
297
|
if (blockEntity.x !== undefined) { // 1.17+
|
|
294
298
|
column.setBlockEntity(blockEntity, blockEntity.nbtData)
|
package/lib/plugins/chat.js
CHANGED
|
@@ -108,43 +108,37 @@ function inject (bot, options) {
|
|
|
108
108
|
|
|
109
109
|
addDefaultPatterns()
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (packet.position === 2) bot.emit('actionBar', msg, null)
|
|
123
|
-
})
|
|
111
|
+
bot._client.on('playerChat', (data) => {
|
|
112
|
+
const message = data.formattedMessage
|
|
113
|
+
const verified = data.verified
|
|
114
|
+
let msg
|
|
115
|
+
if (bot.supportFeature('clientsideChatFormatting')) {
|
|
116
|
+
const parameters = {
|
|
117
|
+
sender: data.senderName ? JSON.parse(data.senderName) : undefined,
|
|
118
|
+
target: data.targetName ? JSON.parse(data.targetName) : undefined,
|
|
119
|
+
content: message ? JSON.parse(message) : { text: data.plainMessage }
|
|
120
|
+
}
|
|
121
|
+
msg = ChatMessage.fromNetwork(data.type, parameters)
|
|
124
122
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (sender) {
|
|
131
|
-
const { profileKeys } = bot.players[sender]
|
|
132
|
-
if (profileKeys) verified = bot._client.verifyMessage(profileKeys.publicKey, packet)
|
|
133
|
-
}
|
|
134
|
-
const parameters = {
|
|
135
|
-
sender: JSON.parse(packet.senderName),
|
|
136
|
-
content: JSON.parse(message)
|
|
123
|
+
if (data.unsignedContent) {
|
|
124
|
+
msg.unsigned = ChatMessage.fromNetwork(data.type, { sender: parameters.sender, target: parameters.target, content: JSON.parse(data.unsignedContent) })
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
msg = ChatMessage.fromNotch(message)
|
|
137
128
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
bot.emit('message', msg, 'chat', packet.senderUuid, verified)
|
|
141
|
-
bot.emit('messagestr', msg.toString(), 'chat', msg, packet.senderUuid, verified)
|
|
129
|
+
bot.emit('message', msg, 'chat', data.sender, verified)
|
|
130
|
+
bot.emit('messagestr', msg.toString(), 'chat', msg, data.sender, verified)
|
|
142
131
|
})
|
|
143
132
|
|
|
144
|
-
bot._client.on('
|
|
145
|
-
const msg = ChatMessage.fromNotch(
|
|
146
|
-
|
|
147
|
-
|
|
133
|
+
bot._client.on('systemChat', (data) => {
|
|
134
|
+
const msg = ChatMessage.fromNotch(data.formattedMessage)
|
|
135
|
+
const chatPositions = {
|
|
136
|
+
1: 'system',
|
|
137
|
+
2: 'game_info'
|
|
138
|
+
}
|
|
139
|
+
bot.emit('message', msg, chatPositions[data.positionId], null)
|
|
140
|
+
bot.emit('messagestr', msg.toString(), chatPositions[data.positionId], msg, null)
|
|
141
|
+
if (data.positionId === 2) bot.emit('actionBar', msg, null)
|
|
148
142
|
})
|
|
149
143
|
|
|
150
144
|
function chatWithHeader (header, message) {
|
|
@@ -163,7 +157,11 @@ function inject (bot, options) {
|
|
|
163
157
|
timestamp,
|
|
164
158
|
salt: 0n,
|
|
165
159
|
argumentSignatures: [],
|
|
166
|
-
signedPreview: false
|
|
160
|
+
signedPreview: false,
|
|
161
|
+
messageCount: 0,
|
|
162
|
+
acknowledged: Buffer.alloc(3),
|
|
163
|
+
// 1.19.2 Chat Command packet also includes an array of last seen messages
|
|
164
|
+
previousMessages: []
|
|
167
165
|
})
|
|
168
166
|
return
|
|
169
167
|
}
|
|
@@ -176,17 +174,7 @@ function inject (bot, options) {
|
|
|
176
174
|
let smallMsg
|
|
177
175
|
for (i = 0; i < subMessage.length; i += lengthLimit) {
|
|
178
176
|
smallMsg = header + subMessage.substring(i, i + lengthLimit)
|
|
179
|
-
|
|
180
|
-
const timestamp = BigInt(Date.now())
|
|
181
|
-
bot._client.write('chat_message', {
|
|
182
|
-
message: smallMsg,
|
|
183
|
-
timestamp,
|
|
184
|
-
salt: 0,
|
|
185
|
-
signature: bot._client.profileKeys ? bot._client.signMessage(smallMsg, timestamp) : Buffer.alloc(0)
|
|
186
|
-
})
|
|
187
|
-
} else {
|
|
188
|
-
bot._client.write('chat', { message: smallMsg })
|
|
189
|
-
}
|
|
177
|
+
bot._client.chat(smallMsg)
|
|
190
178
|
}
|
|
191
179
|
})
|
|
192
180
|
}
|
package/lib/plugins/entities.js
CHANGED
|
@@ -361,13 +361,14 @@ function inject (bot) {
|
|
|
361
361
|
entity.metadata = metadata
|
|
362
362
|
bot.emit('entityUpdate', entity)
|
|
363
363
|
|
|
364
|
-
const typeSlot = bot.supportFeature('itemsAreAlsoBlocks') ? 5 : 6
|
|
364
|
+
const typeSlot = (bot.supportFeature('itemsAreAlsoBlocks') ? 5 : 6) + (bot.supportFeature('entityMetadataHasLong') ? 1 : 0)
|
|
365
365
|
const slot = packet.metadata.find(e => e.type === typeSlot)
|
|
366
366
|
if (entity.name && (entity.name.toLowerCase() === 'item' || entity.name === 'item_stack') && slot) {
|
|
367
367
|
bot.emit('itemDrop', entity)
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
-
const
|
|
370
|
+
const typePose = bot.supportFeature('entityMetadataHasLong') ? 19 : 18
|
|
371
|
+
const pose = packet.metadata.find(e => e.type === typePose)
|
|
371
372
|
if (pose && pose.value === 2) {
|
|
372
373
|
bot.emit('entitySleep', entity)
|
|
373
374
|
}
|
|
@@ -444,81 +445,149 @@ function inject (bot) {
|
|
|
444
445
|
|
|
445
446
|
bot._client.on('player_info', (packet) => {
|
|
446
447
|
// player list item(s)
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
448
|
+
|
|
449
|
+
if (bot.supportFeature('playerInfoActionIsBitfield')) {
|
|
450
|
+
for (const item of packet.data) {
|
|
451
|
+
let player = bot.uuidToUsername[item.uuid] ? bot.players[bot.uuidToUsername[item.uuid]] : null
|
|
450
452
|
let newPlayer = false
|
|
451
453
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
username: item.name,
|
|
456
|
-
ping: item.ping,
|
|
457
|
-
uuid: item.UUID,
|
|
458
|
-
displayName: new ChatMessage({ text: '', extra: [{ text: item.name }] }),
|
|
459
|
-
profileKeys: item.crypto
|
|
460
|
-
? {
|
|
461
|
-
publicKey: item.crypto.publicKey, // DER-encoded public key
|
|
462
|
-
signature: item.crypto.signature // Signature
|
|
463
|
-
}
|
|
464
|
-
: null
|
|
465
|
-
}
|
|
454
|
+
const obj = {
|
|
455
|
+
uuid: item.uuid
|
|
456
|
+
}
|
|
466
457
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
458
|
+
if (!player) newPlayer = true
|
|
459
|
+
|
|
460
|
+
player = player || obj
|
|
461
|
+
|
|
462
|
+
if (packet.action & 1) {
|
|
463
|
+
obj.username = item.player.name
|
|
464
|
+
obj.displayName = player.displayName || new ChatMessage({ text: '', extra: [{ text: item.player.name }] })
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (packet.action & 4) {
|
|
468
|
+
obj.gamemode = item.gamemode
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (packet.action & 16) {
|
|
472
|
+
obj.ping = item.latency
|
|
480
473
|
}
|
|
481
474
|
|
|
482
475
|
if (item.displayName) {
|
|
483
|
-
|
|
476
|
+
obj.displayName = new ChatMessage(JSON.parse(item.displayName))
|
|
477
|
+
} else if (packet.action & 32) obj.displayName = new ChatMessage({ text: '', extra: [{ text: player.username || obj.username }] })
|
|
478
|
+
|
|
479
|
+
if (newPlayer) {
|
|
480
|
+
if (!obj.username) continue // Should be unreachable
|
|
481
|
+
player = bot.players[obj.username] = obj
|
|
482
|
+
bot.uuidToUsername[obj.uuid] = obj.username
|
|
483
|
+
} else {
|
|
484
|
+
Object.assign(player, obj)
|
|
484
485
|
}
|
|
485
486
|
|
|
486
|
-
const playerEntity = Object.values(bot.entities).find(e => e.type === 'player' && e.username ===
|
|
487
|
+
const playerEntity = Object.values(bot.entities).find(e => e.type === 'player' && e.username === obj.username)
|
|
487
488
|
player.entity = playerEntity
|
|
488
489
|
|
|
489
490
|
if (playerEntity === bot.entity) {
|
|
490
491
|
bot.player = player
|
|
491
492
|
}
|
|
492
493
|
|
|
493
|
-
if (
|
|
494
|
-
bot.emit('
|
|
495
|
-
}
|
|
496
|
-
} else if (player) {
|
|
497
|
-
if (packet.action === 1) {
|
|
498
|
-
player.gamemode = item.gamemode
|
|
499
|
-
} else if (packet.action === 2) {
|
|
500
|
-
player.ping = item.ping
|
|
501
|
-
} else if (packet.action === 3 && !item.displayName) {
|
|
502
|
-
player.displayName = new ChatMessage({ text: '', extra: [{ text: player.username }] })
|
|
503
|
-
} else if (packet.action === 3 && item.displayName) {
|
|
504
|
-
player.displayName = new ChatMessage(JSON.parse(item.displayName))
|
|
505
|
-
} else if (packet.action === 4) {
|
|
506
|
-
if (player.entity === bot.entity) continue
|
|
507
|
-
|
|
508
|
-
player.entity = null
|
|
509
|
-
delete bot.players[player.username]
|
|
510
|
-
delete bot.uuidToUsername[item.UUID]
|
|
511
|
-
bot.emit('playerLeft', player)
|
|
512
|
-
continue
|
|
494
|
+
if (newPlayer) {
|
|
495
|
+
bot.emit('playerJoined', player)
|
|
513
496
|
} else {
|
|
514
|
-
|
|
497
|
+
bot.emit('playerUpdated', player)
|
|
515
498
|
}
|
|
499
|
+
}
|
|
500
|
+
} else {
|
|
501
|
+
for (const item of packet.data) {
|
|
502
|
+
let player = bot.uuidToUsername[item.UUID] ? bot.players[bot.uuidToUsername[item.UUID]] : null
|
|
503
|
+
if (packet.action === 0) {
|
|
504
|
+
let newPlayer = false
|
|
505
|
+
|
|
506
|
+
// New Player
|
|
507
|
+
if (!player) {
|
|
508
|
+
player = bot.players[item.name] = {
|
|
509
|
+
username: item.name,
|
|
510
|
+
ping: item.ping,
|
|
511
|
+
uuid: item.UUID,
|
|
512
|
+
displayName: new ChatMessage({ text: '', extra: [{ text: item.name }] }),
|
|
513
|
+
profileKeys: item.crypto
|
|
514
|
+
? {
|
|
515
|
+
publicKey: item.crypto.publicKey, // DER-encoded public key
|
|
516
|
+
signature: item.crypto.signature // Signature
|
|
517
|
+
}
|
|
518
|
+
: null
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
bot.uuidToUsername[item.UUID] = item.name
|
|
522
|
+
bot.emit('playerJoined', player)
|
|
523
|
+
newPlayer = true
|
|
524
|
+
} else {
|
|
525
|
+
// Just an Update
|
|
526
|
+
player.gamemode = item.gamemode
|
|
527
|
+
player.ping = item.ping
|
|
528
|
+
if (item.crypto) {
|
|
529
|
+
player.profileKeys = {
|
|
530
|
+
publicKey: item.crypto.publicKey,
|
|
531
|
+
signature: item.crypto.signature
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (item.displayName) {
|
|
537
|
+
player.displayName = new ChatMessage(JSON.parse(item.displayName))
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const playerEntity = Object.values(bot.entities).find(e => e.type === 'player' && e.username === item.name)
|
|
541
|
+
player.entity = playerEntity
|
|
542
|
+
|
|
543
|
+
if (playerEntity === bot.entity) {
|
|
544
|
+
bot.player = player
|
|
545
|
+
}
|
|
516
546
|
|
|
517
|
-
|
|
547
|
+
if (!newPlayer) {
|
|
548
|
+
bot.emit('playerUpdated', player)
|
|
549
|
+
}
|
|
550
|
+
} else if (player) {
|
|
551
|
+
if (packet.action === 1) {
|
|
552
|
+
player.gamemode = item.gamemode
|
|
553
|
+
} else if (packet.action === 2) {
|
|
554
|
+
player.ping = item.ping
|
|
555
|
+
} else if (packet.action === 3 && !item.displayName) {
|
|
556
|
+
player.displayName = new ChatMessage({ text: '', extra: [{ text: player.username }] })
|
|
557
|
+
} else if (packet.action === 3 && item.displayName) {
|
|
558
|
+
player.displayName = new ChatMessage(JSON.parse(item.displayName))
|
|
559
|
+
} else if (packet.action === 4) {
|
|
560
|
+
if (player.entity === bot.entity) continue
|
|
561
|
+
|
|
562
|
+
player.entity = null
|
|
563
|
+
delete bot.players[player.username]
|
|
564
|
+
delete bot.uuidToUsername[item.UUID]
|
|
565
|
+
bot.emit('playerLeft', player)
|
|
566
|
+
continue
|
|
567
|
+
} else {
|
|
568
|
+
continue
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
bot.emit('playerUpdated', player)
|
|
572
|
+
}
|
|
518
573
|
}
|
|
519
574
|
}
|
|
520
575
|
})
|
|
521
576
|
|
|
577
|
+
// (1.19.3) player(s) leave the game
|
|
578
|
+
bot._client.on('player_remove', (packet) => {
|
|
579
|
+
for (const uuid of packet.players) {
|
|
580
|
+
const player = bot.uuidToUsername[uuid] ? bot.players[bot.uuidToUsername[uuid]] : null
|
|
581
|
+
|
|
582
|
+
if (player.entity === bot.entity) continue
|
|
583
|
+
|
|
584
|
+
player.entity = null
|
|
585
|
+
delete bot.players[player.username]
|
|
586
|
+
delete bot.uuidToUsername[uuid]
|
|
587
|
+
bot.emit('playerLeft', player)
|
|
588
|
+
}
|
|
589
|
+
})
|
|
590
|
+
|
|
522
591
|
// attaching to a vehicle
|
|
523
592
|
bot._client.on('attach_entity', (packet) => {
|
|
524
593
|
if (packet.entityId !== bot.entity.id) return
|
package/lib/version.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
supportedVersions: ['1.8', '1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16', '1.17', '1.18', '1.19'],
|
|
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.2', '1.19']
|
|
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.2', '1.19', '1.19.2', '1.19.3']
|
|
4
4
|
} // when updating testedVersions, make sure to update CI.yml
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mineflayer",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.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,8 +21,8 @@
|
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"minecraft-data": "^3.
|
|
25
|
-
"minecraft-protocol": "^1.
|
|
24
|
+
"minecraft-data": "^3.26.0",
|
|
25
|
+
"minecraft-protocol": "^1.40.3",
|
|
26
26
|
"prismarine-biome": "^1.1.1",
|
|
27
27
|
"prismarine-block": "^1.13.1",
|
|
28
28
|
"prismarine-chat": "^1.7.1",
|