// Don't change this or you gay. // Version: 1.1 const lang = require("../util/en_us.json"); // translate message function uuidFromIntArray (arr) { const buf = Buffer.alloc(16) arr.forEach((num, index) => { buf.writeInt32BE(num, index * 4) }) return buf.toString('hex') } function simplify (data) { try { if (data === undefined) return data; function transform (value, type) { if (type === 'compound') { return Object.keys(value).reduce(function (acc, key) { acc[key] = simplify(value[key]) return acc }, {}) } if (type === 'list') { return value.value.map(function (v) { return transform(v, value.type) }) } return value } return transform(data.value, data.type) } catch (e) { return e; } } 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 (typeof color === 'string' && ansiColorCodes[color] && !color.startsWith('#')) { return ansiColorCodes[color]; } 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) { const red = parseInt(hexCodes[1], 16); const green = parseInt(hexCodes[2], 16); const blue = parseInt(hexCodes[3], 16); const ansiColor = `\u001b[38;2;${red};${green};${blue}m`; return ansiColor; } } else { return ''; } } function parseMinecraftFormat(format) { let result = ''; if (format.bold && format.bold === 1) result += ansiFormatCodes['bold']; if (format.italic && format.italic === 1) result += ansiFormatCodes['italic']; if (format.underlined && format.underlined === 1) result += ansiFormatCodes['underlined']; if (format.strikethrough && format.strikethrough === 1) result += ansiFormatCodes['strikethrough']; if (format.obfuscated && format.obfuscated === 1) result += ansiFormatCodes['obfuscated']; 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; 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; 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) { let translateString = lang[comp.translate] || comp.translate; let DefaultTranslateString = lang[comp.translate] || comp.translate; let DefaultMsg = false; let fallbackMsg = false; if (comp.fallback && !lang[comp.translate]) fallbackMsg = true; if (comp.with && !fallbackMsg) { 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 if (fallbackMsg) { text += formatfunction(comp, comp.fallback); } 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)); }); } return parseMinecraftColor(comp.color) + parseMinecraftFormat(comp) + text + ansiFormatCodes['reset']; } 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) { let translateString = lang[comp.translate] || comp.translate; let DefaultTranslateString = lang[comp.translate] || comp.translate; let DefaultMsg = false; let fallbackMsg = false; if (comp.fallback && !lang[comp.translate]) fallbackMsg = true; if (comp.with && !fallbackMsg) { 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 if (fallbackMsg) { text += comp.fallback; } 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 };