1
1
import type React from 'react'
2
- import { type MinecraftChat , parseValidJson } from '../../minecraft/chatToJsx'
2
+ // import nbt from 'prismarine-nbt'
3
+ import {
4
+ type MinecraftChat ,
5
+ parseChat ,
6
+ parseJsonChat
7
+ } from '../../minecraft/chatToJsx'
3
8
import {
4
9
ConnectionState ,
5
10
type ServerConnection
@@ -33,53 +38,92 @@ type HandleError = (
33
38
) => ( error : unknown ) => any
34
39
35
40
interface PlayerChatMessage {
36
- signedChat : string
37
- unsignedChat ?: string
41
+ signedChat : MinecraftChat
42
+ unsignedChat ?: MinecraftChat
38
43
type : number
39
- displayName : string
44
+ displayName : MinecraftChat
40
45
}
41
46
42
- const parsePlayerChatMessage = ( data : Buffer ) : PlayerChatMessage => {
43
- const [ signedChatLength , signedChatVarIntLength ] = readVarInt ( data )
44
- data = data . slice ( signedChatVarIntLength )
45
- const signedChat = data . slice ( 0 , signedChatLength ) . toString ( 'utf8' )
46
- data = data . slice ( signedChatLength )
47
+ const parsePlayerChatMessage = (
48
+ data : Buffer ,
49
+ version : number
50
+ ) : PlayerChatMessage => {
51
+ let signedChat : MinecraftChat
52
+ if ( version < protocolMap [ '1.20.3' ] ) {
53
+ const [ signedChatLength , signedChatVarIntLength ] = readVarInt ( data )
54
+ data = data . slice ( signedChatVarIntLength )
55
+ signedChat = parseJsonChat ( data . slice ( 0 , signedChatLength ) . toString ( 'utf8' ) )
56
+ data = data . slice ( signedChatLength )
57
+ } else {
58
+ signedChat = 'FIXME: NBT Chat'
59
+ // const signedChatNbt = nbt.parseUncompressed(data)
60
+ // signedChat = nbt.simplify(signedChatNbt)
61
+ // data = data.slice(nbt.writeUncompressed(signedChatNbt).length)
62
+ }
47
63
const hasUnsignedChat = data . readInt8 ( )
48
64
data = data . slice ( 1 )
49
- let unsignedChat
50
- if ( hasUnsignedChat ) {
65
+ let unsignedChat : MinecraftChat | undefined
66
+ if ( hasUnsignedChat && version < protocolMap [ '1.20.3' ] ) {
51
67
const [ unsignedChatLength , unsignedChatVarIntLength ] = readVarInt ( data )
52
68
data = data . slice ( unsignedChatVarIntLength )
53
- unsignedChat = data . slice ( 0 , unsignedChatLength ) . toString ( 'utf8' )
69
+ unsignedChat = parseJsonChat (
70
+ data . slice ( 0 , unsignedChatLength ) . toString ( 'utf8' )
71
+ )
54
72
data = data . slice ( unsignedChatLength )
73
+ } else if ( hasUnsignedChat ) {
74
+ unsignedChat = undefined // FIXME
75
+ // const unsignedChatNbt = nbt.parseUncompressed(data)
76
+ // unsignedChat = nbt.simplify(unsignedChatNbt)
77
+ // data = data.slice(nbt.writeUncompressed(unsignedChatNbt).length)
55
78
}
56
79
const [ type , typeLength ] = readVarInt ( data )
57
80
data = data . slice ( typeLength )
58
81
data = data . slice ( 16 ) // Skip sender UUID
59
- const [ displayNameLength , displayNameVarIntLength ] = readVarInt ( data )
60
- data = data . slice ( displayNameVarIntLength )
61
- const displayName = data . slice ( 0 , displayNameLength ) . toString ( 'utf8' )
82
+ let displayName : MinecraftChat
83
+ if ( version < protocolMap [ '1.20.3' ] ) {
84
+ const [ displayNameLength , displayNameVarIntLength ] = readVarInt ( data )
85
+ data = data . slice ( displayNameVarIntLength )
86
+ displayName = parseJsonChat (
87
+ data . slice ( 0 , displayNameLength ) . toString ( 'utf8' )
88
+ )
89
+ data = data . slice ( displayNameLength )
90
+ } else {
91
+ displayName = 'FIXME: NBT Chat'
92
+ // const displayNameNbt = nbt.parseUncompressed(data)
93
+ // displayName = nbt.simplify(displayNameNbt)
94
+ // data = data.slice(nbt.writeUncompressed(displayNameNbt).length)
95
+ }
62
96
return { signedChat, unsignedChat, type, displayName }
63
97
}
64
98
65
99
const handleSystemMessage = (
66
100
packet : Packet ,
67
101
addMessage : ( text : MinecraftChat ) => void ,
68
102
handleError : HandleError ,
69
- is1191 : boolean
103
+ version : number
70
104
) : void => {
71
105
try {
72
- const [ chatLength , chatVarIntLength ] = readVarInt ( packet . data )
73
- const chatJson = packet . data
74
- . slice ( chatVarIntLength , chatVarIntLength + chatLength )
75
- . toString ( 'utf8' )
106
+ let parsedChat : MinecraftChat
107
+ let offset
108
+ if ( version < protocolMap [ '1.20.3' ] ) {
109
+ const [ chatLength , chatViLength ] = readVarInt ( packet . data )
110
+ const chat = packet . data . slice ( chatViLength , chatViLength + chatLength )
111
+ parsedChat = parseJsonChat ( chat . toString ( 'utf8' ) )
112
+ offset = chatViLength + chatLength
113
+ } else {
114
+ parsedChat = 'FIXME: NBT Chat'
115
+ offset = packet . data . length - 1
116
+ // const chatNbt = nbt.parseUncompressed(packet.data)
117
+ // parsedChat = nbt.simplify(chatNbt)
118
+ // offset = nbt.writeUncompressed(chatNbt).length
119
+ }
76
120
// TODO: Support position 2 (action bar), true (action bar) and sender for disableChat/blocked players.
77
121
// TODO-1.19: 3 say command, 4 msg command, 5 team msg command, 6 emote command, 7 tellraw command, also in Player Chat Message.
78
- const position = packet . data . readInt8 ( chatVarIntLength + chatLength )
79
- if ( ! is1191 && ( position === 0 || position === 1 ) ) {
80
- addMessage ( parseValidJson ( chatJson ) )
81
- } else if ( is1191 && ! position ) {
82
- addMessage ( parseValidJson ( chatJson ) )
122
+ const position = packet . data . readInt8 ( offset )
123
+ if ( version < protocolMap [ '1.19.1' ] && ( position === 0 || position === 1 ) ) {
124
+ addMessage ( parsedChat )
125
+ } else if ( version >= protocolMap [ '1.19.1' ] && ! position ) {
126
+ addMessage ( parsedChat )
83
127
}
84
128
} catch ( e ) {
85
129
handleError ( addMessage , parseMessageError ) ( e )
@@ -138,7 +182,6 @@ export const packetHandler =
138
182
const { protocolVersion : version } = connection . options
139
183
const is117 = version >= protocolMap [ 1.17 ]
140
184
const is118 = version >= protocolMap [ 1.18 ]
141
- const is1191 = version >= protocolMap [ '1.19.1' ]
142
185
143
186
// LOW-TODO: 1.20.2 also has a second Client Information in configuration state, do we send it?
144
187
if ( connection . state === ConnectionState . PLAY ) {
@@ -194,25 +237,22 @@ export const packetHandler =
194
237
. catch ( handleError ( addMessage , sendMessageError ) )
195
238
}
196
239
} else if ( packet . id === packetIds . CLIENTBOUND_CHAT_MESSAGE ( version ) ) {
197
- handleSystemMessage ( packet , addMessage , handleError , is1191 )
240
+ handleSystemMessage ( packet , addMessage , handleError , version )
198
241
} else if (
199
242
packet . id === packetIds . CLIENTBOUND_SYSTEM_CHAT_MESSAGE ( version )
200
243
) {
201
- handleSystemMessage ( packet , addMessage , handleError , is1191 )
244
+ handleSystemMessage ( packet , addMessage , handleError , version )
202
245
} else if (
203
246
packet . id === packetIds . CLIENTBOUND_PLAYER_CHAT_MESSAGE ( version )
204
247
) {
205
248
try {
206
249
const { type, displayName, signedChat, unsignedChat } =
207
- parsePlayerChatMessage ( packet . data )
250
+ parsePlayerChatMessage ( packet . data , version )
208
251
// TODO-1.19: Support sender team name
209
252
if ( type === 0 || type === 1 ) {
210
253
addMessage ( {
211
254
translate : 'chat.type.text' ,
212
- with : [
213
- parseValidJson ( displayName ) ,
214
- parseValidJson ( unsignedChat ?? signedChat )
215
- ]
255
+ with : [ displayName , unsignedChat ?? signedChat ]
216
256
} )
217
257
}
218
258
} catch ( e ) {
@@ -238,9 +278,8 @@ export const packetHandler =
238
278
data = data . slice ( readVarInt ( data ) [ 1 ] ) // Remove Player ID
239
279
if ( version <= protocolMap [ '1.19.4' ] ) data = data . slice ( 4 ) // Remove Killer ID
240
280
const [ chatLen , chatViLength ] = readVarInt ( data )
241
- const deathMessage = parseValidJson (
242
- data . slice ( chatViLength , chatViLength + chatLen ) . toString ( 'utf8' )
243
- )
281
+ const chat = data . slice ( chatViLength , chatViLength + chatLen )
282
+ const deathMessage = parseChat ( chat , version )
244
283
if (
245
284
( typeof deathMessage === 'string' && deathMessage . trim ( ) ) ||
246
285
Object . keys ( deathMessage ) . length !== 0
0 commit comments