UNPKG

yoni-mcscripts-lib

Version:

为 Minecraft Script API 中的部分接口创建了 wrapper,并提供简单的事件管理器和任务管理器,另附有一些便于代码编写的一些小工具。

230 lines (229 loc) 8.15 kB
import { VanillaWorld } from "../basis.js"; import { Command } from "../command.js"; import { visualizeValue } from "../lib/console.js"; import { dealWithCmd as JSONModifier_dealWithCmd } from "../commandutils.js"; import { config } from "../config.js"; import { setDebugFunction } from '../debug.js'; import { ConsoleLogger } from "../lib/ConsoleLogger.js"; async function sendMessageTo(receiver, message) { let rawtext = JSON.stringify({ rawtext: [{ text: message }] }, JSONModifier_dealWithCmd); await Command.addExecute(Command.PRIORITY_HIGH, receiver, `tellraw @s ${rawtext}`); } function formatAnyValue(v) { return typeof v === "string" ? v : visualizeValue(v, 1, { showEnumerableOnly: true, maxItemPerObject: 4, recursiveQuery: false, // recursiveQuery: true, //不开,因为会出奇怪的问题。 // recursiveQueryDepth: 1, //未实现 }); } function showLoggerUsageOnce() { if (showLoggerUsageOnce.hasExecuted) return; showLoggerUsageOnce.hasExecuted = true; } function sendToConsole(method, msg) { method(msg); } function getTimeString(now = new Date()) { let H = String(now.getHours()); let M = String(now.getMinutes()); let S = String(now.getSeconds()); let MS = String(now.getMilliseconds()); let sH = "00" + H; sH = sH.slice(sH.length - 2); let sM = "00" + M; sM = sM.slice(sM.length - 2); let sS = "00" + S; sS = sS.slice(sS.length - 2); let sMS = MS + "000"; sMS = sMS.slice(0, 3); let str = sH + ":" + sM + ":" + sS + "." + sMS; return str; } var LoggingLevel; (function (LoggingLevel) { LoggingLevel[LoggingLevel["FATAL"] = 0] = "FATAL"; LoggingLevel[LoggingLevel["ERROR"] = 1] = "ERROR"; LoggingLevel[LoggingLevel["WARN"] = 2] = "WARN"; LoggingLevel[LoggingLevel["INFO"] = 3] = "INFO"; LoggingLevel[LoggingLevel["DEBUG"] = 4] = "DEBUG"; LoggingLevel[LoggingLevel["TRACE"] = 5] = "TRACE"; LoggingLevel[LoggingLevel["VERBOSE"] = 6] = "VERBOSE"; })(LoggingLevel || (LoggingLevel = {})); function getLoggingLevelName(code) { for (const key of Object.keys(LoggingLevel)) //@ts-ignore if (LoggingLevel[key] === code) return key; return "LOG"; } export const LoggingNameMappings = { "0": LoggingLevel.FATAL, fatal: LoggingLevel.FATAL, f: LoggingLevel.FATAL, "1": LoggingLevel.ERROR, error: LoggingLevel.ERROR, e: LoggingLevel.ERROR, err: LoggingLevel.ERROR, fail: LoggingLevel.ERROR, ex: LoggingLevel.ERROR, severe: LoggingLevel.ERROR, "2": LoggingLevel.WARN, warn: LoggingLevel.WARN, w: LoggingLevel.WARN, warning: LoggingLevel.WARN, notice: LoggingLevel.WARN, "3": LoggingLevel.INFO, info: LoggingLevel.INFO, i: LoggingLevel.INFO, log: LoggingLevel.INFO, "4": LoggingLevel.DEBUG, debug: LoggingLevel.DEBUG, d: LoggingLevel.DEBUG, "5": LoggingLevel.TRACE, trace: LoggingLevel.TRACE, t: LoggingLevel.TRACE, "6": LoggingLevel.VERBOSE, verbose: LoggingLevel.VERBOSE, }; function transferHolder(msg, replacer) { msg = msg.replace(/\{\}/g, (match, offset, string) => { if (replacer.length > 0) match = formatAnyValue(replacer.shift()); return match; }); if (replacer.length > 0) { msg += " " + replacer.map(formatAnyValue).join(" "); } return msg; } function sendLogText(level, msg, rps, time, ignoreLevel = false) { const shouldSendToConsole = ignoreLevel || config.getBoolean("logging.outputToConsole"); const players = Array.from(//我们对旧版有良好的兼容性!(翻译:就是想用,你打我啊) VanillaWorld.getPlayers({ tags: [config.getString("logging.playerConsoleSpecificTag", "yoni:console")] })); if (players.length === 0 && !shouldSendToConsole) { showLoggerUsageOnce(); return; } const timeMsgHeader = `[${getTimeString(time)} ${level}]`; const msgHeader = `[${level}]`; msg = transferHolder(msg, rps); if (config.getBoolean("logging.uniqueFontSize")) msg = "§中" + msg; if (config.getBoolean("logging.showTimeStringOnConsoleOutput") || config.getBoolean("logging.showTimeString")) if (shouldSendToConsole) { const printer = Logger.getConsolePrinter(level, ConsoleLogger.warn); sendToConsole(printer, (config.getBoolean("logging.showTimeStringOnConsoleOutput") ? timeMsgHeader : msgHeader) + msg); } if (players.length > 0) { const msgWithHead = (config.getBoolean("logging.showTimeString") ? timeMsgHeader : msgHeader) + msg; players.forEach(player => sendMessageTo(player, msgWithHead)); } } class Logger { static setConsolePrinter(level, printer) { Logger.#consoleLevelPrinters.set(String(level), printer); } static getConsolePrinter(level, defaultPrinter) { return Logger.#consoleLevelPrinters.get(String(level)) ?? defaultPrinter; } static removeConsolePrinter(level) { if (Logger.#consoleLevelPrinters.has(String(level))) { Logger.#consoleLevelPrinters.delete(String(level)); return true; } return false; } static #consoleLevelPrinters = new Map(); /** * 向控制台输出日志。 */ static log(...data) { sendLogText("LOG", "", data, new Date(), true); } name; constructor(name) { if (typeof name !== "string" || name.trim() === "") throw new TypeError("Logger's name doesn't valid"); this.name = name; for (const lv_c of Object.entries(LoggingNameMappings)) { this.addLevelLogFunc(lv_c[0], lv_c[1]); } // return new Proxy(this, new LoggerProxy()); } async printOnLevel(lv, time, msg = "", ...rps) { if (typeof msg !== "string") { rps.unshift(msg); msg = ""; } msg = `[${this.name}]: ${msg}`; //@ts-ignore sendLogText(getLoggingLevelName(LoggingNameMappings[lv]), msg, rps, time); } addLevelLogFunc(level, levelCode) { //@ts-ignore this[level] = (...data) => { const time = new Date(); if (levelCode <= config.getInt("logging.logLevel", 3)) { this.printOnLevel(level, time, ...data); } }; //@ts-ignore return this[level]; } } export { Logger }; export const console = new Logger("LOG"); export const log = console.log; export const print = console.log; //修改原本的console if (config.getBoolean("logging.overrideDefaultConsole")) { Object.assign(globalThis.console, console, { log: Logger.log }); globalThis.print = print; } setDebugFunction(async function (ChatCommandModule) { const { ChatCommand } = await import("../command/ChatCommand.js"); ChatCommand.registerPrefixCommand("$", "log", onCommandExecute); //@ts-ignore async function onCommandExecute(sender, rawCommand, label, args) { const specificTag = config.getString("logging.playerConsoleSpecificTag", "yoni:console"); let action; if (args.length === 0) { if (sender.hasTag(specificTag)) { action = "off"; } else { action = "on"; } } else if (args[0] === "level") { const newLevelCode = parseInt(args[1]); if (isFinite(newLevelCode)) { config.setInt("logging.logLevel", newLevelCode); } sender.sendMessage("日志输出等级 §b" + newLevelCode); return; } else { if (args[0] === "off" || args[0] === "on") action = args[0]; } if (action === "off") { sender.removeTag(specificTag); sender.sendMessage("日志输出 §c关闭"); } else if (action === "on") { sender.addTag(specificTag); sender.sendMessage("日志输出 §a开启"); } } });