#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, ...) \ 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(eventId)) \ params; \ cancelFun \ } catch (...) {} \ }, \ ll::event::EventPriority(priority) \ ); \ return eventId void Export_Event_API() { RemoteCall::exportAs("GMLIB_Event_API", "removeListener", [](ll::event::ListenerId eventId) -> bool { return EventManager::getInstance().removeListener(eventId); }); RemoteCall::exportAs("GMLIB_Event_API", "hasListener", [](ll::event::ListenerId eventId) -> bool { return EventManager::getInstance().hasListener(eventId); }); 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; }); RemoteCall::exportAs( "GMLIB_Event_API", "emplaceListener", [](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, (), (), , ); } case doHash("gmlib::ClientLoginAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::PacketEvent::ClientLoginAfterEvent, (std::string const& realName, std::string const& uuid, std::string const& serverXuid, std::string const& clientXuid), (event.getRealName(), event.getUuid().asString(), event.getServerAuthXuid(), event.getClientAuthXuid()), if (result) event.disConnectClient(); ); } case doHash("gmlib::WeatherUpdateBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::LevelEvent::WeatherUpdateBeforeEvent, (float rainLevel, int rainTime, float lightningLevel, int lightningTime, bool isCancelled), (event.getRainLevel(), event.getRainingLastTick(), event.getLightningLevel(), event.getLightningLastTick(), event.isCancelled()), event.setCancelled(result); ); } case doHash("gmlib::WeatherUpdateAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::LevelEvent::WeatherUpdateAfterEvent, (float rainLevel, int rainTime, float lightningLevel, int lightningTime), (event.getRainLevel(), event.getRainingLastTick(), event.getLightningLevel(), event.getLightningLastTick()), , ); } case doHash("gmlib::MobPickupItemBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::MobPickupItemBeforeEvent, (Actor * mob, Actor * item, bool isCancelled), (&event.self(), (Actor*)&event.getItemActor(), event.isCancelled()), event.setCancelled(result); ); } case doHash("gmlib::MobPickupItemAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::MobPickupItemAfterEvent, (Actor * mob, Actor * item), (&event.self(), (Actor*)&event.getItemActor()), , ); } case doHash("gmlib::ItemActorSpawnBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::ItemActorSpawnBeforeEvent, (ItemStack * item, std::pair position, int64 spawnerUniqueId, bool isCancelled), (&event.getItem(), {event.getPosition(), event.getBlockSource().getDimensionId().id}, event.getSpawner().has_value() ? event.getSpawner()->getOrCreateUniqueID().id : -1, event.isCancelled()), event.setCancelled(result); ); } case doHash("gmlib::ItemActorSpawnAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::ItemActorSpawnAfterEvent, (Actor * item, std::pair position, int64 spawnerUniqueId), (&event.self(), {event.getPosition(), event.getBlockSource().getDimensionId().id}, event.getSpawner().has_value() ? event.getSpawner()->getOrCreateUniqueID().id : -1), , ); } case doHash("gmlib::ActorChangeDimensionBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::ActorChangeDimensionBeforeEvent, (Actor * entity, int toDimId, bool isCancelled), (&event.self(), event.getToDimensionId(), event.isCancelled()), event.setCancelled(result); ); } case doHash("gmlib::ActorChangeDimensionAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::ActorChangeDimensionAfterEvent, (Actor * entity, int fromDimId, int toDimId), (&event.self(), event.getFromDimensionId(), event.getToDimensionId()), , ); } case doHash("gmlib::PlayerStartSleepBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::PlayerEvent::PlayerStartSleepBeforeEvent, (Player * entity, BlockPos pos, bool isCancelled), (&event.self(), event.getPosition(), event.isCancelled()), event.setCancelled(result); ); } case doHash("gmlib::PlayerStartSleepAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::PlayerEvent::PlayerStartSleepAfterEvent, (Player * entity, BlockPos pos, int result), (&event.self(), event.getPosition(), (int)event.getResult()), , ); } case doHash("gmlib::PlayerStopSleepBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::PlayerEvent::PlayerStopSleepBeforeEvent, (Player * entity, bool forcefulWakeUp, bool updateLevelList, bool isCancelled), (&event.self(), event.isForcefulWakeUp(), event.isUpdateLevelList(), event.isCancelled()), event.setCancelled(result); ); } case doHash("gmlib::PlayerStopSleepAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::PlayerEvent::PlayerStopSleepAfterEvent, (Player * entity, bool forcefulWakeUp, bool updateLevelList, bool), (&event.self(), event.isForcefulWakeUp(), event.isUpdateLevelList(), false), , ); } case doHash("gmlib::DeathMessageAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::DeathMessageAfterEvent, (std::string const& message, std::vector, Actor* dead), (event.getDeathMessage().first, event.getDeathMessage().second, &event.self()), , ); } case doHash("gmlib::MobHurtAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::MobHurtAfterEvent, (Actor * mob, Actor * source, float damage, int cause), (&event.self(), source, -event.getDamage(), (int)damageSource.getCause()), , auto& damageSource = event.getSource(); Actor* source = nullptr; if (damageSource.isEntitySource()) { auto uniqueId = damageSource.getDamagingEntityUniqueID(); source = ll::service::getLevel()->fetchEntity(uniqueId); if (source->getOwner()) source = source->getOwner(); } ); } case doHash("gmlib::EndermanTakeBlockBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::EndermanTakeBlockBeforeEvent, (Actor * mob, bool isCancelled), (&event.self(), event.isCancelled()), event.setCancelled(result); ); } case doHash("gmlib::DragonRespawnBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::DragonRespawnBeforeEvent, (bool isCancelled), (event.isCancelled()), event.setCancelled(result); ); } case doHash("gmlib::DragonRespawnAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::DragonRespawnAfterEvent, (Actor * mob), (event.getEnderDragon()), ); } case doHash("gmlib::ProjectileCreateBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::ProjectileCreateBeforeEvent, (Actor * mob, int64 uniqueId, bool isCancelled), (&event.self(), event.getShooter() ? event.getShooter()->getOrCreateUniqueID().id : -1, event.isCancelled()), event.setCancelled(result); ); } case doHash("gmlib::ProjectileCreateAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::ProjectileCreateAfterEvent, (Actor * mob, int64 uniqueId), (&event.self(), event.getShooter() ? event.getShooter()->getOrCreateUniqueID().id : -1), ); } case doHash("gmlib::SpawnWanderingTraderBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::SpawnWanderingTraderBeforeEvent, (std::pair pos, bool isCancelled), ({event.getPos(), event.getRegion().getDimensionId()}, event.isCancelled()), event.setCancelled(result); ); } case doHash("gmlib::SpawnWanderingTraderAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::SpawnWanderingTraderAfterEvent, (std::pair pos), ({event.getPos(), event.getRegion().getDimensionId()}), ); } case doHash("gmlib::HandleRequestActionBeforeEvent"): { // clang-format off REGISTER_EVENT_LISTEN( GMLIB::Event::PlayerEvent::HandleRequestActionBeforeEvent, ( Player * player, std::string const& actionType, int count, std::string const& sourceContainerNetId, int sourceSlot, std::string const& destinationContainerNetId, int destinationSlot, bool isCancelled ), ( (Player*)&event.self(), magic_enum::enum_name(requestAction.mActionType).data(), (int)requestAction.mAmount, magic_enum::enum_name(requestAction.mSrc.mOpenContainerNetId).data(), (int)requestAction.mSrc.mSlot, magic_enum::enum_name(requestAction.mDst.mOpenContainerNetId).data(), (int)requestAction.mDst.mSlot, event.isCancelled() ), event.setCancelled(result);, auto& requestAction = (ItemStackRequestActionTransferBase&)event.getRequestAction(); ); // clang-format on } case doHash("gmlib::HandleRequestActionAfterEvent"): { // clang-format off REGISTER_EVENT_LISTEN( GMLIB::Event::PlayerEvent::HandleRequestActionAfterEvent, ( Player * player, std::string const& actionType, int count, std::string const& sourceContainerNetId, int sourceSlot, std::string const& destinationContainerNetId, int destinationSlot ), ( (Player*)&event.self(), magic_enum::enum_name(requestAction.mActionType).data(), (int)requestAction.mAmount, magic_enum::enum_name(requestAction.mSrc.mOpenContainerNetId).data(), (int)requestAction.mSrc.mSlot, magic_enum::enum_name(requestAction.mDst.mOpenContainerNetId).data(), (int)requestAction.mDst.mSlot ), , auto& requestAction = (ItemStackRequestActionTransferBase&)event.getRequestAction(); ); // clang-format on } case doHash("gmlib::ContainerClosePacketSendAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::PacketEvent::ContainerClosePacketSendAfterEvent, (Player * player, int containerId, bool serverInitiatedClose, bool), (event.getServerNetworkHandler() .getServerPlayer(event.getNetworkIdentifier(), event.getPacket().mClientSubId), (int)event.getPacket().mContainerId, event.getPacket().mServerInitiatedClose, false), , ); } } return -1; } ); }