iron-golem
Version:
A robust Minecraft bot built upon mineflayer
163 lines (131 loc) • 4.84 kB
JavaScript
const stripAnsi = require('strip-ansi');
const { Vec3 } = require('vec3');
const ConsoleColor = require('../enum/ConsoleColor');
const SPACE_REGEX = /^\s+$/;
class MinecraftUtil {
/**
* Turn a packet (JSON message) into text.
* @param {object} packet - The packet to turn into text.
* @param {boolean} [stripSpaces = true] - Whether 2+ spaces should be turned into 1
* @return {string}
*/
static packetToText(packet, stripSpaces = true) {
const packetText = packet.toString();
return (stripSpaces) ? packetText.replace(/\s+/, ' ') : packetText;
}
/**
* Strip the text of all minecraft color codes and chalk (ANSI) colors.
* @param text
* @return {string}
*/
static stripColor(text) {
return stripAnsi(text.replace(/\u00A7[0-9A-FK-OR]/ig, ''));
}
static _applyColor(str, code) {
return (ConsoleColor.Chat.get(code))(str);
}
/**
* Turn a minecraft color code string into console-colored text.
* @param {string} text - The text to console-ify
* @return {string}
*/
static textToChalk(text) {
let chalkMessage = '';
const bits = text.split('§');
if (bits.length === 1) {
return text;
}
let bit;
for (let i = 0; i < bits.length; i++) {
bit = bits[i];
if (bit.length === 0) {
continue;
}
if (SPACE_REGEX.test(bit)) {
chalkMessage += bit;
continue;
}
if (bit.length === 1) {
// We don't care about single resets since something else is related to it
if (bit === 'r') {
continue;
}
const relatedBits = [bit];
for (++i; i < bits.length; i++) {
bit = bits[i];
relatedBits.push(bit[0]);
if (bit.length !== 1) {
bit = relatedBits.reduce(MinecraftUtil._applyColor, bit.slice(1));
break;
}
}
if (bit.length === 1) {
continue;
}
} else {
const colorCode = bit[0];
bit = MinecraftUtil._applyColor(bit.slice(1), colorCode);
}
chalkMessage += bit;
}
return chalkMessage;
}
/**
* Turn a minecraft JSON packet into console-colored text.
* @param {string|object|Array} item - An item to convert. This mainly is multi-type for recursion.
* @return {string}
*/
static jsonToChalk(item) {
let chalkMessage = '';
if (typeof item === 'string') {
return item;
} else if (typeof item === 'object') {
if (Array.isArray(item)) {
// We're looking at an array of 'extra' items.
for (const element of item) {
chalkMessage += MinecraftUtil.jsonToChalk(element);
}
} else {
// We're looking at a specific extra item.
const { color, text, extra } = item;
if (color) {
chalkMessage += (ConsoleColor.Minecraft.get(color.toUpperCase()))(text);
} else {
chalkMessage += text;
}
if (extra) {
chalkMessage += MinecraftUtil.jsonToChalk(extra);
}
}
}
return MinecraftUtil.textToChalk(chalkMessage);
}
/**
* Turn a Minecraft packet into console-colored text.
* @param {object} packet - The packet (JSON message) to convert.
* @return {string}
*/
static packetToChalk(packet) {
if (packet.toAnsi) {
return packet.toAnsi();
}
const text = MinecraftUtil.packetToText(packet);
// Assume the whole message is colored only with section signs
// If this is an issue in the future, I'll fix it
if (text.includes('§')) {
return MinecraftUtil.textToChalk(text);
} else {
// Yay, it's a JSON message... Just what I wanted.
// This completely ignores most vanilla server messages,
// most prominently achievements.
return MinecraftUtil.jsonToChalk(packet);
}
}
static getLookPosition(entity) {
if (!entity.position) {
return new Vec3(0, 1.5, 0);
}
return entity.position.offset(0, 1.5, 0);
}
}
module.exports = MinecraftUtil;