zh

事件监听

事件是PNX中插件执行工作的主要方式之一,本章节将通过带您制作一个简单的屏蔽词插件带您学会使用PNX-JS进行事件监听。

什么是事件

每当服务器中发生了特定的行为,一个事件对象就会产生。事件是对某种行为或动作的描述,比如玩家登录、 玩家离开、玩家发送消息等等。种种的行为或动作都对应一个事件对象作为它们的抽象,事件对象中带有这个行为或者动作中的一些 关键信息,比如玩家发送消息事件对象中就带有发送事件的玩家对象、发送的消息字符串等等,而玩家对象又包含这个玩家的 位置、生命值、物品栏等等数据。

插件可以向PNX注册监听器来在事件发生的时候做出反应。每个事件对象都包含了对事件的描述,通常事件监听器会在事件发生之前被调用, 此时监听器可以通过取消事件来阻止事件真的发生,如果没有任何事件监听器取消了这个事件,那么它就会真正地在游戏内发生。 监听器的执行是单线程的,所有监听器在注册的时候都要给PNX提供它的优先级,PNX会按照优先级将监听器排序,然后依次执行监听器。 很可能在你的插件的监听器被执行之间这个事件已经被取消了,但通常这不会影响你的监听器的执行,你的监听器仍然会被执行,你可以通过 event.isCancelled()来判断事件是否被取消了(后面会详细讲解)。 特别注意的是,优先级越高,执行顺序越往后排。也就是说,优先级越低,越优先执行!
你问为啥不是优先级越高越优先?我也这么认为,但是NKX就是这样奇怪地设计的,为了兼容NK生态我们不得不做出这个反人类的妥协

监听器参与事件的过程如下面的流程如所示:

PNX事件流程图

PNX中提供了非常多事件,您可以在 事件对照表 中查看。表中每个事件都标注了类名, 您可以在插件中使用这个类名来监听这个事件,点击类名也可以进入对应的JavaDoc查看更多细节。

注册一个事件监听器

在PNX-JS中,注册事件监听器是通过:powernukkitx内置模块中的PowerNukkitX来执行的,下面提供了一个简单的模板:

import { PowerNukkitX, EventPriority } from ":powernukkitx"; // PowerNukkitX和EventPriority都是:powernukkitx内置模块中的

// 注册事件监听器只能在main函数中或者main函数执行完毕之后才可以
export function main() {
    PowerNukkitX.listenEvent("cn.nukkit.event.Event", //这里的字符串写事件的类名,在事件对照表中有
        EventPriority.NORMAL, // 监听器的优先级,有LOWEST LOW NORMAL HIGH HIGHEST MONITOR六级,LOW最先,MONITOR最后
        event => { // 这个箭头函数的event参数就是事件对象,类型即为上面你写的事件的类
        // 事件处理代码
    })
}

:powernukkitx模块提供了一系列服务器插件所需要的最基本功能函数,比如注册事件监听器,注册函数等等,具体内容可以看 powernukkitx内置模块JSDoc

实现禁止发出脏话的功能

这里,我们通过注册一个 cn.nukkit.event.player.PlayerChatEvent (玩家聊天事件) 来监听玩家在聊天框中发出消息的事件,并检测玩家是否发出了脏话,如果是,则取消事件,让玩家无法 发出这条带有脏话的消息。

export function main() {
    PowerNukkitX.listenEvent("cn.nukkit.event.player.PlayerChatEvent", EventPriority.NORMAL, event => {
        
    })
}

首先,我们应该判断事件是否已经取消,如果事件已经被其他插件取消了,我们就不需要再进行判断。

export function main() {
    PowerNukkitX.listenEvent("cn.nukkit.event.player.PlayerChatEvent", EventPriority.NORMAL, event => {
        if (event.isCancelled()) {
            return;
        }
    })
}

我们查阅玩家聊天事件的JavaDoc可知 (在事件对照表中可以点击链接) ,它继承自cn.nukkit.event.Event类,所以 它也拥有isCancelled函数 (查询这个事件是否已经取消)setCancelled函数 (取消这个事件)

JavaDoc中有如下部分:
从类继承的方法 cn.nukkit.event.Event
getEventName, isCancelled, setCancelled, setCancelled

接下来,我们获取事件中玩家发送的消息,判断其中是否有fuck这一脏话,如果有则取消这个事件。

export function main() {
    PowerNukkitX.listenEvent("cn.nukkit.event.player.PlayerChatEvent", EventPriority.NORMAL, event => {
        if (event.isCancelled()) {
            return;
        }
        if (event.getMessage().includes("fuck")) { // 检测消息中是否有fuck
            event.setCancelled();
        }
    })
}

查阅玩家聊天事件的JavaDoc可知,它有一个叫做getMessage的方法,根据我们之前说的望名知义的方法,分解为getMessage,即获取消息,连起来就是获取消息,JavaDoc上面说它返回String,就是字符串,我们就能大概确定, 这个函数可以从事件中获取玩家发送的消息。这样的过程不会再在以后赘述,希望你已经掌握了。

我们不仅要让玩家发不出去,而且还要让玩家知道自己不是网卡了而是因为被禁止发脏话了,我们要给玩家一些提示:

export function main() {
    PowerNukkitX.listenEvent("cn.nukkit.event.player.PlayerChatEvent", EventPriority.NORMAL, event => {
        if (event.isCancelled()) {
            return;
        }
        if (event.getMessage().includes("fuck")) {
            event.setCancelled();
            event.getPlayer().sendMessage("禁止说脏话");
        }
    })
}

查阅玩家聊天事件的JavaDoc可知getPlayer方法能返回这个事件的玩家,接下来,我们可以点击JavaDoc中的方法返回值, 那是指向返回值的类型的JavaDoc文档的链接,在 cn.nukkit.Player 也就是玩家类的JavaDoc中,我们找到了sendMessage函数,用于向玩家发送消息。PNX的设计哲学中,在对象上面使用的方法(函数) 通常只会对这个对象生效,也就是说我们对这个玩家对象使用sendMessage函数,只有这一个玩家能接受到消息。

至此,我们的插件就初步完成了,接下来我们需要编写plugin.yml等,并且将插件安装到服务器中进行测试。

安装插件并测试

编写plugin.yml很简单,你可以遵照 插件格式章节 中的内容来编写。 编写完成后,将你的js代码和yml文件复制到plugins文件夹下面一个以@加上你插件名字命名的文件夹中,重启服务器即可进服测试。

如果你在你的聊天框中输入fuck xxx,然后收到了一条禁止说脏话消息,那就说明你的插件成功了!

获取全部代码

本节所有的全部代码和完整插件可以在Github仓库 ObscenityDefender 中获取。


© PowerNukkitX 开发组