diff --git a/lib/EventAPI-JS.d.ts b/lib/EventAPI-JS.d.ts index f525eaa..a8975bc 100644 --- a/lib/EventAPI-JS.d.ts +++ b/lib/EventAPI-JS.d.ts @@ -636,10 +636,7 @@ export namespace Event { /** 回调 */ callback: (event: { /** 事件参数 */ - params: { - /** 末影龙复活后的uniqueId */ - 0: number - }, + params: {}, /** 拦截事件 */ cancel: () => void, /** 设置拦截状态 */ @@ -668,7 +665,7 @@ export namespace Event { callback: (event: { /** 事件参数 */ params: { - /** 末影人实体 */ + /** 末影龙实体 */ 0: Entity }, /** 获取事件ID */ diff --git a/lib/EventAPI-JS.js b/lib/EventAPI-JS.js index 384bcc2..f45fd02 100644 --- a/lib/EventAPI-JS.js +++ b/lib/EventAPI-JS.js @@ -7,7 +7,7 @@ const getPluginName = () => { } catch (error) { return error.stack.trim().match(/plugins\\(.*)\\.*\.js:[0-9]+\)$/i)?.[1] || "Unknown"; } -} +}; module.exports = { Event: { @@ -37,6 +37,7 @@ module.exports = { */ listen: function (eventName, callback) { try { + if (typeof callback !== "function") return false; const eventReflection = { onServerStopping: "ll::ServerStoppingEvent", onClientLogin: "gmlib::ClientLoginAfterEvent", @@ -75,6 +76,7 @@ module.exports = { * @returns {number} */ emplaceListener: function (eventName, callback, priority = this.EventPriority.Normal, pluginName = getPluginName()) { + if (typeof callback !== "function") throw new Error("callback must be a function!"); 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) => { @@ -83,7 +85,7 @@ module.exports = { callback({ params: data, cancel: () => result = true, - setCancelled: (/** @type {boolean} */value) => result = value, + setCancelled: (/** @type {boolean} */value) => { result = value; }, isCancelled: () => result, getId: () => eventId, getEventType: () => eventName @@ -95,8 +97,7 @@ module.exports = { } return result; }, pluginName, eventName + "_" + eventId); - if (this.mEventData[eventName] === undefined) this.mEventData[eventName] = []; - this.mEventData[eventName].push(eventId); + (this.mEventData[eventName] ??= []).push(eventId); return eventId; }, @@ -140,7 +141,7 @@ module.exports = { * @param {string | undefined} eventName * @returns {number[] | Object.} */ - getListener: function(eventName) { + getListener: function (eventName) { return eventName === undefined ? this.mEventData : this.mEventData[eventName] ?? []; }, diff --git a/src/EventAPI.cpp b/src/EventAPI.cpp index f80428b..c5bf2da 100644 --- a/src/EventAPI.cpp +++ b/src/EventAPI.cpp @@ -1,42 +1,72 @@ #include "Global.h" using namespace ll::hash_utils; +class EventManager { +private: + std::unordered_map mEventIds; + +public: + static EventManager& getInstance() { + static std::unique_ptr instance; + if (!instance) instance = std::make_unique(); + return *instance; + } + + ullong getNextId() { + auto id = mEventIds.size(); + mEventIds.emplace(id, nullptr); + return id; + } + + bool addListener(ullong id, ll::event::ListenerPtr const& listener) { + if (mEventIds.contains(id) && mEventIds[id]) return false; + mEventIds[id] = listener; + return true; + } + + bool removeListener(ullong id) { + if (ll::event::EventBus::getInstance().removeListener(mEventIds[id])) { + mEventIds[id] = nullptr; + return true; + } + return false; + } + + bool hasListener(ullong id) { return mEventIds.contains(id) && mEventIds[id]; } + + ll::event::ListenerPtr getListener(ullong id) { return mEventIds.contains(id) ? mEventIds[id] : nullptr; } +}; + #define REGISTER_EVENT_LISTEN(eventType, paramType, params, cancelFun, ...) \ - ll::event::ListenerPtr eventPtr = eventBus.emplaceListener( \ - [&eventBus, pluginName, eventName, eventId = (llong)mEventIds.size()](eventType& event) -> void { \ - if (!RemoteCall::hasFunc(pluginName, eventName + "_" + std::to_string(mEventIds.at(eventId)))) { \ - eventBus.removeListener(mEventIds.at(eventId)); \ + auto eventPtr = ll::event::EventBus::getInstance().emplaceListener( \ + [pluginName, eventName, eventId](eventType& event) -> void { \ + if (!RemoteCall::hasFunc(pluginName, eventName + "_" + std::to_string(eventId))) { \ + EventManager::getInstance().removeListener(eventId); \ return; \ } \ try { \ __VA_ARGS__ \ - auto result = RemoteCall::importAs( \ - pluginName, \ - eventName + "_" + std::to_string(mEventIds.at(eventId)) \ - ) params; \ - cancelFun; \ + auto result = \ + RemoteCall::importAs(pluginName, eventName + "_" + std::to_string(eventId)) \ + params; \ + cancelFun \ } catch (...) {} \ }, \ ll::event::EventPriority(priority) \ ); \ - mEventIds[mEventIds.size()] = eventPtr->getId(); \ - return (llong)eventPtr->getId() + return eventId void Export_Event_API() { - static std::unordered_map mEventIds = {}; - - auto& eventBus = ll::event::EventBus::getInstance(); - - RemoteCall::exportAs("GMLIB_Event_API", "removeListener", [&eventBus](ll::event::ListenerId eventId) -> bool { - return eventBus.removeListener(eventId); + RemoteCall::exportAs("GMLIB_Event_API", "removeListener", [](ll::event::ListenerId eventId) -> bool { + return EventManager::getInstance().removeListener(eventId); }); - RemoteCall::exportAs("GMLIB_Event_API", "hasListener", [&eventBus](ll::event::ListenerId eventId) -> bool { - return eventBus.hasListener(eventId); + RemoteCall::exportAs("GMLIB_Event_API", "hasListener", [](ll::event::ListenerId eventId) -> bool { + return EventManager::getInstance().hasListener(eventId); }); - RemoteCall::exportAs("GMLIB_Event_API", "getListenerPriority", [&eventBus](ll::event::ListenerId eventId) -> int { - if (auto event = eventBus.getListener(eventId); event != nullptr) { + RemoteCall::exportAs("GMLIB_Event_API", "getListenerPriority", [](ll::event::ListenerId eventId) -> int { + if (auto event = EventManager::getInstance().getListener(eventId); event != nullptr) { return (int)event->getPriority(); } return -1; @@ -45,7 +75,8 @@ void Export_Event_API() { RemoteCall::exportAs( "GMLIB_Event_API", "emplaceListener", - [&eventBus](std::string const& pluginName, std::string const& eventName, int priority) -> llong { + [](std::string const& pluginName, std::string const& eventName, int priority) -> llong { + auto eventId = EventManager::getInstance().getNextId(); switch (doHash(eventName)) { case doHash("ll::ServerStoppingEvent"): { REGISTER_EVENT_LISTEN(ll::event::ServerStoppingEvent, (), (), , ); @@ -61,7 +92,7 @@ void Export_Event_API() { event.getUuid().asString(), event.getServerAuthXuid(), event.getClientAuthXuid()), - if (result) event.disConnectClient() + if (result) event.disConnectClient(); ); } case doHash("gmlib::WeatherUpdateBeforeEvent"): { @@ -73,7 +104,7 @@ void Export_Event_API() { event.getLightningLevel(), event.getLightningLastTick(), event.isCancelled()), - event.setCancelled(result) + event.setCancelled(result); ); } case doHash("gmlib::WeatherUpdateAfterEvent"): { @@ -92,7 +123,7 @@ void Export_Event_API() { GMLIB::Event::EntityEvent::MobPickupItemBeforeEvent, (Actor * mob, Actor * item, bool isCancelled), (&event.self(), (Actor*)&event.getItemActor(), event.isCancelled()), - event.setCancelled(result) + event.setCancelled(result); ); } case doHash("gmlib::MobPickupItemAfterEvent"): { @@ -111,7 +142,7 @@ void Export_Event_API() { {event.getPosition(), event.getBlockSource().getDimensionId().id}, event.getSpawner().has_value() ? event.getSpawner()->getOrCreateUniqueID().id : -1, event.isCancelled()), - event.setCancelled(result) + event.setCancelled(result); ); } case doHash("gmlib::ItemActorSpawnAfterEvent"): { @@ -129,7 +160,7 @@ void Export_Event_API() { GMLIB::Event::EntityEvent::ActorChangeDimensionBeforeEvent, (Actor * entity, int toDimId, bool isCancelled), (&event.self(), event.getToDimensionId(), event.isCancelled()), - event.setCancelled(result) + event.setCancelled(result); ); } case doHash("gmlib::ActorChangeDimensionAfterEvent"): { @@ -145,7 +176,7 @@ void Export_Event_API() { GMLIB::Event::PlayerEvent::PlayerStartSleepBeforeEvent, (Player * entity, BlockPos pos, bool isCancelled), (&event.self(), event.getPosition(), event.isCancelled()), - event.setCancelled(result) + event.setCancelled(result); ); } case doHash("gmlib::PlayerStartSleepAfterEvent"): { @@ -161,7 +192,7 @@ void Export_Event_API() { GMLIB::Event::PlayerEvent::PlayerStopSleepBeforeEvent, (Player * entity, bool forcefulWakeUp, bool updateLevelList, bool isCancelled), (&event.self(), event.isForcefulWakeUp(), event.isUpdateLevelList(), event.isCancelled()), - event.setCancelled(result) + event.setCancelled(result); ); } case doHash("gmlib::PlayerStopSleepAfterEvent"): { @@ -200,15 +231,15 @@ void Export_Event_API() { GMLIB::Event::EntityEvent::EndermanTakeBlockBeforeEvent, (Actor * mob, bool isCancelled), (&event.self(), event.isCancelled()), - event.setCancelled(result) + event.setCancelled(result); ); } case doHash("gmlib::DragonRespawnBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::DragonRespawnBeforeEvent, - (int64 uniqueId, bool isCancelled), - (event.getEnderDragon().id, event.isCancelled()), - event.setCancelled(result) + (bool isCancelled), + (event.isCancelled()), + event.setCancelled(result); ); } case doHash("gmlib::DragonRespawnAfterEvent"): { @@ -225,7 +256,7 @@ void Export_Event_API() { (&event.self(), event.getShooter() ? event.getShooter()->getOrCreateUniqueID().id : -1, event.isCancelled()), - event.setCancelled(result) + event.setCancelled(result); ); } case doHash("gmlib::ProjectileCreateAfterEvent"): { @@ -240,7 +271,7 @@ void Export_Event_API() { GMLIB::Event::EntityEvent::SpawnWanderingTraderBeforeEvent, (std::pair pos, bool isCancelled), ({event.getPos(), event.getRegion().getDimensionId()}, event.isCancelled()), - event.setCancelled(result) + event.setCancelled(result); ); } case doHash("gmlib::SpawnWanderingTraderAfterEvent"): { @@ -274,7 +305,7 @@ void Export_Event_API() { (int)requestAction.mDst.mSlot, event.isCancelled() ), - event.setCancelled(result), + event.setCancelled(result);, auto& requestAction = (ItemStackRequestActionTransferBase&)event.getRequestAction(); ); // clang-format on diff --git a/xmake.lua b/xmake.lua index 5a928d5..8452b4b 100644 --- a/xmake.lua +++ b/xmake.lua @@ -10,7 +10,7 @@ end -- Option 1: Use the latest version of LeviLamina released on GitHub. add_requires("levilaminalibrary") add_requires("legacyremotecall") -add_requires("gmlib 0.13.7") +add_requires("gmlib") -- Option 2: Use a specific version of LeviLamina released on GitHub. -- add_requires("levilamina x.x.x")