Files
GameStarter/libraries/chat.js
T

238 lines
6.5 KiB
JavaScript

// https://github.com/janispritzkau/mc-chat-format
/**
* Converts a Minecraft chat component to a formatted string.
* */
export function format(component, options = {}) {
const text = formatString(convert(component, options), options.useAnsiCodes);
if (options.maxLineLength) {
let t = "", e = false, l = 0;
for (let c of text) {
if (c === "\x1b")
e = true;
else if (c === "m")
e = false;
else if (c === "\n")
l = 0;
t += c;
if (l === options.maxLineLength)
t += "\n", l = 0;
if (!e)
l += 1;
}
return t;
} else
return text;
}
/**
* Applies translations to a [Chat component](https://wiki.vg/Chat) and converts
* it to `StringComponent`.
*/
export function convert(component, options = {}) {
if (typeof component == "string") {
return options.keepOld ? {text: component} : convertOld(component);
}
if (component.extra) {
component.extra = component.extra.map(x => convert(x, options));
}
if (options.stripNonText) {
delete component.hoverEvent;
delete component.clickEvent;
delete component.insertion;
}
if (!options.keepOld) {
const {text, extra} = convertOld(component.text);
component.text = text;
if (extra && component.extra)
component.extra = [...extra, ...component.extra];
else if (extra && !component.extra)
component.extra = extra;
}
return component;
}
/**
* Converts a string formatted using the old formatting scheme
* to the current JSON chat system.
*/
export function convertOld(text) {
let c = {text: ""};
const extra = [];
for (const [i, t] of text.split(/ยง(.)/).entries()) {
if (i === 0) {
c.text = t;
} else if (i % 2 === 0) {
if (t.length !== 0)
extra.push({...c, text: t});
} else
switch (t) {
case "k":
c.obfuscated = true;
break;
case "l":
c.bold = true;
break;
case "m":
c.strikethrough = true;
break;
case "n":
c.underlined = true;
break;
case "o":
c.bold = true;
break;
case "r":
c = {text: c.text};
break;
case "0":
c.color = "black";
break;
case "1":
c.color = "dark_blue";
break;
case "2":
c.color = "dark_green";
break;
case "3":
c.color = "dark_aqua";
break;
case "4":
c.color = "dark_red";
break;
case "5":
c.color = "dark_purple";
break;
case "6":
c.color = "gold";
break;
case "7":
c.color = "gray";
break;
case "8":
c.color = "dark_gray";
break;
case "9":
c.color = "blue";
break;
case "a":
c.color = "green";
break;
case "b":
c.color = "aqua";
break;
case "c":
c.color = "red";
break;
case "d":
c.color = "light_purple";
break;
case "e":
c.color = "yellow";
break;
case "f":
c.color = "white";
break;
}
}
c = {text: c.text};
if (extra.length > 0)
c.extra = extra;
return c;
}
/** Flattens a nested `StringComponent`. */
export function flatten(component) {
const {text, extra, ...rest} = component;
const array = [{text, ...rest}];
if (extra)
array.push(...flattenArray(extra.map(c => {
if (typeof c == "string")
return [{text: c, ...rest}];
if (!('text' in c))
throw new Error("Not a StringComponent");
return flatten(c).map(c => ({...c, ...rest, ...c}));
})));
return array;
}
/** Converts a `StringComponent` to plain text and can format it using ANSI codes. */
export function formatString(component) {
return flatten(component).map((c) => {
let codes = colorToAnsiCode(c.color);
if (c.bold)
codes += "\u00a7l";
if (c.italic)
codes += "\u00a7o";
if (c.underlined)
codes += "\u00a7n";
if (c.strikethrough)
codes += "\u00a7m";
return codes ? codes + c.text + "\u00a7r" : c.text;
}).join("");
}
function colorToAnsiCode(color) {
let code = "";
switch (color) {
case "black":
code += "0";
break;
case "dark_blue":
code += "1";
break;
case "dark_green":
code += "2";
break;
case "dark_aqua":
code += "3";
break;
case "dark_red":
code += "4";
break;
case "dark_purple":
code += "5";
break;
case "gold":
code += "6";
break;
case "gray":
code += "7";
break;
case "dark_gray":
code += "8";
break;
case "blue":
code += "9";
break;
case "green":
code += "a";
break;
case "aqua":
code += "b";
break;
case "red":
code += "c";
break;
case "light_purple":
code += "d";
break;
case "yellow":
code += "e";
break;
case "white":
code += "f";
break;
}
return code && "\u00a7" + code;
}
function flattenArray(array) {
return [].concat(...array);
}
/** @deprecated Use `format(convert(component))` instead */
export function chatToText(component, translation) {
return format(component, {translation});
}