Skip to content
全文约 1118 字 预计阅读 4 分钟

自定义事件 ​

除 LeviLamina 与 Minecraft 原生事件外,LOICollectionA 还对外发布了 12 个自定义事件头文件(共 22 个事件类型),位于 src/LOICollectionA/include/server/Events/。它们都使用 ll::event::EventBus 发布,因此可以用与其他事件完全相同的方式监听。

NOTE

所有这些头文件都是服务端专用的。xmake.lua 在 client 目标下会通过 remove_headerfiles("src/LOICollectionA/include/(server/**.h)") 把它们从分发清单中移除。

事件总表 ​

头文件事件类型暴露的 Getter发布者触发时机
modules/BlacklistEvent.hBlacklistAddBeforeEventgetCause、getTimeEvents 适配器BlacklistPlugin::addBlacklist 执行前,可取消
modules/BlacklistEvent.hBlacklistAddAfterEventgetCause、getTimeEvents 适配器BlacklistPlugin::addBlacklist 执行后
modules/BlacklistEvent.hBlacklistRemoveEventgetTargetEvents 适配器BlacklistPlugin::delBlacklist 执行前,可取消
modules/MarketItemSoldEvent.hMarketItemSoldEventgetItemName、getPrice、getTax、getBuyerUuid、getSellerUuid、getTimeMarketPlugin一笔交易成交时(玩家商店、求购单与拍卖三个成交路径都会发布)
modules/MuteEvent.hMuteAddBeforeEventgetCause、getTimeEvents 适配器MutePlugin::addMute 执行前,可取消
modules/MuteEvent.hMuteAddAfterEventgetCause、getTimeEvents 适配器MutePlugin::addMute 执行后,可取消
modules/MuteEvent.hMuteRemoveEventgetTargetEvents 适配器MutePlugin::delMute 执行前,可取消
modules/NoticeEvent.hNoticeCreateEventgetTarget、getTitle、getPriority、isPoiontoutEvents 适配器NoticePlugin::create 执行前,可取消
modules/NoticeEvent.hNoticeDeleteEventgetTargetEvents 适配器NoticePlugin::remove 执行前,可取消
modules/RedEnvelopeCompletedEvent.hRedEnvelopeCompletedEventgetEnvelopeId、getSenderUuid、getKingUuid、getKingName、getKingAmount、getTotal、getTimeWalletPlugin一个红包被领完时
modules/WalletTransferEvent.hWalletTransferEventgetFromUuid、getFromName、getToUuid、getToName、getAmount、getFee、getType、getTimeWalletPlugin一笔转账或资金变动被记入台账时
player/PlayerContainerEvent.hPlayerOpenContainerEventgetPosition、getDimensionIdEvents 适配器玩家打开容器时,可取消
player/PlayerHurtEvent.hPlayerHurtEventgetSource、getDamage、isKnock、isIgnite、getReasonEvents 适配器玩家受到其他实体伤害时,可取消
player/PlayerScoreChangedEvent.hPlayerScoreChangedEventgetObjective、getScoreChangedType、getScoreEvents 适配器玩家计分板分数变化时,可取消
server/NetworkPacketEvent.hNetworkPacketBeforeEventgetNetworkIdentifier、getPacket、getSubClientId、getTypeEvents 适配器数据包发送 / 接收前后,可取消
server/NetworkPacketEvent.hNetworkPacketAfterEventgetNetworkIdentifier、getPacket、getSubClientId、getTypeEvents 适配器数据包发送 / 接收之后
server/NetworkPacketEvent.hNetworkBroadcastPacketEventgetPacketEvents 适配器广播数据包时,可取消
world/BlockExplodedEvent.hBlockExplodedEventgetPosition、getBlock、getDimensionId、getSourceEvents 适配器方块被爆炸破坏时
world/RedStoneEvent.hRedStoneEventgetPosition、getSource、getDimensionId、getStrength、isFirstTimeEvents 适配器红石线、红石火把、比较器或观察者发生红石更新时

NOTE

上表中的「Events 适配器」指 src/LOICollectionA/modules/server/Events/** 下的桥接实现。它们通过 LL_TYPE_INSTANCE_HOOK + ll::event::Emitter 自行注册,因此与模块开关无关:只要插件被加载,这些 hook 就已经生效。

事件的层次 ​

可取消事件 ​

多数事件继承 ll::event::Cancellable,监听器可以调用 event.cancel() 来阻止默认行为。是否真正生效取决于发布者的处理:

  • BlacklistAddBeforeEvent、BlacklistRemoveEvent、MuteAddBeforeEvent、MuteRemoveEvent、NoticeCreateEvent、NoticeDeleteEvent:取消后对应插件方法直接返回,不写入数据库
  • PlayerOpenContainerEvent、PlayerHurtEvent、PlayerScoreChangedEvent:取消后 hook 返回 EventResult::StopProcessing 或提前返回,原版行为被拦截
  • NetworkPacketBeforeEvent、NetworkBroadcastPacketEvent:取消后数据包不再发送

WARNING

BlacklistAddAfterEvent 与 MuteAddAfterEvent 在数据库写入已经完成之后发布,此时取消事件不会回滚已落库的数据。两者的基类并不一致:BlacklistAddAfterEvent 继承普通 PlayerEvent,而 MuteAddAfterEvent 继承 Cancellable<PlayerEvent>,因此它虽然可以调用 cancel(),但同样没有回滚效果。

不可取消事件 ​

以下事件只用于通知,无法拦截:MarketItemSoldEvent、RedEnvelopeCompletedEvent、WalletTransferEvent、BlockExplodedEvent、RedStoneEvent、NetworkPacketAfterEvent。

枚举参数 ​

三个事件带有可用来分支的枚举:

枚举取值所属事件
PlayerHurtReasonHurt、Effect、ProjectilePlayerHurtEvent
ScoreChangedTypeadd、reducePlayerScoreChangedEvent
NetworkPacketTypesend、receiveNetworkPacketBeforeEvent / NetworkPacketAfterEvent

监听事件 ​

cpp
void XxxPlugin::listenEvent() {
    ll::event::EventBus& eventBus = ll::event::EventBus::getInstance();

    this->mImpl->myListener = eventBus.emplaceListener<LOICollection::server::Events::PlayerScoreChangedEvent>(
        [this](LOICollection::server::Events::PlayerScoreChangedEvent& event) -> void {
            if (event.getScoreChangedType() == LOICollection::server::Events::ScoreChangedType::reduce)
                return;

            // event.cancel(); // 可取消事件才需要
        });
}

void XxxPlugin::unlistenEvent() {
    ll::event::EventBus::getInstance().removeListener(this->mImpl->myListener);
}

TIP

事件类型都位于 LOICollection::server::Events 命名空间下,头文件路径以 LOICollectionA/include/server/Events/ 开头,例如 #include "LOICollectionA/include/server/Events/player/PlayerScoreChangedEvent.h"。

WARNING

请务必在模块的 unregistry() 中调用 unlistenEvent(),否则模块被卸载后监听器仍会持有悬空的 this 指针。

相关文档 ​

LOICollectionA · 开箱即用的 LeviLamina 多功能插件集