refactor: Rewrites the event API
This commit is contained in:
Vendored
+860
-214
File diff suppressed because it is too large
Load Diff
+166
-25
@@ -1,28 +1,169 @@
|
||||
/** 事件创建函数 @type {function(string,string):boolean} */
|
||||
const CallEvent = ll.import("GMLIB_Event_API", "callCustomEvent");
|
||||
/** 获取事件ID函数 @type {function():string} */
|
||||
const getNextEventId = ll.import("GMLIB_Event_API", "getNextScriptEventId");
|
||||
|
||||
/** 事件类 */
|
||||
class Event {
|
||||
constructor() { throw new Error("Static class cannot be instantiated"); }
|
||||
|
||||
/**
|
||||
* 监听事件
|
||||
* @param {string} event 事件名称
|
||||
* @param {function} callback 回调
|
||||
* @returns {boolean} 是否创建成功
|
||||
*/
|
||||
static listen(event, callback) {
|
||||
let eventId = getNextEventId();
|
||||
ll.export(callback, event, eventId);
|
||||
let result = CallEvent(event, eventId);
|
||||
if (!result) {
|
||||
logger.error(`Cannot listen event "${event}" !`);
|
||||
logger.error(`GMLIB Script Event "${event}" does not exist !`);
|
||||
}
|
||||
return result;
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
const getPluginName = () => {
|
||||
try {
|
||||
throw new Error("getPluginName");
|
||||
} catch (error) {
|
||||
return error.stack.trim().match(/plugins\\(.*)\\.*\.js:[0-9]+\)$/i)?.[1] || "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Event };
|
||||
module.exports = {
|
||||
Event: {
|
||||
/**
|
||||
* 事件订阅记录
|
||||
* 例如: {事件名: [事件ID, ...], ...}
|
||||
* @type {Object.<string, number[]>}
|
||||
*/
|
||||
mEventData: {},
|
||||
/**
|
||||
* 事件异常处理回调
|
||||
* @param {Error} error
|
||||
* @param {string} eventName
|
||||
* @param {number} eventID
|
||||
* @param {string} pluginName
|
||||
* @returns {void}
|
||||
*/
|
||||
mErrorHanlerCallback: (error, eventName, eventID, pluginName) => {
|
||||
logger.error(`Info: ${pluginName}-${eventName}-${eventID} Exception: ${error.message}\n${error.stack}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听事件(兼容旧版)
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
* @param {boolean}
|
||||
*/
|
||||
listen: function (eventName, callback) {
|
||||
try {
|
||||
const eventReflection = {
|
||||
onServerStopping: "ll::ServerStoppingEvent",
|
||||
onClientLogin: "gmlib::ClientLoginAfterEvent",
|
||||
onWeatherChange: "gmlib::WeatherUpdateBeforeEvent",
|
||||
onMobPick: "gmlib::MobPickupItemBeforeEvent",
|
||||
onItemTrySpawn: "gmlib::ItemActorSpawnBeforeEvent",
|
||||
onItemSpawned: "gmlib::ItemActorSpawnAfterEvent",
|
||||
onEntityTryChangeDim: "gmlib::ActorChangeDimensionBeforeEvent",
|
||||
onLeaveBed: "gmlib::PlayerStopSleepBeforeEvent",
|
||||
onDeathMessage: "gmlib::DeathMessageAfterEvent",
|
||||
onMobHurted: "gmlib::MobHurtAfterEvent",
|
||||
onEndermanTake: "gmlib::EndermanTakeBlockBeforeEvent",
|
||||
onEntityChangeDim: "gmlib::ActorChangeDimensionAfterEvent",
|
||||
onDragonRespawn: "gmlib::DragonRespawnBeforeEvent",
|
||||
onProjectileTryCreate: "gmlib::ProjectileCreateBeforeEvent",
|
||||
onProjectileCreate: "gmlib::ProjectileCreateAfterEvent",
|
||||
onSpawnWanderingTrader: "gmlib::SpawnWanderingTraderBeforeEvent",
|
||||
onHandleRequestAction: "gmlib::HandleRequestActionBeforeEvent",
|
||||
onSendContainerClosePacket: "gmlib::ContainerClosePacketSendAfterEvent"
|
||||
};
|
||||
this.emplaceListener(eventReflection[eventName] ?? eventName, event => {
|
||||
const result = callback(...event.params);
|
||||
if (typeof (result) === "boolean" && !result) event.cancel();
|
||||
});
|
||||
return true;
|
||||
} catch { }
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* 订阅事件
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
* @param {number?} priority
|
||||
* @param {string?} pluginName
|
||||
* @returns {number}
|
||||
*/
|
||||
emplaceListener: function (eventName, callback, priority = this.EventPriority.Normal, pluginName = getPluginName()) {
|
||||
const /** @type {number} */ eventId = ll.imports("GMLIB_Event_API", "emplaceListener")(pluginName, eventName, priority);
|
||||
if (eventId === -1) throw new Error(`Event ${eventName} creation failed!`);
|
||||
ll.exports((...data) => {
|
||||
let /** @type {boolean} */ result = typeof (data.slice(-1)[0]) === "boolean" ? data.pop() : false;
|
||||
try {
|
||||
callback({
|
||||
params: data,
|
||||
cancel: () => result = true,
|
||||
setCancelled: (/** @type {boolean} */value) => result = value,
|
||||
isCancelled: () => result,
|
||||
getId: () => eventId,
|
||||
getEventType: () => eventName
|
||||
});
|
||||
} catch (error) {
|
||||
try {
|
||||
this.mErrorHanlerCallback(error, eventName, eventId, pluginName);
|
||||
} catch { }
|
||||
}
|
||||
return result;
|
||||
}, pluginName, eventName + "_" + eventId);
|
||||
if (this.mEventData[eventName] === undefined) this.mEventData[eventName] = [];
|
||||
this.mEventData[eventName].push(eventId);
|
||||
return eventId;
|
||||
},
|
||||
|
||||
/**
|
||||
* 取消事件订阅
|
||||
* @param {number} eventId
|
||||
* @param {boolean}
|
||||
*/
|
||||
removeListener: function (eventId) {
|
||||
const result = ll.imports("GMLIB_Event_API", "removeListener")(eventId);
|
||||
if (result) {
|
||||
for (let [eventName, eventIds] of Object.entries(this.mEventData)) {
|
||||
this.mEventData[eventName] = eventIds.filter(id => id !== eventId);
|
||||
if (this.mEventData[eventName].length === 0) delete this.mEventData[eventName];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* 判断事件订阅是否存在
|
||||
* @param {number} eventId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
hasListener: function (eventId) {
|
||||
return ll.imports("GMLIB_Event_API", "hasListener")(eventId);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取订阅事件优先级
|
||||
* @param {number} eventId
|
||||
* @returns {number?}
|
||||
*/
|
||||
getListenerPriority: function (eventId) {
|
||||
const priority = ll.imports("GMLIB_Event_API", "getListenerPriority")(eventId);
|
||||
return priority === -1 ? undefined : priority;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取订阅事件列表
|
||||
* @param {string | undefined} eventName
|
||||
* @returns {number[] | Object.<string, number[]>}
|
||||
*/
|
||||
getListener: function(eventName) {
|
||||
return eventName === undefined ? this.mEventData : this.mEventData[eventName] ?? [];
|
||||
},
|
||||
|
||||
/**
|
||||
* 设置异常处理回调
|
||||
* @param {function(Error, string, number, string): void} callback
|
||||
* @returns {boolean}
|
||||
*/
|
||||
setErrorHanlerCallback: function (callback) {
|
||||
if (callback === undefined || typeof callback !== "function") return false;
|
||||
this.mErrorHanlerCallback = callback;
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* 事件优先级
|
||||
*/
|
||||
EventPriority: {
|
||||
Highest: 0,
|
||||
High: 100,
|
||||
Normal: 200,
|
||||
Low: 300,
|
||||
Lowest: 400
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user