yoni-mcscripts-lib
Version:
为 Minecraft Script API 中的部分接口创建了 wrapper,并提供简单的事件管理器和任务管理器,另附有一些便于代码编写的一些小工具。
230 lines (229 loc) • 8.15 kB
JavaScript
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开启");
}
}
});