diff --git a/src/catalyst/config.ts b/src/catalyst/config.ts index e4a950a..85f0ae1 100644 --- a/src/catalyst/config.ts +++ b/src/catalyst/config.ts @@ -6,18 +6,24 @@ export default { * enable debugging */ debug: true, - /** - * command prefix to use, default is "\" - */ - commandPrefix: "\\", /** * threshold duration for server lag warning (in milliseconds) */ serverLagWarning: 400, /** - * how many commands from the queue should be executed in a tick + * how many minecraft commands from the queue should be executed in a tick */ commandBuffer: 128, + + /** + * command prefix to use, default is "\" + */ + commandPrefix: "\\", + + /** + * allow multithreading + */ + multiThreading: true, /** * max number of thread tasks to execute every tick */ diff --git a/src/catalyst/core/command.ts b/src/catalyst/core/command.ts index 281a2a9..a7c2fa4 100644 --- a/src/catalyst/core/command.ts +++ b/src/catalyst/core/command.ts @@ -14,6 +14,7 @@ export let commandPrefix: string = config.commandPrefix; /** * change the command prefix + * @param newPrefix new prefix */ export function setCommandPrefix(newPrefix: string): void { events.dispatchEvent("commandPrefixChanged", commandPrefix, newPrefix); diff --git a/src/catalyst/core/events.ts b/src/catalyst/core/events.ts index 70fc092..1d134b3 100644 --- a/src/catalyst/core/events.ts +++ b/src/catalyst/core/events.ts @@ -86,7 +86,13 @@ export class EventManager> { // run the listener try { listener.callback?.(...args); - } catch { /* no-op */ }; + } catch (e) { + // error + console.error( + `Uncaught exception on an event listener for ${event as string}:\n`, + e?.stack || e + ); + } // the listener only listens once if (listener.once) this.removeEventListener(listener); diff --git a/src/catalyst/core/glyphs.ts b/src/catalyst/core/glyphs.ts index ddfd62e..9ad308f 100644 --- a/src/catalyst/core/glyphs.ts +++ b/src/catalyst/core/glyphs.ts @@ -13,9 +13,7 @@ // lg = left grab // rg = right grab -export const glyphs: { - [name: string]: string -} = { +export const glyphs: Record = { xbox_a: "\uE000", xbox_b: "\uE001", xbox_x: "\uE002", diff --git a/src/catalyst/core/logger.ts b/src/catalyst/core/logger.ts index 1d663f5..777e0ef 100644 --- a/src/catalyst/core/logger.ts +++ b/src/catalyst/core/logger.ts @@ -7,10 +7,12 @@ const logTextPlaceholder = "[text]"; const logTypePlaceholder = "[type]"; /** + * @class Logger * a custom logger */ export class Logger { /** + * @constructor * make an instance of logger * @param format the log format, with placeholders "[text]" and "[type]" * @throws placeholder [text] not found on format string @@ -20,10 +22,12 @@ export class Logger { throw new Error("Placeholder \"[text]\" not found on log format: " + format); this.format = format; } + /** * the log format */ public readonly format: string; + /** * whether to show all logs on the gui (useful when debugging) */ @@ -32,6 +36,7 @@ export class Logger { * enable debug logging */ public showDebug: boolean = false; + /** * return a text from the given log following the format string * @param text the text @@ -41,6 +46,7 @@ export class Logger { public makeLogText(text: string, type: string): string { return this.format.replace(logTypePlaceholder, type).replace(logTextPlaceholder, text); } + /** * prints the log into the content log file or gui, or botha * @param text the log text @@ -56,6 +62,7 @@ export class Logger { case 2: console.error(text); break; } } + /** * logs a message * @param msg the text @@ -63,6 +70,7 @@ export class Logger { public log(text: string): void { this.printLog(this.makeLogText(text, "log"), this.showToGui ? 1 : 0); } + /** * logs information * @param msg the text @@ -70,6 +78,7 @@ export class Logger { public info(text: string): void { this.printLog(this.makeLogText(text, "info"), this.showToGui ? 1 : 0); } + /** * logs debugging message * @param msg the text @@ -78,6 +87,7 @@ export class Logger { if (!this.showDebug) return; this.printLog(this.makeLogText(text, "debug"), this.showToGui ? 1 : 0); } + /** * logs a warning * @param msg the text @@ -85,6 +95,7 @@ export class Logger { public warn(text: string): void { this.printLog(this.makeLogText(text, "warning"), 1); } + /** * logs an error * @param msg the text @@ -92,4 +103,5 @@ export class Logger { public error(text: string): void { this.printLog(this.makeLogText(text, "error"), 2); } + } diff --git a/src/catalyst/core/plugin.ts b/src/catalyst/core/plugin.ts index 3c21089..91e1c3c 100644 --- a/src/catalyst/core/plugin.ts +++ b/src/catalyst/core/plugin.ts @@ -55,10 +55,12 @@ type pluginEvents = { }; /** + * @class Plugin * plugin class */ export class Plugin extends EventManager { /** + * @constructor * make a new plugin * @param id the identifier of the plugin * @param fn the startup function of the plugin diff --git a/src/catalyst/core/rawtext.ts b/src/catalyst/core/rawtext.ts index d789c91..992da4e 100644 --- a/src/catalyst/core/rawtext.ts +++ b/src/catalyst/core/rawtext.ts @@ -59,9 +59,19 @@ interface scoreRawMessage { type rawTextNode = textRawMessage | translateRawMessage | selectorRawMessage | scoreRawMessage; /** + * @class RawText * the rawtext builder class */ export class RawText { + /** + * @constructor + * creates a new RawText instance + * @param [nodes] optional raw json nodes + */ + constructor(nodes: rawTextNode[] = []) { + this._nodes = nodes; + } + /** * rawtext nodes * @private @@ -71,20 +81,26 @@ export class RawText { /** * raw string * @param val the string + * @param [prepend] put this on top of the rawtext * @returns self */ - public text(val: string): this { - this._nodes.push({ text: val }); + public text(val: string, prepend?: boolean): this { + const json = { text: val }; + if (prepend) this.prepend(json); + else this.append(json); return this; } /** * translate message from player's locale * @param key the translation key + * @param [prepend] put this on top of the rawtext * @returns self */ - public translate(key: string): this { - this._nodes.push({ translate: key }); + public translate(key: string, prepend?: boolean): this { + const json = { translate: key }; + if (prepend) this.prepend(json); + else this.append(json); return this; } @@ -110,10 +126,13 @@ export class RawText { /** * target selector * @param val '@-' target selector or player name + * @param [prepend] put this on top of the rawtext * @returns self */ - public selector(val: string): this { - this._nodes.push({ selector: val }); + public selector(val: string, prepend?: boolean): this { + const json = { selector: val }; + if (prepend) this.prepend(json); + else this.append(json); return this; } @@ -121,10 +140,13 @@ export class RawText { * scorboard score of entity * @param objective the scoreboard objective * @param name target selector + * @param [prepend] put this on top of the rawtext * @returns self */ - public score(objective: string, name: string): this { - this._nodes.push({score:{ objective, name }}); + public score(objective: string, name: string, prepend?: boolean): this { + const json = {score:{ objective, name }}; + if (prepend) this.prepend(json); + else this.append(json); return this; } @@ -164,4 +186,12 @@ export class RawText { }) } } + + /** + * returns json text + * @returns the string + */ + toString(): string { + return JSON.stringify(this.toJSON()); + } } diff --git a/src/catalyst/core/selector.ts b/src/catalyst/core/selector.ts index c28c822..69a76c8 100644 --- a/src/catalyst/core/selector.ts +++ b/src/catalyst/core/selector.ts @@ -41,10 +41,12 @@ type slotType = "slot.weapon.mainhand" | "slot.weapon.offhand" | "slot.armor.hea | "slot.chest" | "slot.equippable"; /** + * @class Selector * selector builder */ export class Selector { /** + * @constructor * make a new selector builder * @param [base] the base selector */ diff --git a/src/catalyst/core/server.ts b/src/catalyst/core/server.ts index a74947d..67a4cf6 100644 --- a/src/catalyst/core/server.ts +++ b/src/catalyst/core/server.ts @@ -37,35 +37,42 @@ export function message(msg: string, target?: Player | Player[]): void { // [/tellraw] command const cmd = `tellraw @s {"rawtext":[{"text":${JSON.stringify(msg)}}]}`; // run command - if (target instanceof Player) runCommand(cmd, target); - else if (target instanceof Array) target.forEach(plr => runCommand(cmd, plr)); - else runCommand(cmd); + if (target instanceof Player) queueCommand(cmd, target); + else if (target instanceof Array) target.forEach(plr => queueCommand(cmd, plr)); + else world.getAllPlayers()?.forEach(plr => queueCommand(cmd, plr)); } // command queue const cmdQueue: Function[] = []; -// just trigger promises every tick +// flush the command queue system.runInterval(() => { // initial value for buffer let buffer = config.commandBuffer; // loop - while (cmdQueue.length && buffer > 0) { + while (cmdQueue.length && buffer-- > 0) cmdQueue.shift()?.(); - buffer--; - } }); /** - * queue a command + * queue a minecraft command * @param cmd the command * @param [target] the target * @returns a promise which later can be resolved */ -export function runCommand(cmd: string, target?: Entity | Dimension): Promise { +export function queueCommand(cmd: string, target?: Entity | Dimension): Promise { return new Promise(resolve => cmdQueue.push(resolve)) - .then(r => (target ?? world.getDimension("overworld")).runCommand(cmd)); + .then(r => runCommand(cmd)); } +/** + * run a minecraft command + * @param cmd the command + * @param [target] the target + * @returns the command result + */ +export function runCommand(cmd: string, target?: Entity | Dimension): CommandResult { + return (target ?? world.getDimension("overworld")).runCommand(cmd); +} // listen for internal events world.beforeEvents.chatSend.subscribe(ev => events.dispatchEvent("beforeChatSend", ev)); diff --git a/src/catalyst/core/thread.ts b/src/catalyst/core/thread.ts index 7b7db9b..504bbc7 100644 --- a/src/catalyst/core/thread.ts +++ b/src/catalyst/core/thread.ts @@ -47,16 +47,18 @@ system.runInterval(() => { }); /** + * @class Thread * thread handler * @template A args of the generator function * @template R return type of the generator function */ export class Thread { /** + * @constructor * initialize a new Thread instance * @param fn the generator function */ - constructor(fn: genFn, unknown, unknown>) { + constructor(fn: genFn, unknown, unknown>) { this._function = fn; this.threadId = id++; } @@ -109,6 +111,9 @@ export class Thread { if (!this.isActive) { this._task = this._function.apply(this, args); + // multi threading disabled + if (!config.multiThreading) this.join(); + // return Promise return new Promise((res, rej) => { this._fnReturn = res; diff --git a/src/catalyst/plugins/chats/profanity.js b/src/catalyst/plugins/chats/profanity.js index 9a8ab9a..8060c50 100644 --- a/src/catalyst/plugins/chats/profanity.js +++ b/src/catalyst/plugins/chats/profanity.js @@ -4,23 +4,23 @@ /** @type {string[]} */ export default [ - 'ars*e', // arse + 'ars+e', // arse 'as{2,}', // ass - 'ba*sta*rd', // bastard - 'be*lle*nd',// bellend - 'bi*nt', // bint - 'bi*a?tc*h', // bitch - 'bo*llo*c*ks', // bollocks - 'bu*gger', // bugger - 'da*mn*', // damn - 'di*c*k', // dick - 'f(?:u|e)*c*k', // f[ue]ck - 'gi*t', // git - 'mi*nge*r', // minger - 'mu*nte*r', // munter - 'ni*g*a', // nigga - 'pi*s{2,}e*d', // pissed - 'shi*t', // shit - 'so*d', // sod - 'twa*t' // twat + 'ba+sta+d', // bastard + 'be+lle+nd',// bellend + 'bi+nt', // bint + 'bi+a?tc+h', // bitch + 'bo+llo+c+ks', // bollocks + 'bu+gger', // bugger + 'da+mn+', // damn + 'di+c+k', // dick + 'f(?:u|e)+c+k', // f[ue]ck + 'gi+t', // git + 'mi+nge+r', // minger + 'mu+nte+r', // munter + 'ni+g+a', // nigga + 'pi+s{2,}e+d', // pissed + 'shi+t', // shit + 'so+d', // sod + 'twa+t' // twat ];