diff --git a/main/chatparser.js b/main/chatparser.js index 364c8ae..6e9589c 100644 --- a/main/chatparser.js +++ b/main/chatparser.js @@ -27,355 +27,15 @@ function simplify (data) { } } -function processNbtMessage (msg) { - try { - if (!msg || msg.type === 'end') return null; - if (typeof msg === 'string') return msg - - const simplified = simplify(msg); // Ensure nbt is defined elsewhere - const json = JSON.stringify(simplified, (key, val) => { - if (key === 'id' && Array.isArray(val)) return uuidFromIntArray(val); - return val; - }); - - return json; - } catch (e) { - return e; - } -} - -function inject(bot) { - -let playerchat = {}; // im think this can fix memory leak. -let systemchat = {}; -let profilelesschat = {}; -let actionbar = {}; - - -bot.on('action_bar', (packet) => { - actionbar = {}; - actionbar.message = parseMinecraftMessage(simplify(packet.text)); - actionbar.nocolor_message = parseMinecraftMessageNoColor(simplify(packet.text)) - bot.emit('custom_actionbar', actionbar.message, actionbar, packet); - bot.emit('custom_allchat', 'actionbar', actionbar.message, actionbar, packet); -}); - -bot.on('system_chat', (packet) => { // system - if (packet.isActionBar) return; - - systemchat = {}; - systemchat.jsonMsg = simplify(packet.content); - systemchat.message = parseMinecraftMessage(simplify(packet.content)); - systemchat.nocolor_message = parseMinecraftMessageNoColor(simplify(packet.content)); - - bot.emit('custom_systemchat', systemchat.message, systemchat, packet); - bot.emit('custom_allchat', 'system', systemchat.message, systemchat, packet); - -}); - - -bot.on('profileless_chat', (packet) => { // kinda player_chat - - profilelesschat = {}; - - profilelesschat.type = packet.type - - profilelesschat.formattedMessage = simplify(packet.message); - profilelesschat.senderName = simplify(packet.name); - profilelesschat.targetName = simplify(packet.target); - - switch (profilelesschat.type) { - case 1: // /me - profilelesschat.message = parseMinecraftMessage({ "translate": "chat.type.emote", "with": [ profilelesschat.senderName, profilelesschat.formattedMessage ]}); - profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ "translate": "chat.type.emote", "with": [ profilelesschat.senderName, profilelesschat.formattedMessage ]}); - break; - case 2: // player /tell - profilelesschat.message = parseMinecraftMessage({ translate: "commands.message.display.incoming", with: [ profilelesschat.senderName, profilelesschat.formattedMessage ], color: "gray", italic: true }); - profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ translate: "commands.message.display.incoming", with: [ profilelesschat.senderName, profilelesschat.formattedMessage ], color: "gray", italic: true }); - break; - case 3: // you /tell - profilelesschat.message = parseMinecraftMessage({ translate: "commands.message.display.outgoing", with: [ profilelesschat.targetName, profilelesschat.formattedMessage ], color: "gray", italic: true }); - profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ translate: "commands.message.display.outgoing", with: [ profilelesschat.targetName, profilelesschat.formattedMessage ], color: "gray", italic: true }); - break; - case 4: // player chat - profilelesschat.message = parseMinecraftMessage(profilelesschat.formattedMessage); - profilelesschat.nocolor_msg = parseMinecraftMessageNoColor(profilelesschat.formattedMessage); - break; - case 5: // - profilelesschat.message = parseMinecraftMessage({ translate: 'chat.type.announcement', with: [ profilelesschat.senderName, profilelesschat.formattedMessage ]}); - profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ translate: 'chat.type.announcement', with: [ profilelesschat.senderName, profilelesschat.formattedMessage ]}); - break; - case 6: // player /teammsg - profilelesschat.message = parseMinecraftMessage({ translate: 'chat.type.team.text', with: [ profilelesschat.targetName, profilelesschat.senderName, profilelesschat.formattedMessage ]}); - profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ translate: 'chat.type.team.text', with: [ profilelesschat.targetName, profilelesschat.senderName, profilelesschat.formattedMessage ]}); - break; - case 7: // you /teammsg - profilelesschat.message = parseMinecraftMessage({ translate: 'chat.type.team.sent', with: [ profilelesschat.targetName, profilelesschat.senderName, profilelesschat.formattedMessage ]}); - profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ translate: 'chat.type.team.sent', with: [ profilelesschat.targetName, profilelesschat.senderName, profilelesschat.formattedMessage ]}); - break; - default: - console.log(`Unknown player_chat packet. Type: ${playerchat.type}`); - console.log(packet); - break; - } - - bot.emit('custom_profilelesschat', profilelesschat.message, profilelesschat, packet) - bot.emit('custom_allchat', 'profileless', profilelesschat.message, profilelesschat, packet) -}) - - -bot.on('player_chat', (packet) => { // player - playerchat = {}; - - playerchat.plainMessage = packet.plainMessage; - playerchat.type = packet.type; - playerchat.sender = packet.senderUuid; - - playerchat.unsignedContent = simplify(packet.unsignedChatContent); - playerchat.senderName = simplify(packet.networkName); - playerchat.targetName = simplify(packet.networkTargetName); - - playerchat.nocolor_senderName = parseMinecraftMessageNoColor(simplify(packet.networkName)); - playerchat.nocolor_targetName = parseMinecraftMessageNoColor(simplify(packet.networkTargetName)); - - switch (playerchat.type) { // vanish off - case 1: // /minecraft:me - playerchat.message = parseMinecraftMessage({ "translate": "chat.type.emote", "with": [ playerchat.senderName, playerchat.plainMessage ]}); - playerchat.nocolor_msg = parseMinecraftMessageNoColor({ "translate": "chat.type.emote", "with": [ playerchat.senderName, playerchat.plainMessage ]}); - break; - case 2: // player /minecraft:tell - playerchat.message = parseMinecraftMessage({ translate: "commands.message.display.incoming", with: [ playerchat.senderName, playerchat.plainMessage ], color: "gray", italic: true }); - playerchat.nocolor_msg = parseMinecraftMessageNoColor({ translate: "commands.message.display.incoming", with: [ playerchat.senderName, playerchat.plainMessage ], color: "gray", italic: true }); - break; - case 3: // you /minecraft:tell - playerchat.message = parseMinecraftMessage({ translate: "commands.message.display.outgoing", with: [ playerchat.targetName, playerchat.plainMessage ], color: "gray", italic: true }); - playerchat.nocolor_msg = parseMinecraftMessageNoColor({ translate: "commands.message.display.outgoing", with: [ playerchat.targetName, playerchat.plainMessage ], color: "gray", italic: true }); - break; - case 4: // player chat - playerchat.message = parseMinecraftMessage(playerchat.unsignedContent); - playerchat.nocolor_msg = parseMinecraftMessageNoColor(playerchat.unsignedContent); - break; - case 5: // - playerchat.message = parseMinecraftMessage({ translate: 'chat.type.announcement', with: [ playerchat.senderName, playerchat.plainMessage ]}); - playerchat.nocolor_msg = parseMinecraftMessageNoColor({ translate: 'chat.type.announcement', with: [ playerchat.senderName, playerchat.plainMessage ]}); - break; - case 6: // player /minecraft:teammsg || /teammsg - playerchat.message = parseMinecraftMessage({ translate: 'chat.type.team.text', with: [ playerchat.targetName, playerchat.senderName, playerchat.plainMessage ]}); - playerchat.nocolor_msg = parseMinecraftMessageNoColor({ translate: 'chat.type.team.text', with: [ playerchat.targetName, playerchat.senderName, playerchat.plainMessage ]}); - break; - case 7: // you /minecraft:teammsg || /teammsg - playerchat.message = parseMinecraftMessage({ translate: 'chat.type.team.sent', with: [ playerchat.targetName, playerchat.senderName, playerchat.plainMessage ]}); - playerchat.message = parseMinecraftMessageNoColor({ translate: 'chat.type.team.sent', with: [ playerchat.targetName, playerchat.senderName, playerchat.plainMessage ]}); - break; - default: - console.log(`Unknown player_chat packet. Type: ${playerchat.type}`); - console.log(packet); - break; - } - bot.emit('custom_playerchat', playerchat.message, playerchat, packet); - bot.emit('custom_allchat', 'player', playerchat.message, playerchat, packet) -}); - -} - -const ansiColorCodes = { - '§0': '\x1B[30m', '§1': '\x1B[34m', '§2': '\x1B[32m', '§3': '\x1B[36m', - '§4': '\x1B[31m', '§5': '\x1B[35m', '§6': '\x1B[33m', '§7': '\x1B[37m', - '§8': '\x1B[90m', '§9': '\x1B[94m', '§a': '\x1B[92m', '§b': '\x1B[96m', - '§c': '\x1B[91m', '§d': '\x1B[95m', '§e': '\x1B[93m', '§f': '\x1B[97m', - 'black': '\x1B[30m', 'dark_blue': '\x1B[34m', 'dark_green': '\x1B[32m', - 'dark_aqua': '\x1B[36m', 'dark_red': '\x1B[31m', 'dark_purple': '\x1B[35m', - 'gold': '\x1B[33m', 'gray': '\x1B[37m', 'dark_gray': '\x1B[90m', 'blue': '\x1B[94m', - 'green': '\x1B[92m', 'aqua': '\x1B[96m', 'red': '\x1B[91m', 'light_purple': '\x1B[95m', - 'yellow': '\x1B[93m', 'white': '\x1B[97m' -}; - -const ansiFormatCodes = { - '§l': '\x1B[1m', '§o': '\x1B[3m', '§n': '\x1B[4m', '§m': '\x1B[9m', '§k': '\x1B[5m', '§r': '\x1B[0m', - 'bold': '\x1B[1m', 'italic': '\x1B[3m', 'underlined': '\x1B[4m', 'strikethrough': '\x1B[9m', 'obfuscated': '\x1B[5m', 'reset': '\x1B[0m', -}; - -function parseMinecraftMessage(component) { - if (component === undefined) return; - - function extractText(comp) { - let text = ''; - if (comp.text && typeof comp.text === 'string' || typeof comp.text === 'number') { - text += comp.text; - } - if (comp[""] && typeof comp[""] === 'string' || typeof comp[""] === 'number') { - text += comp[""]; - } - if (comp && typeof comp === 'string' || typeof comp === 'number') { - return comp; - } - - if (comp.extra) { - if (!Array.isArray(comp.extra)) comp.extra = [comp.extra] - comp.extra.forEach(subComp => { - text += formatfunction(comp, extractText(subComp)); - }); - } - - if (comp.translate) { - let translateString = lang[comp.translate] || comp.translate; - let DefaultTranslateString = lang[comp.translate] || comp.translate; - let DefaultMsg = false; - - if (comp.with) { - const withArgs = comp.with.map(arg => extractText(arg)); - let usedReplacements = 0; - translateString = translateString.replace(/thing__placeholder__/g, 'default_thing__placeholder__'); - - translateString = translateString.replace(/%s/g, (match, offset, string) => { - if (offset > 0 && string[offset - 1] === '%') { - return 's'; - } - - if (usedReplacements < withArgs.length) { - if (translateString.length + formatfunction(comp, withArgs[usedReplacements]).length > 2048) return 'Translate Crash'; // Prevent translate crash - return `thing__placeholder__${usedReplacements++}`; - } - - DefaultMsg = true; - return "%s"; - }); - - translateString = translateString.replace(/%(-?\d+)\$s/g, (match, index, stringindex, string) => { - const argIndex = parseInt(index, 10) - 1; - - if (argIndex < 0 || argIndex >= withArgs.length) { - DefaultMsg = true; - return match; - } - - if (stringindex > 0 && string[stringindex - 1] === '%') { - return match; - } - if (translateString.length + formatfunction(comp, withArgs[argIndex]).length > 2048) return 'Translate Crash'; // Prevent translate crash - return `thing__placeholder__${argIndex}`; - }); - - for (let i = 0; i < withArgs.length; i++) { - if (translateString.length + formatfunction(comp, withArgs[i]).length > 2048) return 'Translate Crash'; // Prevent translate crash - translateString = translateString.replace(new RegExp(`thing__placeholder__${i}`, 'g'), (match) => { - const formattedArg = formatfunction(comp, withArgs[i]); - return formattedArg; - }); - } - translateString = translateString.replace(/default_thing__placeholder__/g, 'thing__placeholder__'); - } - - if (DefaultMsg) { - text += formatfunction(comp, DefaultTranslateString); - } else { - text += formatfunction(comp, translateString); - } - } - - text = parseMinecraftColor(comp.color) + parseMinecraftFormat(comp) + text + ansiFormatCodes['reset']; - return text; - } - - return extractText(component) + ansiFormatCodes['reset']; -} - - -function parseMinecraftMessageNoColor(component) { - if (component === undefined) return; - - function extractText(comp) { - let text = ''; - - if (comp.text && typeof comp.text === 'string' || typeof comp.text === 'number') { - text += comp.text; - } - if (comp[""] && typeof comp[""] === 'string' || typeof comp[""] === 'number') { - text += comp[""]; - } - if (comp && typeof comp === 'string' || typeof comp === 'number') { - return comp; - } - - if (comp.extra) { - if (!Array.isArray(comp.extra)) comp.extra = [comp.extra] - comp.extra.forEach(subComp => { - text += extractText(subComp); - }); - } - - if (comp.translate) { - let translateString = lang[comp.translate] || comp.translate; - let DefaultTranslateString = lang[comp.translate] || comp.translate; - let DefaultMsg = false; - - if (comp.with) { - const withArgs = comp.with.map(arg => extractText(arg)); - let usedReplacements = 0; - - translateString = translateString.replace(/thing__placeholder__/g, 'default_thing__placeholder__'); - translateString = translateString.replace(/%s/g, (match, offset, string) => { - if (offset > 0 && string[offset - 1] === '%') { - return 's'; - } - - if (usedReplacements < withArgs.length) { - if (translateString.length + withArgs[usedReplacements].length > 2048) return 'Translate Crash'; // Prevent translate crash - return `thing__placeholder__${usedReplacements++}`; - } - - DefaultMsg = true; - return "%s"; - }); - - translateString = translateString.replace(/%(-?\d+)\$s/g, (match, index, stringindex, string) => { - const argIndex = parseInt(index, 10) - 1; - - if (argIndex < 0 || argIndex >= withArgs.length) { - DefaultMsg = true; - return match; - } - - if (stringindex > 0 && string[stringindex - 1] === '%') { - return match; - } - - if (translateString.length + withArgs[argIndex].length > 2048) return 'Translate Crash'; // Prevent translate crash - return `thing__placeholder__${argIndex}`; - }); - - for (let i = 0; i < withArgs.length; i++) { - if (translateString.length + withArgs[i].length > 2048) return 'Translate Crash'; // Prevent translate crash - translateString = translateString.replace(new RegExp(`thing__placeholder__${i}`, 'g'), (match) => { - const formattedArg = withArgs[i]; - return formattedArg; - }); - } - translateString = translateString.replace(/default_thing__placeholder__/g, 'thing__placeholder__'); - } - - if (DefaultMsg) { - text += DefaultTranslateString; - } else { - text += translateString; - } - } - - return text; - } - - return extractText(component); -} - function formatfunction(comp, text) { if (text === undefined) return ''; return text = parseMinecraftColor(comp.color) + parseMinecraftFormat(comp) + text + parseMinecraftColor(comp.color) + parseMinecraftFormat(comp); } function parseMinecraftColor(color) { - if (color && ansiColorCodes[color] && !color.startsWith('#')) { + if (typeof color === 'string' && ansiColorCodes[color] && !color.startsWith('#')) { return ansiColorCodes[color]; - } else if (color && color.startsWith('#')) { + } else if (typeof color === 'string' && color.startsWith('#')) { const hexRegex = /#?([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})/; const hexCodes = hexRegex.exec(color); if (hexCodes) { @@ -400,4 +60,383 @@ function parseMinecraftFormat(format) { return result; } +function inject(bot) { + +let playerchat = {}; +let systemchat = {}; +let profilelesschat = {}; +let actionbar = {}; +let bossbar = {}; + +bot.on('end', () => { // ok keep this + playerchat = {}; delete playerchat; + systemchat = {}; delete systemchat; + profilelesschat = {}; delete profilelesschat; + actionbar = {}; delete actionbar; + bossbar = {}; delete bossbar; +}) + +bot.on('boss_bar', (packet) => { + + bossbar = {}; + bossbar.uuid = packet.entityUUID; + bossbar.action = packet.action; + + switch (bossbar.action) { + case 1: // bossbar remove || bossbar visible false || bossbar player !botName + break; + case 0: // bossbar visible true || bossbar player botName + bossbar.title = parseMinecraftMessage(simplify(packet.title)); + bossbar.nocolor_title = parseMinecraftMessageNoColor(simplify(packet.title)); + bossbar.health = packet.health; + bossbar.color = packet.color; + bossbar.dividers = packet.dividers; + bossbar.flags = packet.flags; + break; + + case 2: // bossbar set max || bossbar set value, 1 mean full + bossbar.health = packet.health; + break; + + case 3: // bossbar set name + bossbar.title = parseMinecraftMessage(simplify(packet.title)); + bossbar.nocolor_title = parseMinecraftMessageNoColor(simplify(packet.title)); + break; + + case 4: + bossbar.color = packet.color; // bossbar set color + bossbar.dividers = packet.dividers; // bossbar set style + break; + + case 5: // wither, ender dragon etc... , chayapak found it + bossbar.flags = packet.flags; + break; + + default: + console.log(packet); + break; + } + + bot.emit('custom_bossbar', bossbar.title, bossbar, packet); + bot.emit('custom_allchat', 'bossbar', bossbar.title, bossbar, packet); +}); + +bot.on('action_bar', (packet) => { + actionbar = {}; + actionbar.message = parseMinecraftMessage(simplify(packet.text)); + actionbar.nocolor_message = parseMinecraftMessageNoColor(simplify(packet.text)) + bot.emit('custom_actionbar', actionbar.message, actionbar, packet); + bot.emit('custom_allchat', 'actionbar', actionbar.message, actionbar, packet); +}); + + +bot.on('system_chat', (packet) => { // system + if (packet.isActionBar) return; // useless i guess + systemchat = {}; + systemchat.jsonMsg = simplify(packet.content); + systemchat.message = parseMinecraftMessage(simplify(packet.content)); + systemchat.nocolor_message = parseMinecraftMessageNoColor(simplify(packet.content)); + + bot.emit('custom_systemchat', systemchat.message, systemchat, packet); + bot.emit('custom_allchat', 'systemchat', systemchat.message, systemchat, packet); + +}); + + +bot.on('profileless_chat', (packet) => { // kinda player_chat + + profilelesschat = {}; + + profilelesschat.type = packet.type.registryIndex; + + profilelesschat.formattedMessage = simplify(packet.message); + profilelesschat.senderName = simplify(packet.name); + profilelesschat.targetName = simplify(packet.target); + + switch (profilelesschat.type) { + case 1: // /me + profilelesschat.message = parseMinecraftMessage({ "translate": "chat.type.emote", "with": [ profilelesschat.senderName, profilelesschat.formattedMessage ]}); + profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ "translate": "chat.type.emote", "with": [ profilelesschat.senderName, profilelesschat.formattedMessage ]}); + break; + case 2: // player /tell + profilelesschat.message = parseMinecraftMessage({ translate: "commands.message.display.incoming", with: [ profilelesschat.senderName, profilelesschat.formattedMessage ], color: "gray", italic: true }); + profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ translate: "commands.message.display.incoming", with: [ profilelesschat.senderName, profilelesschat.formattedMessage ], color: "gray", italic: true }); + break; + case 3: // you /tell + profilelesschat.message = parseMinecraftMessage({ translate: "commands.message.display.outgoing", with: [ profilelesschat.targetName, profilelesschat.formattedMessage ], color: "gray", italic: true }); + profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ translate: "commands.message.display.outgoing", with: [ profilelesschat.targetName, profilelesschat.formattedMessage ], color: "gray", italic: true }); + break; + case 4: // player chat + profilelesschat.message = parseMinecraftMessage(profilelesschat.formattedMessage); + profilelesschat.nocolor_msg = parseMinecraftMessageNoColor(profilelesschat.formattedMessage); + break; + case 5: // /say + profilelesschat.message = parseMinecraftMessage({ translate: 'chat.type.announcement', with: [ profilelesschat.senderName, profilelesschat.formattedMessage ]}); + profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ translate: 'chat.type.announcement', with: [ profilelesschat.senderName, profilelesschat.formattedMessage ]}); + break; + case 6: // player /teammsg + profilelesschat.message = parseMinecraftMessage({ translate: 'chat.type.team.text', with: [ profilelesschat.targetName, profilelesschat.senderName, profilelesschat.formattedMessage ]}); + profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ translate: 'chat.type.team.text', with: [ profilelesschat.targetName, profilelesschat.senderName, profilelesschat.formattedMessage ]}); + break; + case 7: // you /teammsg + profilelesschat.message = parseMinecraftMessage({ translate: 'chat.type.team.sent', with: [ profilelesschat.targetName, profilelesschat.senderName, profilelesschat.formattedMessage ]}); + profilelesschat.nocolor_msg = parseMinecraftMessageNoColor({ translate: 'chat.type.team.sent', with: [ profilelesschat.targetName, profilelesschat.senderName, profilelesschat.formattedMessage ]}); + break; + default: + console.log(`Unknown profilelesschat packet. Type: ${playerchat.type}`); + console.log(packet); + break; + } + + bot.emit('custom_profilelesschat', profilelesschat.message, profilelesschat, packet) + bot.emit('custom_allchat', 'profilelesschat', profilelesschat.message, profilelesschat, packet) +}) + + +bot.on('player_chat', (packet) => { // player + playerchat = {}; + + playerchat.plainMessage = packet.plainMessage; + playerchat.type = packet.type.registryIndex; + playerchat.sender = packet.senderUuid; + + playerchat.unsignedContent = simplify(packet.unsignedChatContent); + playerchat.senderName = simplify(packet.networkName); + playerchat.targetName = simplify(packet.networkTargetName); + + playerchat.nocolor_unsignedContent = parseMinecraftMessageNoColor(simplify(packet.unsignedChatContent)); + playerchat.nocolor_senderName = parseMinecraftMessageNoColor(simplify(packet.networkName)); + playerchat.nocolor_targetName = parseMinecraftMessageNoColor(simplify(packet.networkTargetName)); + switch (playerchat.type) { // vanish off + case 1: // /minecraft:me + playerchat.message = parseMinecraftMessage({ "translate": "chat.type.emote", "with": [ playerchat.senderName, playerchat.plainMessage ]}); + playerchat.nocolor_msg = parseMinecraftMessageNoColor({ "translate": "chat.type.emote", "with": [ playerchat.senderName, playerchat.plainMessage ]}); + break; + case 2: // player /minecraft:tell + playerchat.message = parseMinecraftMessage({ translate: "commands.message.display.incoming", with: [ playerchat.senderName, playerchat.plainMessage ], color: "gray", italic: true }); + playerchat.nocolor_msg = parseMinecraftMessageNoColor({ translate: "commands.message.display.incoming", with: [ playerchat.senderName, playerchat.plainMessage ], color: "gray", italic: true }); + break; + case 3: // you /minecraft:tell + playerchat.message = parseMinecraftMessage({ translate: "commands.message.display.outgoing", with: [ playerchat.targetName, playerchat.plainMessage ], color: "gray", italic: true }); + playerchat.nocolor_msg = parseMinecraftMessageNoColor({ translate: "commands.message.display.outgoing", with: [ playerchat.targetName, playerchat.plainMessage ], color: "gray", italic: true }); + break; + case 4: // player chat + playerchat.message = parseMinecraftMessage(playerchat.unsignedContent); + playerchat.nocolor_msg = parseMinecraftMessageNoColor(playerchat.unsignedContent); + break; + case 5: // /say + playerchat.message = parseMinecraftMessage({ translate: 'chat.type.announcement', with: [ playerchat.senderName, playerchat.plainMessage ]}); + playerchat.nocolor_msg = parseMinecraftMessageNoColor({ translate: 'chat.type.announcement', with: [ playerchat.senderName, playerchat.plainMessage ]}); + break; + case 6: // player /minecraft:teammsg || /teammsg + playerchat.message = parseMinecraftMessage({ translate: 'chat.type.team.text', with: [ playerchat.targetName, playerchat.senderName, playerchat.plainMessage ]}); + playerchat.nocolor_msg = parseMinecraftMessageNoColor({ translate: 'chat.type.team.text', with: [ playerchat.targetName, playerchat.senderName, playerchat.plainMessage ]}); + break; + case 7: // you /minecraft:teammsg || /teammsg + playerchat.message = parseMinecraftMessage({ translate: 'chat.type.team.sent', with: [ playerchat.targetName, playerchat.senderName, playerchat.plainMessage ]}); + playerchat.message = parseMinecraftMessageNoColor({ translate: 'chat.type.team.sent', with: [ playerchat.targetName, playerchat.senderName, playerchat.plainMessage ]}); + break; + default: + console.log(`Unknown player_chat packet. Type: ${playerchat.type}`); + console.log(packet); + break; + } + bot.emit('custom_playerchat', playerchat.message, playerchat, packet); + bot.emit('custom_allchat', 'playerchat', playerchat.message, playerchat, packet) +}); + +} + +const ansiColorCodes = { + '§0': '\x1B[30m', '§1': '\x1B[34m', '§2': '\x1B[32m', '§3': '\x1B[36m', + '§4': '\x1B[31m', '§5': '\x1B[35m', '§6': '\x1B[33m', '§7': '\x1B[37m', + '§8': '\x1B[90m', '§9': '\x1B[94m', '§a': '\x1B[92m', '§b': '\x1B[96m', + '§c': '\x1B[91m', '§d': '\x1B[95m', '§e': '\x1B[93m', '§f': '\x1B[97m', + 'black': '\x1B[30m', 'dark_blue': '\x1B[34m', 'dark_green': '\x1B[32m', + 'dark_aqua': '\x1B[36m', 'dark_red': '\x1B[31m', 'dark_purple': '\x1B[35m', + 'gold': '\x1B[33m', 'gray': '\x1B[37m', 'dark_gray': '\x1B[90m', 'blue': '\x1B[94m', + 'green': '\x1B[92m', 'aqua': '\x1B[96m', 'red': '\x1B[91m', 'light_purple': '\x1B[95m', + 'yellow': '\x1B[93m', 'white': '\x1B[97m' +}; + +const ansiFormatCodes = { + '§l': '\x1B[1m', '§o': '\x1B[3m', '§n': '\x1B[4m', '§m': '\x1B[9m', '§k': '\x1B[5m', '§r': '\x1B[0m', + 'bold': '\x1B[1m', 'italic': '\x1B[3m', 'underlined': '\x1B[4m', 'strikethrough': '\x1B[9m', 'obfuscated': '\x1B[5m', 'reset': '\x1B[0m', +}; + +function parseMinecraftMessage(component) { + if (component === undefined) return; + + function extractText(comp) { + let text = ''; + if (comp.text && typeof comp.text === 'string' || typeof comp.text === 'number') { + text += comp.text; + } + if (comp[""] && typeof comp[""] === 'string' || typeof comp[""] === 'number') { + text += comp[""]; + } + if (comp && typeof comp === 'string' || typeof comp === 'number') { + return comp; + } + + if (comp.translate) { + if (comp.fallback && !lang[comp.translate]) return text += formatfunction(comp, comp.fallback); + let translateString = lang[comp.translate] || comp.translate; + let DefaultTranslateString = lang[comp.translate] || comp.translate; + let DefaultMsg = false; + + if (comp.with) { + const withArgs = comp.with.map(arg => extractText(arg)); + let usedReplacements = 0; + translateString = translateString.replace(/thing__placeholder__/g, 'default_thing__placeholder__'); + + translateString = translateString.replace(/%s/g, (match, offset, string) => { + if (offset > 0 && string[offset - 1] === '%') { + return 's'; + } + + if (usedReplacements < withArgs.length) { + if (translateString.length + formatfunction(comp, withArgs[usedReplacements]).length > 16384) return 'Translate Crash'; // Prevent translate crash + return `thing__placeholder__${usedReplacements++}`; + } + + DefaultMsg = true; + return "%s"; + }); + + translateString = translateString.replace(/%(-?\d+)\$s/g, (match, index, stringindex, string) => { + const argIndex = parseInt(index, 10) - 1; + + if (argIndex < 0 || argIndex >= withArgs.length) { + DefaultMsg = true; + return match; + } + + if (stringindex > 0 && string[stringindex - 1] === '%') { + return match; + } + if (translateString.length + formatfunction(comp, withArgs[argIndex]).length > 16384) return 'Translate Crash'; // Prevent translate crash + return `thing__placeholder__${argIndex}`; + }); + + for (let i = 0; i < withArgs.length; i++) { + if (translateString.length + formatfunction(comp, withArgs[i]).length > 16384) return 'Translate Crash'; // Prevent translate crash + translateString = translateString.replace(new RegExp(`thing__placeholder__${i}`, 'g'), (match) => { + const formattedArg = formatfunction(comp, withArgs[i]); + return formattedArg; + }); + } + translateString = translateString.replace(/default_thing__placeholder__/g, 'thing__placeholder__'); + } + + if (DefaultMsg) { + text += formatfunction(comp, DefaultTranslateString); + } else { + text += formatfunction(comp, translateString); + } + } + + if (comp.extra) { + if (!Array.isArray(comp.extra)) comp.extra = [comp.extra] + comp.extra.forEach(subComp => { + text += formatfunction(comp, extractText(subComp)); + }); + } + + text = parseMinecraftColor(comp.color) + parseMinecraftFormat(comp) + text + ansiFormatCodes['reset']; + + return text; + } + + return extractText(component) + ansiFormatCodes['reset']; +} + + +function parseMinecraftMessageNoColor(component) { + if (component === undefined) return; + + function extractText(comp) { + let text = ''; + + if (comp.text && typeof comp.text === 'string' || typeof comp.text === 'number') { + text += comp.text; + } + if (comp[""] && typeof comp[""] === 'string' || typeof comp[""] === 'number') { + text += comp[""]; + } + if (comp && typeof comp === 'string' || typeof comp === 'number') { + return comp; + } + + if (comp.translate) { + if (comp.fallback && !lang[comp.translate]) return text += comp.fallback; + let translateString = lang[comp.translate] || comp.translate; + let DefaultTranslateString = lang[comp.translate] || comp.translate; + let DefaultMsg = false; + + if (comp.with) { + const withArgs = comp.with.map(arg => extractText(arg)); + let usedReplacements = 0; + + translateString = translateString.replace(/thing__placeholder__/g, 'default_thing__placeholder__'); + translateString = translateString.replace(/%s/g, (match, offset, string) => { + if (offset > 0 && string[offset - 1] === '%') { + return 's'; + } + + if (usedReplacements < withArgs.length) { + if (translateString.length + withArgs[usedReplacements].length > 16384) return 'Translate Crash'; // Prevent translate crash + return `thing__placeholder__${usedReplacements++}`; + } + + DefaultMsg = true; + return "%s"; + }); + + translateString = translateString.replace(/%(-?\d+)\$s/g, (match, index, stringindex, string) => { + const argIndex = parseInt(index, 10) - 1; + + if (argIndex < 0 || argIndex >= withArgs.length) { + DefaultMsg = true; + return match; + } + + if (stringindex > 0 && string[stringindex - 1] === '%') { + return match; + } + + if (translateString.length + withArgs[argIndex].length > 16384) return 'Translate Crash'; // Prevent translate crash + return `thing__placeholder__${argIndex}`; + }); + + for (let i = 0; i < withArgs.length; i++) { + if (translateString.length + withArgs[i].length > 16384) return 'Translate Crash'; // Prevent translate crash + translateString = translateString.replace(new RegExp(`thing__placeholder__${i}`, 'g'), (match) => { + const formattedArg = withArgs[i]; + return formattedArg; + }); + } + translateString = translateString.replace(/default_thing__placeholder__/g, 'thing__placeholder__'); + } + + if (DefaultMsg) { + text += DefaultTranslateString; + } else { + text += translateString; + } + } + + if (comp.extra) { + if (!Array.isArray(comp.extra)) comp.extra = [comp.extra] + comp.extra.forEach(subComp => { + text += extractText(subComp); + }); + } + + return text; + } + + return extractText(component); +} + module.exports = { inject }; \ No newline at end of file