mirror of
https://github.com/PrismarineJS/node-minecraft-protocol.git
synced 2024-11-24 00:07:51 -05:00
reapply on master (#1067)
This commit is contained in:
parent
d9e37e3d76
commit
d643d40415
3 changed files with 59 additions and 12 deletions
|
@ -266,9 +266,9 @@ Called when an error occurs within the client. Takes an Error as parameter.
|
|||
### `playerChat` event
|
||||
|
||||
Called when a chat message from another player arrives. The emitted object contains:
|
||||
* formattedMessage -- the chat message preformatted, if done on server side
|
||||
* plainMessage -- the chat message without formatting (for example no `<username> message` ; instead `message`), on version 1.19+
|
||||
* unsignedContent -- unsigned formatted chat contents ; should only be present when the message is modified and server has chat previews disabled - only on version 1.19 - 1.19.2
|
||||
* formattedMessage -- (JSON) the chat message preformatted, if done on server side
|
||||
* plainMessage -- (Plaintext) the chat message without formatting (for example no `<username> message` ; instead `message`), on version 1.19+
|
||||
* unsignedContent -- (JSON) unsigned formatted chat contents ; should only be present when the message is modified and server has chat previews disabled - only on version 1.19 - 1.19.2
|
||||
* type -- the message type - on 1.19, which format string to use to render message ; below, the place where the message is displayed (for example chat or action bar)
|
||||
* sender -- the UUID of the player sending the message
|
||||
* senderTeam -- scoreboard team of the player (pre 1.19)
|
||||
|
@ -279,7 +279,7 @@ Called when a chat message from another player arrives. The emitted object conta
|
|||
### `systemChat` event
|
||||
|
||||
Called when a system chat message arrives. A system chat message is any message not sent by a player. The emitted object contains:
|
||||
* formattedMessage -- the chat message preformatted
|
||||
* formattedMessage -- (JSON) the chat message preformatted
|
||||
* positionId -- the chat type of the message. 1 for system chat and 2 for actionbar
|
||||
|
||||
See the [chat example](https://github.com/PrismarineJS/node-minecraft-protocol/blob/master/examples/client_chat/client_chat.js#L1) for usage.
|
||||
|
|
|
@ -266,7 +266,7 @@ module.exports = function (client, options) {
|
|||
plain: packet.plainMessage,
|
||||
decorated: packet.formattedMessage
|
||||
},
|
||||
messageHash: packet.bodyDigest,
|
||||
messageHash: packet.messageHash,
|
||||
timestamp: packet.timestamp,
|
||||
salt: packet.salt,
|
||||
lastSeen: packet.previousMessages
|
||||
|
@ -297,6 +297,39 @@ module.exports = function (client, options) {
|
|||
})
|
||||
})
|
||||
|
||||
const sliceIndexForMessage = {}
|
||||
client.on('declare_commands', (packet) => {
|
||||
const nodes = packet.nodes
|
||||
for (const commandNode of nodes[0].children) {
|
||||
const node = nodes[commandNode]
|
||||
const commandName = node.extraNodeData.name
|
||||
function visit (node, depth = 0) {
|
||||
const name = node.extraNodeData.name
|
||||
if (node.extraNodeData.parser === 'minecraft:message') {
|
||||
sliceIndexForMessage[commandName] = [name, depth]
|
||||
}
|
||||
for (const child of node.children) {
|
||||
visit(nodes[child], depth + 1)
|
||||
}
|
||||
}
|
||||
visit(node, 0)
|
||||
}
|
||||
})
|
||||
|
||||
function signaturesForCommand (string, ts, salt) {
|
||||
const signatures = []
|
||||
const slices = string.split(' ')
|
||||
if (sliceIndexForMessage[slices[0]]) {
|
||||
const [fieldName, sliceIndex] = sliceIndexForMessage[slices[0]]
|
||||
const sliced = slices.slice(sliceIndex)
|
||||
if (sliced.length > 0) {
|
||||
const signable = sliced.join(' ')
|
||||
signatures.push({ argumentName: fieldName, signature: client.signMessage(signable, ts, salt) })
|
||||
}
|
||||
}
|
||||
return signatures
|
||||
}
|
||||
|
||||
// Chat Sending
|
||||
let pendingChatRequest
|
||||
let lastPreviewRequestId = 0
|
||||
|
@ -305,6 +338,23 @@ module.exports = function (client, options) {
|
|||
options.timestamp = options.timestamp || BigInt(Date.now())
|
||||
options.salt = options.salt || 1n
|
||||
|
||||
if (message.startsWith('/') && !mcData.supportFeature('useChatSessions')) {
|
||||
const command = message.slice(1)
|
||||
client.write('chat_command', {
|
||||
command,
|
||||
timestamp: options.timestamp,
|
||||
salt: options.salt,
|
||||
argumentSignatures: signaturesForCommand(command, options.timestamp, options.salt),
|
||||
signedPreview: options.didPreview,
|
||||
previousMessages: client._lastSeenMessages.map((e) => ({
|
||||
messageSender: e.sender,
|
||||
messageSignature: e.signature
|
||||
})),
|
||||
lastRejectedMessage: client._lastRejectedMessage
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (mcData.supportFeature('useChatSessions')) {
|
||||
let acc = 0
|
||||
const acknowledgements = []
|
||||
|
@ -351,7 +401,7 @@ module.exports = function (client, options) {
|
|||
lastRejectedMessage: client._lastRejectedMessage
|
||||
})
|
||||
client._lastSeenMessages.pending = 0
|
||||
} else {
|
||||
} else if (client.serverFeatures.chatPreview) {
|
||||
client.write('chat_preview', {
|
||||
query: lastPreviewRequestId,
|
||||
message
|
||||
|
|
|
@ -7,12 +7,9 @@ const { mojangPublicKeyPem } = require('./constants')
|
|||
class VerificationError extends Error {}
|
||||
function validateLastMessages (pending, lastSeen, lastRejected) {
|
||||
if (lastRejected) {
|
||||
const rejectedTs = pending.get(lastRejected.sender, lastRejected.signature)
|
||||
if (!rejectedTs) {
|
||||
throw new VerificationError(`Client rejected a message we never sent from '${lastRejected.sender}'`)
|
||||
} else {
|
||||
pending.acknowledge(lastRejected.sender, lastRejected.signature)
|
||||
}
|
||||
const rejectedTime = pending.get(lastRejected.sender, lastRejected.signature)
|
||||
if (rejectedTime) pending.acknowledge(lastRejected.sender, lastRejected.signature)
|
||||
else throw new VerificationError(`Client rejected a message we never sent from '${lastRejected.sender}'`)
|
||||
}
|
||||
|
||||
let lastTimestamp
|
||||
|
|
Loading…
Reference in a new issue