Skip to content

Commit

Permalink
Handle unsigned 1.19 chat, nested translations.
Browse files Browse the repository at this point in the history
  • Loading branch information
retrixe committed Aug 10, 2022
1 parent 1753531 commit 3c53937
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 26 deletions.
55 changes: 32 additions & 23 deletions src/minecraft/chatToJsx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export interface BaseChat {
obfuscated?: boolean
underlined?: boolean
strikethrough?: boolean
// TODO: This should be MinecraftChat, so translateChat should be
// called in flattenExtraComponents when the extra is translatable.
extra?: PlainTextChat[]
insertion?: string
clickEvent?: ClickEvent
Expand All @@ -68,8 +70,9 @@ export interface PlainTextChat extends BaseChat {
}

export interface TranslatedChat {
// TODO: This should extend BaseChat, so this should apply to child withs.
translate: string
with: string | PlainTextChat[]
with: MinecraftChat[]
}

export type MinecraftChat = PlainTextChat | TranslatedChat | string
Expand Down Expand Up @@ -167,6 +170,33 @@ const flattenExtraComponents = (chat: PlainTextChat): PlainTextChat[] => {
return [...arr, ...flattenedExtra]
}

const translateChat = (chat: TranslatedChat): PlainTextChat[] => {
if (!chat.with) chat.with = []
const translation = translations[chat.translate]
?.split('%s')
?.map((text, index) => {
let insert = chat.with[index] ? [chat.with[index]] : []
if (typeof insert[0] === 'string') insert = [{ text: insert[0] }]
else if (insert[0] && (insert[0] as TranslatedChat).translate) {
insert = translateChat(insert[0] as TranslatedChat)
}
return [{ text }, ...insert] as PlainTextChat[]
})
?.flat()
if (!translation) {
return [{ text: `[EnderChat] Unknown translation ${chat.translate}.` }]
} else return translation
}

const flattenTranslateComponents = (chat: MinecraftChat): PlainTextChat[] => {
if (typeof chat === 'string') return parseColorCodes(chat)
else if ((chat as TranslatedChat).translate) {
return translateChat(chat as TranslatedChat)
} else {
return flattenExtraComponents(chat as PlainTextChat)
}
}

const parseChatToJsx = (
chat: MinecraftChat,
Component: React.ComponentType<TextProps>,
Expand All @@ -175,28 +205,7 @@ const parseChatToJsx = (
componentProps?: {},
trim = false
) => {
if (chat && typeof chat !== 'string' && (chat as TranslatedChat).translate) {
const translatedChat = chat as TranslatedChat
if (!translatedChat.with) translatedChat.with = []
const translation = translations[translatedChat.translate]
?.split('%s')
?.map((text, index) => {
let insert = translatedChat.with[index]
if (typeof insert === 'string') insert = { text: insert }
return [{ text }, insert]
})
?.flat()
?.filter(component => !!component)
chat = {
extra: translation ?? [
{ text: `[EnderChat] Unknown translation ${translatedChat.translate}.` }
]
}
}
const flat =
typeof chat === 'string'
? parseColorCodes(chat)
: flattenExtraComponents(chat as PlainTextChat)
const flat = flattenTranslateComponents(chat)
return (
<Component {...componentProps}>
{flat.map((c, i) => {
Expand Down
3 changes: 1 addition & 2 deletions src/screens/ServerScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,7 @@ const ServerScreen = (props: Props) => {
if (version === -1) {
const ping = pingResponses[servers[server].address]
// Try the latest.
// TODO: Make 1.19 the default.
if (!ping) version = protocolMap['1.18.2']
if (!ping) version = protocolMap['1.19']
else if (typeof ping.version === 'object') {
version = ping.version.protocol
} else version = (ping as LegacyPing).protocol
Expand Down
46 changes: 45 additions & 1 deletion src/screens/chat/packetHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,50 @@ export const packetHandler =
packet.id === 0x30 /* Player Chat Message (clientbound) */ &&
is119
) {
// TODO-1.19: Support player chat messages.
try {
const [signedChatLen, signedChatViLen] = readVarInt(packet.data)
const signedChat = packet.data
.slice(signedChatViLen, signedChatViLen + signedChatLen)
.toString('utf8')
const totalSignedChatLen = signedChatViLen + signedChatLen
const hasUnsignedChat = packet.data.readInt8(totalSignedChatLen)
const moreData = packet.data.slice(totalSignedChatLen + 1)
if (hasUnsignedChat) {
const [unsignedChatLen, unsignedChatViLen] = readVarInt(moreData)
const unsignedChat = moreData
.slice(unsignedChatViLen, unsignedChatViLen + unsignedChatLen)
.toString('utf8')
const totalUnsignedChatLen = unsignedChatViLen + unsignedChatLen
const position = moreData.readInt8(totalUnsignedChatLen)
const [displayNameLen, displayNameViLen] = readVarInt(moreData, 17)
const nameViLenOffset = 17 + displayNameViLen
const displayName = moreData
.slice(nameViLenOffset, nameViLenOffset + displayNameLen)
.toString('utf8')
if (position === 0 || position === 1) {
addMessage({
translate: 'chat.type.text',
with: [parseValidJson(displayName), parseValidJson(unsignedChat)]
})
}
} else {
const position = moreData.readInt8()
const [displayNameLen, displayNameViLen] = readVarInt(moreData, 17)
const nameViLenOffset = 17 + displayNameViLen
const displayName = moreData
.slice(nameViLenOffset, nameViLenOffset + displayNameLen)
.toString('utf8')
if (position === 0 || position === 1) {
addMessage({
translate: 'chat.type.text',
with: [parseValidJson(displayName), parseValidJson(signedChat)]
})
}
}
// TODO-1.19: Support sender team name
} catch (e) {
handleError(addMessage, parseMessageError)(e)
}
} else if (
packet.id === 0x5f /* System Chat Message (clientbound) */ &&
is119
Expand All @@ -81,6 +124,7 @@ export const packetHandler =
.toString('utf8')
const position = packet.data.readInt8(chatVarIntLength + chatLength)
// TODO-1.19 - 3: say command, 4: msg command, 5: team msg command, 6: emote command, 7: tellraw command
// Also in Player Chat Message.
if (position === 0 || position === 1) {
addMessage(parseValidJson(chatJson))
}
Expand Down

0 comments on commit 3c53937

Please sign in to comment.