From 802ad261aae4377b02a9881522406aedbcbf5b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=90=E6=B2=90=E5=91=80?= <163636894+zimuya4153@users.noreply.github.com> Date: Sat, 16 Nov 2024 17:33:37 +0800 Subject: [PATCH] refactor: Rewrites the event API --- lib/EventAPI-JS.d.ts | 1074 +++++++++++++++++++++++++++++++++--------- lib/EventAPI-JS.js | 191 +++++++- src/EventAPI.cpp | 416 +++++++++------- 3 files changed, 1272 insertions(+), 409 deletions(-) diff --git a/lib/EventAPI-JS.d.ts b/lib/EventAPI-JS.d.ts index b8654bc..5b869f2 100644 --- a/lib/EventAPI-JS.d.ts +++ b/lib/EventAPI-JS.d.ts @@ -1,251 +1,897 @@ -/** 事件监听接口 */ -declare class Event { - /** 生物捡起物品 */ - static listen( +export namespace Event { + /** 事件优先级 */ + export enum EventPriority { + /** 最高 */ + Highest = 0, + /** 高 */ + High = 100, + /** 正常(推荐) */ + Normal = 200, + /** 低 */ + Low = 300, + /** 最低 */ + Lowest = 400 + } + + /** 获取所有事件订阅 */ + export function getListener(): Record; + + /** 获取事件订阅列表 */ + export function getListener( /** 事件名 */ - event: "onMobDie", - /** 监听函数 */ - listener: ( - /** 尝试捡起物品的实体对象 */ - entity: Entity, - /** 掉落物实体对象 */ - itemEntity: Entity - ) => boolean | void + eventName: + "ll::ServerStoppingEvent" + | "gmlib::ClientLoginAfterEvent" + | "gmlib::WeatherUpdateBeforeEvent" + | "gmlib::MobPickupItemBeforeEvent" + | "gmlib::ItemActorSpawnBeforeEvent" + | "gmlib::ItemActorSpawnAfterEvent" + | "gmlib::ActorChangeDimensionBeforeEvent" + | "gmlib::PlayerStopSleepBeforeEvent" + | "gmlib::DeathMessageAfterEvent" + | "gmlib::MobHurtAfterEvent" + | "gmlib::EndermanTakeBlockBeforeEvent" + | "gmlib::ActorChangeDimensionAfterEvent" + | "gmlib::DragonRespawnBeforeEvent" + | "gmlib::ProjectileCreateBeforeEvent" + | "gmlib::ProjectileCreateAfterEvent" + | "gmlib::SpawnWanderingTraderBeforeEvent" + | "gmlib::HandleRequestActionBeforeEvent" + | "gmlib::ContainerClosePacketSendAfterEvent" + ): number[]; + + /** 订阅事件是否存在 */ + export function hasListener( + /** 事件ID */ + eventId: number ): boolean; - /** 客户端登录后事件(不可以拦截) */ - static listen( - /** 事件名 */ - event: "onClientLogin", - /** 监听函数 */ - listener: ( - /** 玩家的游戏名字 */ - realName: string, - /** 玩家的uuid */ - uuid: string, - /** 玩家在服务端的xuid */ - serverXuid: string, - /** 玩家在客户端的xuid */ - clientXuid: string + /** 取消事件订阅 */ + export function removeListener( + /** 事件ID */ + eventId: number + ): boolean; + + /** 获取订阅事件优先级 */ + export function getListenerPriority( + /** 事件ID */ + eventId: number + ): EventPriority | undefined; + + /** 设置事件异常处理回调 */ + export function setErrorHanlerCallback( + /** 回调 */ + callback: ( + /** 错误 */ + error: Error, + /** 事件名 */ + eventName: string, + /** 事件ID */ + eventId: number, + /** 插件名 */ + pluginName: string ) => void ): boolean; - /** 天气改变事件事件 */ - static listen( + /** 监听事件(兼容旧版) */ + export function listen( /** 事件名 */ - event: "onWeatherChange", - /** 监听函数 */ - listener: ( - /** 雷暴天气等级 */ - lightningLevel: number, - /** 雨天天气等级 */ - rainLevel: number, - /** 雷暴持续时间(刻) */ - lightningLastTick: number, - /** 雨天持续时间(刻) */ - rainingLastTick: number - ) => boolean | void + eventName: "onServerStopping" + | "onClientLogin" + | "onWeatherChange" + | "onMobPick" + | "onItemTrySpawn" + | "onItemSpawned" + | "onEntityTryChangeDim" + | "onLeaveBed" + | "onDeathMessage" + | "onMobHurted" + | "onEndermanTake" + | "onEntityChangeDim" + | "onDragonRespawn" + | "onProjectileTryCreate" + | "onProjectileCreate" + | "onSpawnWanderingTrader" + | "onHandleRequestAction" + | "onSendContainerClosePacket", + /** 回调 */ + callback: Function ): boolean; - /** 掉落物尝试生成 */ - static listen( - event: "onItemTrySpawn", - listener: ( - /** 物品对象 */ - item: Item, - /** 尝试生成的坐标对象 */ - pos: FloatPos, - /** 创建掉落物的实体uniqueId */ - spawnerUniqueId: number - ) => boolean | void - ): boolean; - - /** 掉落物生成完毕(不可以拦截) */ - static listen( + /** 订阅事件 */ + export function emplaceListener( /** 事件名 */ - event: "onItemSpawned", - /** 回调函数 */ - listener: ( - /** 物品对象 */ - item: Item, - /** 掉落物实体对象 */ - entity: Entity, - /** 实体生成的坐标 */ - pos: FloatPos, - /** 创建掉落物的实体uniqueId */ - spawnerUniqueId: number - ) => void - ): boolean; + eventName: string, + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: any[], + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 实体切换维度 */ - static listen( + /** 订阅事件(服务器关闭事件) */ + export function emplaceListener( /** 事件名 */ - event: "onEntityTryChangeDim", - /** 回调函数 */ - listener: ( - /** 切换维度的实体对象 */ - entity: Entity, - /** 前往到的维度ID */ - dimid: number - ) => boolean | void - ): boolean; + eventName: "ll::ServerStoppingEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: {}, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 实体切换维度后(不可拦截) */ - static listen( + /** 订阅事件(客户端登录后事件) */ + export function emplaceListener( /** 事件名 */ - event: "onEntityChangeDim", - /** 回调函数 */ - listener: ( - /** 切换维度的实体对象 */ - entity: Entity, - /** 前往到的维度ID */ - fromDimid: number - ) => void - ): boolean; + eventName: "gmlib::ClientLoginAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 玩家名 */ + 0: string, + /** 玩家uuid */ + 1: string, + /** 玩家服务端xuid */ + 2: string, + /** 玩家客户端xuid */ + 3: string, + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 玩家下床 */ - static listen( + /** 订阅事件(天气更新前事件) */ + export function emplaceListener( /** 事件名 */ - event: "onLeaveBed", - /** 回调函数 */ - listener: ( - /** 下床的玩家对象 */ - player: Player - ) => boolean | void - ): boolean; + eventName: "gmlib::WeatherUpdateBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 雨天等级 */ + 0: number, + /** 雨天时间(tick) */ + 1: number, + /** 暴雨等级 */ + 2: number, + /** 暴雨时间(tick) */ + 3: number, + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 触发死亡信息(不可以拦截) */ - static listen( + /** 订阅事件(天气更新后事件) */ + export function emplaceListener( /** 事件名 */ - event: "onDeathMessage", - /** 回调函数 */ - listener: ( - /** 死亡信息键名 */ - deathMsgKey: string, - /** 死亡信息翻译参数 */ - deathMsgParams: string[], - /** 死亡实体的实体对象 */ - entity: Entity - ) => void - ): boolean; + eventName: "gmlib::WeatherUpdateAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 雨天等级 */ + 0: number, + /** 雨天时间(tick) */ + 1: number, + /** 暴雨等级 */ + 2: number, + /** 暴雨时间(tick) */ + 3: number, + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 实体受伤后事件 */ - static listen( + /** 订阅事件(实体捡起物品前事件) */ + export function emplaceListener( /** 事件名 */ - event: "onMobHurted", - /** 回调函数 */ - listener: ( - /** 受伤的实体对象 */ - entity: Entity, - /** 造成伤害的实体对象 */ - source: Entity, - /** 伤害值 */ - damage: number, - /** 伤害类型 */ - cause: number - ) => void - ): boolean; + eventName: "gmlib::MobPickupItemBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 捡起物品的实体 */ + 0: Entity, + /** 掉落物 */ + 1: Entity + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 末影人搬起方块 */ - static listen( + /** 订阅事件(实体捡起物品后事件) */ + export function emplaceListener( /** 事件名 */ - event: "onEndermanTake", - /** 回调函数 */ - listener: ( - /** 末影人实体对象 */ - entity: Entity - ) => boolean | void - ): boolean; + eventName: "gmlib::MobPickupItemAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 捡起物品的实体 */ + 0: Entity, + /** 掉落物 */ + 1: Entity + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 末影龙重生事件 */ - static listen( + /** 订阅事件(掉落物生成前事件) */ + export function emplaceListener( /** 事件名 */ - event: "onDragonRespawn", - /** 回调函数 */ - listener: ( - /** 末影龙重生后的UniqueID */ - uniqueID: number - ) => boolean | void - ): boolean; + eventName: "gmlib::ItemActorSpawnBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 物品 */ + 0: Item, + /** 生成坐标坐标 */ + 1: FloatPos, + /** 生成此物品主人的uniqueId (-1为不存在) */ + 2: number + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 弹射物实体尝试创建 */ - static listen( + /** 订阅事件(掉落物生成后事件) */ + export function emplaceListener( /** 事件名 */ - event: "onProjectileTryCreate", - /** 回调函数 */ - listener: ( - /** 弹射物实体对象 */ - entity: Entity, - /** 创建弹射的实体的uniqueID */ - uniqueId: number - ) => boolean | void - ): boolean; + eventName: "gmlib::ItemActorSpawnAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 物品 */ + 0: Item, + /** 生成坐标坐标 */ + 1: FloatPos, + /** 生成此物品主人的uniqueId (-1为不存在) */ + 2: number + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 弹射物实体成功后(不可拦截) */ - static listen( + /** 订阅事件(实体切换维度前事件) */ + export function emplaceListener( /** 事件名 */ - event: "onProjectileCreate", - /** 回调函数 */ - listener: ( - /** 弹射物实体对象 */ - entity: Entity, - /** 创建弹射的实体的uniqueID */ - uniqueId: number - ) => void - ): boolean; + eventName: "gmlib::ActorChangeDimensionBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 切换维度的实体 */ + 0: Entity, + /** 前往的维度ID */ + 1: number + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 生成流浪商人 */ - static listen( + /** 订阅事件(事件切换维度后事件) */ + export function emplaceListener( /** 事件名 */ - event: "onSpawnWanderingTrader", - /** 回调函数 */ - listener: ( - /** 生成的坐标 */ - pos: IntPos - ) => boolean | void - ): boolean; + eventName: "gmlib::ActorChangeDimensionAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 切换维度的实体 */ + 0: Entity, + /** 原来的维度ID */ + 1: number, + /** 前往的维度ID */ + 2: number + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 处理物品请求 */ - static listen( + /** 订阅事件(玩家开始睡觉前事件) */ + export function emplaceListener( /** 事件名 */ - event: "onHandleRequestAction", - /** 回调函数 */ - listener: ( - /** 请求玩家 */ - player: Player, - /** 请求类型 */ - actionType: string, - /** 请求数量 */ - count: number, - /** 第一个格子的容器类型 */ - sourceContainerNetId: string, - /** 第一个格子的槽位 */ - sourceSlot: number, - /** 第二个格子的容器类型 */ - destinationContainerNetId: string, - /** 第二个格子的槽位 */ - destinationSlot: number - ) => boolean | void - ): boolean; + eventName: "gmlib::PlayerStartSleepBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 睡觉的玩家 */ + 0: Player, + /** 床的坐标 */ + 1: IntPos + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 发送容器关闭数据包后(不可拦截) */ - static listen( + /** 订阅事件(玩家开始睡觉后事件) */ + export function emplaceListener( /** 事件名 */ - event: "onSendContainerClosePacket", - /** 回调函数 */ - listener: ( - /** 要被关闭的玩家 */ - player: Player, - /** 容器ID */ - containerId: number - ) => void - ): boolean; + eventName: "gmlib::PlayerStartSleepAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 睡觉的玩家 */ + 0: Player, + /** 床的坐标 */ + 1: IntPos, + /** 睡觉的结果 */ + 2: number + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; - /** 关闭服务器(不可拦截) */ - static listen( + /** 订阅事件(玩家停止睡觉前事件) */ + export function emplaceListener( /** 事件名 */ - event: "onServerStopping", - /** 回调函数 */ - listener: () => void - ): boolean; + eventName: "gmlib::PlayerStopSleepBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 睡觉的玩家 */ + 0: Player, + /** forcefulWakeUp */ + 1: boolean, + /** updateLevelList */ + 2: boolean + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(玩家停止睡觉后事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::PlayerStopSleepAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 睡觉的玩家 */ + 0: Player, + /** forcefulWakeUp */ + 1: boolean, + /** updateLevelList */ + 2: boolean + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(生成死亡消息后事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::DeathMessageAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 键名 */ + 0: string, + /** 翻译参数 */ + 1: string[], + /** 死亡的实体 */ + 2: Entity + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(实体受伤后事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::MobHurtAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 受伤的实体 */ + 0: Entity, + /** 伤害来源 */ + 1: Entity, + /** 伤害值 */ + 2: number, + /** 伤害类型 */ + 3: DamageCause + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(末影人搬运方块前事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::EndermanTakeBlockBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 末影人实体 */ + 0: Entity + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(末影龙复活前事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::DragonRespawnBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 末影龙复活后的uniqueId */ + 0: number + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(末影龙复活后事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::DragonRespawnAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 末影人实体 */ + 0: Entity + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(投射物创建前事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::ProjectileCreateBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 投射物实体 */ + 0: Entity, + /** 创建投射物实体的uniqueId */ + 1: number + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(投射物创建后事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::ProjectileCreateAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 投射物实体 */ + 0: Entity, + /** 创建投射物实体的uniqueId */ + 1: number + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(生成流浪商人前事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::SpawnWanderingTraderBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 出现的坐标 */ + 0: IntPos + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(生成流浪商人后事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::SpawnWanderingTraderAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 出现的坐标 */ + 0: IntPos + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(处理物品请求前事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::HandleRequestActionBeforeEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 请求的玩家 */ + 0: Player, + /** 请求类型 */ + 1: string, + /** 请求数量 */ + 2: number, + /** 请求原容器类型 */ + 3: string, + /** 请求原容器槽位 */ + 4: number, + /** 请求前往的容器类型 */ + 5: string, + /** 请求前往的槽位 */ + 6: number + }, + /** 拦截事件 */ + cancel: () => void, + /** 设置拦截状态 */ + setCancelled: ( + /** 是否拦截 */ + value: boolean + ) => void, + /** 是否被拦截 */ + isCancelled: () => boolean, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(处理物品请求后事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::HandleRequestActionAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 请求的玩家 */ + 0: Player, + /** 请求类型 */ + 1: string, + /** 请求数量 */ + 2: number, + /** 请求原容器类型 */ + 3: string, + /** 请求原容器槽位 */ + 4: number, + /** 请求前往的容器类型 */ + 5: string, + /** 请求前往的槽位 */ + 6: number + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; + + /** 订阅事件(玩家关闭容器后事件) */ + export function emplaceListener( + /** 事件名 */ + eventName: "gmlib::ContainerClosePacketSendAfterEvent", + /** 回调 */ + callback: (event: { + /** 事件参数 */ + params: { + /** 关闭的玩家 */ + 0: Player, + /** 容器会话ID */ + 1: number, + /** 由服务器关闭 */ + 2: boolean + }, + /** 获取事件ID */ + getId: () => number, + /** 获取事件类型 */ + getEventType: () => string + }) => void, + /** 优先级 */ + priority?: Event.EventPriority, + /** 插件名 */ + pluginName?: string + ): number; } \ No newline at end of file diff --git a/lib/EventAPI-JS.js b/lib/EventAPI-JS.js index 61a9c72..384bcc2 100644 --- a/lib/EventAPI-JS.js +++ b/lib/EventAPI-JS.js @@ -1,28 +1,169 @@ -/** 事件创建函数 @type {function(string,string):boolean} */ -const CallEvent = ll.import("GMLIB_Event_API", "callCustomEvent"); -/** 获取事件ID函数 @type {function():string} */ -const getNextEventId = ll.import("GMLIB_Event_API", "getNextScriptEventId"); - -/** 事件类 */ -class Event { - constructor() { throw new Error("Static class cannot be instantiated"); } - - /** - * 监听事件 - * @param {string} event 事件名称 - * @param {function} callback 回调 - * @returns {boolean} 是否创建成功 - */ - static listen(event, callback) { - let eventId = getNextEventId(); - ll.export(callback, event, eventId); - let result = CallEvent(event, eventId); - if (!result) { - logger.error(`Cannot listen event "${event}" !`); - logger.error(`GMLIB Script Event "${event}" does not exist !`); - } - return result; +/** + * @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 }; \ No newline at end of file +module.exports = { + Event: { + /** + * 事件订阅记录 + * 例如: {事件名: [事件ID, ...], ...} + * @type {Object.} + */ + 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.} + */ + 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 + } + } +}; \ No newline at end of file diff --git a/src/EventAPI.cpp b/src/EventAPI.cpp index c040bb9..fbdbc3f 100644 --- a/src/EventAPI.cpp +++ b/src/EventAPI.cpp @@ -1,249 +1,325 @@ #include "Global.h" using namespace ll::hash_utils; -class LegacyScriptEventManager { -private: - int64 mNextEventId = 0; - std::unordered_map mEventListeners; - -public: - std::string getNextEventId() { - mNextEventId++; - return "GMLIB_EVENT_" + std::to_string(mNextEventId); - } - - void emplaceListener(std::string const& scriptEventId, ll::event::ListenerPtr listenerPtr) { - mEventListeners[doHash(scriptEventId)] = std::move(listenerPtr); - } - - void removeListener(std::string const& scriptEventId) { - ll::event::EventBus::getInstance().removeListener(mEventListeners[doHash(scriptEventId)]); - mEventListeners.erase(doHash(scriptEventId)); - } - -public: - static LegacyScriptEventManager& getInstance() { - static std::unique_ptr instance; - if (!instance) { - instance = std::make_unique(); - } - return *instance; - } -}; - -#define REGISTER_EVENT_LISTEN(eventType, callFunction, eventParams, cancelFunction, otherFunction) \ - eventManager.emplaceListener( \ - eventId, \ - eventBus.emplaceListener([eventName, eventId, &eventBus, &eventManager](eventType& ev) -> void { \ - if (!RemoteCall::hasFunc(eventName, eventId)) { \ - eventManager.removeListener(eventId); \ +#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)); \ return; \ } \ - bool result = true; \ try { \ - otherFunction; \ - result = RemoteCall::importAs(eventName, eventId) eventParams; \ + __VA_ARGS__ \ + auto result = RemoteCall::importAs( \ + pluginName, \ + eventName + "_" + std::to_string(mEventIds.at(eventId)) \ + ) params; \ + cancelFun; \ } catch (...) {} \ - if (!result) cancelFunction; \ - }) \ + }, \ + ll::event::EventPriority(priority) \ ); \ - return true; + mEventIds[mEventIds.size()] = eventPtr->getId(); \ + return (llong)eventPtr->getId() void Export_Event_API() { - RemoteCall::exportAs("GMLIB_Event_API", "getNextScriptEventId", []() -> std::string { - return LegacyScriptEventManager::getInstance().getNextEventId(); + 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); }); - auto& eventBus = ll::event::EventBus::getInstance(); - auto& eventManager = LegacyScriptEventManager::getInstance(); + + RemoteCall::exportAs("GMLIB_Event_API", "hasListener", [&eventBus](ll::event::ListenerId eventId) -> bool { + return eventBus.hasListener(eventId); + }); + + RemoteCall::exportAs("GMLIB_Event_API", "getListenerPriority", [&eventBus](ll::event::ListenerId eventId) -> int { + if (auto event = eventBus.getListener(eventId); event != nullptr) { + return (int)event->getPriority(); + } + return -1; + }); + RemoteCall::exportAs( "GMLIB_Event_API", - "callCustomEvent", - [&eventBus, &eventManager](std::string const& eventName, std::string const& eventId) -> bool { - if (!RemoteCall::hasFunc(eventName, eventId)) return false; + "emplaceListener", + [&eventBus](std::string const& pluginName, std::string const& eventName, int priority) -> llong { switch (doHash(eventName)) { - case doHash("onClientLogin"): { + 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), - (ev.getRealName(), ev.getUuid().asString(), ev.getServerAuthXuid(), ev.getClientAuthXuid()), - logger.error("Event \"onClientLogin\" cannot be intercepted"), - ) + (event.getRealName(), + event.getUuid().asString(), + event.getServerAuthXuid(), + event.getClientAuthXuid()), + if (result) event.disConnectClient() + ); } - case doHash("onWeatherChange"): { + case doHash("gmlib::WeatherUpdateBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::LevelEvent::WeatherUpdateBeforeEvent, - (int lightningLevel, int rainLevel, int lightningLast, int rainLast), - (ev.getLightningLevel(), ev.getRainLevel(), ev.getLightningLastTick(), ev.getRainingLastTick()), - ev.cancel(), - ) + (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("onMobPick"): { + 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), - (&ev.self(), (Actor*)&ev.getItemActor()), - ev.cancel(), - ) + (Actor * mob, Actor * item, bool isCancelled), + (&event.self(), (Actor*)&event.getItemActor(), event.isCancelled()), + event.setCancelled(result) + ); } - case doHash("onItemTrySpawn"): { + 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, - (const ItemStack* item, std::pair position, int64 spawnerUniqueId), - (&ev.getItem(), - {ev.getPosition(), ev.getBlockSource().getDimensionId().id}, - ev.getSpawner().has_value() ? ev.getSpawner()->getOrCreateUniqueID().id : -1), - ev.cancel(), - ) + (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("onItemSpawned"): { + case doHash("gmlib::ItemActorSpawnAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::ItemActorSpawnAfterEvent, - (const ItemStack* item, Actor* itemActor, std::pair position, int64 spawnerUniqueId), - (&ev.getItem(), - (Actor*)&ev.getItemActor(), - {ev.getPosition(), ev.getBlockSource().getDimensionId().id}, - ev.getSpawner().has_value() ? ev.getSpawner()->getOrCreateUniqueID().id : -1), - logger.error("Event \"onItemSpawned\" cannot be intercepted"), - ) + (ItemStack * item, std::pair position, int64 spawnerUniqueId), + (&event.getItem(), + {event.getPosition(), event.getBlockSource().getDimensionId().id}, + event.getSpawner().has_value() ? event.getSpawner()->getOrCreateUniqueID().id : -1), + , + ); } - case doHash("onEntityTryChangeDim"): { + case doHash("gmlib::ActorChangeDimensionBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::ActorChangeDimensionBeforeEvent, - (Actor * entity, int toDimId), - (&ev.self(), ev.getToDimensionId()), - ev.cancel(), - ) + (Actor * entity, int toDimId, bool isCancelled), + (&event.self(), event.getToDimensionId(), event.isCancelled()), + event.setCancelled(result) + ); } - case doHash("onLeaveBed"): { + 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 * pl), - (&ev.self()), - ev.cancel(), - ) + (Player * entity, bool forcefulWakeUp, bool updateLevelList, bool isCancelled), + (&event.self(), event.isForcefulWakeUp(), event.isUpdateLevelList(), event.isCancelled()), + event.setCancelled(result) + ); } - case doHash("onDeathMessage"): { + 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), - (ev.getDeathMessage().first, ev.getDeathMessage().second, &ev.self()), - logger.error("Event \"onDeathMessage\" cannot be intercepted"), - ) + (event.getDeathMessage().first, event.getDeathMessage().second, &event.self()), + , + ); } - case doHash("onMobHurted"): { + case doHash("gmlib::MobHurtAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::MobHurtAfterEvent, (Actor * mob, Actor * source, float damage, int cause), - (&ev.self(), source, ev.getDamage(), (int)damageSource.getCause()), - logger.error("Event \"onMobHurted\" cannot be intercepted"), - auto& damageSource = ev.getSource(); + (&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("onEndermanTake"): { + case doHash("gmlib::EndermanTakeBlockBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::EndermanTakeBlockBeforeEvent, - (Actor * mob), - (&ev.self()), - ev.cancel(), - ) + (Actor * mob, bool isCancelled), + (&event.self(), event.isCancelled()), + event.setCancelled(result) + ); } - case doHash("onEntityChangeDim"): { - REGISTER_EVENT_LISTEN( - GMLIB::Event::EntityEvent::ActorChangeDimensionAfterEvent, - (Actor * mob, int fromDimId), - (&ev.self(), ev.getFromDimensionId()), - logger.error("Event \"onEntityChangeDim\" cannot be intercepted"), - ) - } - case doHash("onDragonRespawn"): { + case doHash("gmlib::DragonRespawnBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::DragonRespawnBeforeEvent, - (int64 enderDragonUniqueID), - (ev.getEnderDragon().id), - ev.cancel(), - ) + (int64 uniqueId, bool isCancelled), + (event.getEnderDragon().id, event.isCancelled()), + event.setCancelled(result) + ); } - case doHash("onProjectileTryCreate"): { + 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), - (&ev.self(), ev.getShooter() ? ev.getShooter()->getOrCreateUniqueID().id : -1), - ev.cancel(), - ) + (Actor * mob, int64 uniqueId, bool isCancelled), + (&event.self(), + event.getShooter() ? event.getShooter()->getOrCreateUniqueID().id : -1, + event.isCancelled()), + event.setCancelled(result) + ); } - case doHash("onProjectileCreate"): { + case doHash("gmlib::ProjectileCreateAfterEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::ProjectileCreateAfterEvent, (Actor * mob, int64 uniqueId), - (&ev.self(), ev.getShooter() ? ev.getShooter()->getOrCreateUniqueID().id : -1), - logger.error("Event \"onProjectileCreate\" cannot be intercepted"), - ) + (&event.self(), event.getShooter() ? event.getShooter()->getOrCreateUniqueID().id : -1), + ); } - case doHash("onSpawnWanderingTrader"): { + case doHash("gmlib::SpawnWanderingTraderBeforeEvent"): { REGISTER_EVENT_LISTEN( GMLIB::Event::EntityEvent::SpawnWanderingTraderBeforeEvent, - (std::pair pos), - ({ev.getPos(), ev.getRegion().getDimensionId()}), - ev.cancel(), - ) + (std::pair pos, bool isCancelled), + ({event.getPos(), event.getRegion().getDimensionId()}, event.isCancelled()), + event.setCancelled(result) + ); } - case doHash("onHandleRequestAction"): { - // clang-format off + case doHash("gmlib::SpawnWanderingTraderAfterEvent"): { 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 - ), - ( - (Player*)&ev.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 - ), - ev.cancel(), - auto& requestAction = (ItemStackRequestActionTransferBase&)ev.getRequestAction(); - ) + 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("onSendContainerClosePacket"): { + 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 ContainerNetId), - (ev.getServerNetworkHandler() - .getServerPlayer(ev.getNetworkIdentifier(), ev.getPacket().mClientSubId), - (int)ev.getPacket().mContainerId), - logger.error("Event \"onSendContainerClosePacket\" cannot be intercepted"), - ) + (Player * player, int containerId, bool serverInitiatedClose, bool), + (event.getServerNetworkHandler() + .getServerPlayer(event.getNetworkIdentifier(), event.getPacket().mClientSubId), + (int)event.getPacket().mContainerId, + event.getPacket().mServerInitiatedClose, + false), + , + ); } - case doHash("onServerStopping"): { - REGISTER_EVENT_LISTEN( - ll::event::server::ServerStoppingEvent, - (), - (), - logger.error("Event \"onServerStopping\" cannot be intercepted"), - ) - } - default: - return false; } + return -1; } ); } \ No newline at end of file