refactor: Simplify and optimize event handling and listener management

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