Files
GMLIB-LegacyRemoteCallApi/lib/EventAPI-JS.js
T
2024-11-16 17:33:37 +08:00

169 lines
6.5 KiB
JavaScript

/**
* @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: {
/**
* 事件订阅记录
* 例如: {事件名: [事件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
}
}
};