From eb96195fb9675232e4755aa8516854318860f4ff Mon Sep 17 00:00:00 2001 From: Yaode_owo Date: Sat, 8 Jun 2024 02:59:54 -0400 Subject: [PATCH] Upload files to "/" --- MessageBuilder.js | 257 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 MessageBuilder.js diff --git a/MessageBuilder.js b/MessageBuilder.js new file mode 100644 index 0000000..0048459 --- /dev/null +++ b/MessageBuilder.js @@ -0,0 +1,257 @@ +const mojangson = require('mojangson') +const nbt = require('prismarine-nbt') + +const supportedColors = { + 0: 'black', + 1: 'dark_blue', + 2: 'dark_green', + 3: 'dark_aqua', + 4: 'dark_red', + 5: 'dark_purple', + 6: 'gold', + 7: 'gray', + 8: 'dark_gray', + 9: 'blue', + a: 'green', + b: 'aqua', + c: 'red', + d: 'light_purple', + e: 'yellow', + f: 'white', + k: 'obfuscated', + l: 'bold', + m: 'strikethrough', + n: 'underlined', + o: 'italic', + r: 'reset' +} + +function loader (registry) { + class MessageBuilder { + constructor () { + this.with = [] + this.extra = [] + } + + /** @param {boolean} val */ + setBold (val) { this.bold = val; return this } + /** @param {boolean} val */ + setItalic (val) { this.italic = val; return this } + /** @param {boolean} val */ + setUnderlined (val) { this.underlined = val; return this } + /** @param {boolean} val */ + setStrikethrough (val) { this.strikethrough = val; return this } + /** @param {boolean} val */ + setObfuscated (val) { this.obfuscated = val; return this } + /** @param {string} val */ + setColor (val) { this.color = val; return this } + /** @param {string} val */ + setText (val) { this.text = val; return this } + /** + * The resource location of the font for this component in the resource pack within `assets//font`. + * @param {string} val Defaults to `minecraft:default` + * @returns + */ + setFont (val) { this.font = val; return this } + /** + * When used, it's expected that all slots for text will be filled using .addWith() + * @param {string} val + * @returns + */ + setTranslate (val) { this.translate = val; return this } + /** + * text shown when shift clicked on message + * @param {string} val + */ + setInsertion (val) { this.insertion = val; return this } + /** + * Overrode by .setText() + * @param {string} val + * @example + * builder.setKeybind('key.inventory') + */ + setKeybind (val) { this.keybind = val; return this } + /** + * Displays a score holder's current score in an objective. + * Displays nothing if the given score holder or the given objective do not exist, or if the score holder is not tracked in the objective. + * @param {string} name if '*', show reader their own score. Otherwise, this is the player's score shown. Can be a selector string, but must never select more than one entity. + * @param {string} objective The internal name of the objective to display the player's score in. + */ + setScore (name, objective) { this.score = { name, objective }; return this } + /** + * @param {'open_url'|'run_command'|'suggest_command'|'change_page'|'copy_to_clipboard'} action + * @param {string|number} value + * @example + * builder.setClickEvent('open_url', 'https://google.com') + * builder.setClickEvent('run_command', '/say Hi!') // for signs, the slash doesn't need to be there + * builder.setClickEvent('suggest_command', '/say ') + * builder.setClickEvent('change_page', '/say Hi!') // Can only be used in written books + * builder.setClickEvent('copy_to_clipboard', 'welcome to your clipboard') + */ + setClickEvent (action, value) { this.clickEvent = { action, value }; return this } + /** + * @param {'show_text'|'show_entity'|'show_item'} action + * @param {import('prismarine-item').Item|import('prismarine-entity').Entity|MessageBuilder} data + * @param {'contents'|'value'} type [type='contents'] + */ + setHoverEvent (action, data, type = 'contents') { + const hoverEvent = { action } + if (type === 'contents') { + switch (action) { + case 'show_item': + hoverEvent.contents = { + id: `minecraft:${data.name}`, + count: data.count, + tag: data.nbt ? mojangson.stringify(data.nbt) : {} + } + break + case 'show_entity': + hoverEvent.contents = { + name: data.displayName, + type: `minecraft:${data.name}`, + id: data.uuid + } + break + case 'show_text': + hoverEvent.contents = data + break + default: + throw Error('Not implemented') + } + } else if (type === 'value') { + switch (action) { + case 'show_item': + // works for 1.12.2 & 1.17 + hoverEvent.value = mojangson.stringify(nbt.comp({ + id: nbt.string(`minecraft:${data.name}`), + Count: nbt.byte(data.count), + tag: data.nbt || nbt.comp({}), + Damage: nbt.short(0) + })) + break + case 'show_text': + hoverEvent.value = data.toString() + break + case 'show_entity': + default: + throw Error('Not implemented') + } + } + this.hoverEvent = hoverEvent + return this + } + + /** + * appended to the end of this message object with the existing formatting. + * formatting can be overrode in child messagebuilder + * @param {Array} ...args + * @returns + */ + addExtra (...args) { + for (const v of args) { + const value = typeof v === 'string' ? v : v.toJSON() + this.extra.push(value) + } + return this + } + + /** + * requires .translate to be set for this to be used + * @param {Array} ...args + * @returns + */ + addWith (...args) { + for (const v of args) { + const value = typeof v === 'string' ? v : v.toJSON() + this.with.push(value) + } + return this + } + + resetFormatting () { + this.setBold(false) + this.setItalic(false) + this.setUnderlined(false) + this.setStrikethrough(false) + this.setObfuscated(false) + this.setColor('reset') + } + + toJSON () { + const isDef = x => x !== undefined + const obj = {} + if (isDef(this.strikethrough)) obj.strikethrough = this.strikethrough + if (isDef(this.obfuscated)) obj.obfuscated = this.obfuscated + if (isDef(this.underlined)) obj.underlined = this.underlined + if (isDef(this.clickEvent)) obj.clickEvent = this.clickEvent + if (isDef(this.hoverEvent)) obj.hoverEvent = this.hoverEvent + if (isDef(this.translate)) obj.translate = this.translate + if (isDef(this.insertion)) obj.insertion = this.insertion + if (isDef(this.italic)) obj.italic = this.italic + if (isDef(this.color)) obj.color = this.color + if (isDef(this.bold)) obj.bold = this.bold + if (isDef(this.font)) obj.font = this.font + if (isDef(this.text)) { // text > keybind > score + obj.text = this.text + } else if (isDef(this.keybind)) { + obj.keybind = this.keybind + } else if (isDef(this.score)) { + obj.score = this.score + } + if (isDef(this.translate) && this.with.length > 0) { + obj.with = this.with + } + if (this.extra.length > 0) { + obj.extra = this.extra + } + return obj + } + + toString () { + return JSON.stringify(this) + } + + static fromString (str, { colorSeparator = '&' } = {}) { + let lastObj = null + let currString = '' + for (let i = str.length - 1; i > -1; i--) { + const char = str.substring(i, i + 1) + if (char !== colorSeparator) currString += char + else { + const text = currString.split('').reverse() + const color = supportedColors[text.shift()] + const newObj = new MessageBuilder() + if (color === 'obfuscated') { + newObj.setObfuscated(true) + } else if (color === 'bold') { + newObj.setBold(true) + } else if (color === 'strikethrough') { + newObj.setStrikethrough(true) + } else if (color === 'underlined') { + newObj.setUnderlined(true) + } else if (color === 'italic') { + newObj.setItalic(true) + } else if (color === 'reset') { + newObj.resetFormatting() + } else { + newObj.setColor(color) + } + newObj.setText(text.join('')) + if (lastObj === null) lastObj = newObj + else lastObj = newObj.addExtra(lastObj) + currString = '' + } + } + if (currString !== '') { + const txt = currString.split('').reverse().join('') + if (lastObj !== null) lastObj = new MessageBuilder().setText(txt).addExtra(lastObj) + else lastObj = new MessageBuilder().setText(txt) + } + return lastObj + } + } + + return { MessageBuilder } +} + +module.exports = loader