yoni-mcscripts-lib
Version:
为 Minecraft Script API 中的部分接口创建了 wrapper,并提供简单的事件管理器和任务管理器,另附有一些便于代码编写的一些小工具。
101 lines (100 loc) • 4.06 kB
JavaScript
import { sEventListenerData } from "./decorators/EventListener.js";
import { logger } from "./logger.js";
import { EventError } from "./EventError.js";
import { EventRegistry } from "./EventRegistry.js";
import { isDebug, config } from "../config.js";
import { listenEvent } from "./lib/listenEvent.js";
export class EventManager {
/**
* 处理事件回调要求的额外参数。
*/
static checkExtraOption(eventRegistry, handler, event) {
if (!eventRegistry.extraOption
|| !handler.options
|| !eventRegistry.extraOptionResolver) {
return true;
}
try {
return eventRegistry.extraOptionResolver(event, handler.options);
}
catch (e) {
if (isDebug() || config.getConfig("eventManager.showErrorOfEventFilter"))
logger.warn("处理事件过滤器时发生以下错误:", e);
}
return false;
}
/**
* 处理一次事件。
* @param eventRegistry 事件的注册信息。
* @param event 事件对象。
* @param noExtendsAlways 指定是否不应该去尝试扩展事件的回调范围。
*/
callEvent(eventRegistry, event, noExtendsAlways = false) {
eventRegistry.throwIfNotRegistered();
if (!noExtendsAlways && !eventRegistry.noExtends) {
let extendsEvents = EventRegistry.getExtends(eventRegistry);
for (const registry of extendsEvents) {
this.callEvent(registry, event, true);
}
}
try {
for (const handler of eventRegistry.handlers) {
if (handler.ignoreCancelled
&& "cancel" in event
&& event.cancel) {
continue; //跳过,由于处理器不接受已取消事件
}
if (!EventManager.checkExtraOption(eventRegistry, handler, event)) {
continue;
}
try { //捕获事件处理错误,并输出日志
handler.onEvent(event);
}
catch (e) {
logger.error("处理事件 {} 时发生以下错误:", eventRegistry.eventName, e);
}
}
}
catch (e) { //捕获事件执行错误,应该抛出(不过我也不知道这里能捕获到什么错误)
//re-throw EventError
const error = new EventError(eventRegistry, event, e);
if (isDebug())
logger.error(error);
throw error;
}
}
addListener(listener) {
if (!(sEventListenerData in listener))
throw new TypeError("not a listener");
const cListener = listener;
const data = cListener[sEventListenerData];
if (data.registeredListeners.size === 0)
for (const entries of data.handlerEntries) {
const [tevent, prio, handler] = entries;
EventRegistry.getRegistry(tevent).addHandler(handler, prio);
}
if (data.registeredListeners.has(listener))
throw new Error("the listener already been registered");
data.registeredListeners.add(listener);
}
removeListener(listener) {
if (!(sEventListenerData in listener))
throw new TypeError("not a listener");
const cListener = listener;
const data = cListener[sEventListenerData];
if (!data.registeredListeners.has(listener))
return false;
data.registeredListeners.delete(listener);
if (data.registeredListeners.size === 0)
for (const entries of data.handlerEntries) {
const [tevent, prio, handler] = entries;
EventRegistry.getRegistry(tevent).removeHandler(handler, prio);
}
return true;
}
listenEvent(listenOptions, callback) {
return listenEvent(listenOptions, callback);
}
}
export const eventManager = new EventManager();
export { eventManager as manager };