Files
mengyanote/public/mengyanote/.trash/第二章-插件要素.md
2025-10-05 19:44:37 +08:00

7.7 KiB
Raw Blame History

上一章 下一章

第一部分 第二章 插件要素

参与编写者: MagicLu550

建议学习时间: 50分钟

学习要点: 了解nukkit的项目结构认识一些普通组件的定义和注册

插件要素这章会概括性的介绍nukkit的一些主要组件后面的章节将会对他们系统的介绍。

所有的插件式编程都有它的一套运行标准如maven插件,PocketMine插件以及我们的nukkit插件等。

我称插件的规则元素为一个插件的要素,主要是运行的主类所依托的父类或一个动作所依托的父类(PluginBase等),它 用于对服务器阅读的参数表(如web.xml,plugin.yml等),以及执行一系列动作的附件(如监听器,Servlet,过滤器,命令等)

nukkit的插件以PluginBase的代表,以plugin.yml为运行依据,以监听器等附件为动作,这些动作基于在PluginBase里 注册,所以nukkit的结构主要为这些

    1. plugin.yml [必须有]
    2. 继承于PluginBase的主类 [必须有]
    3. Listener(监听器),Command(命令),Timer(计时器)
    

nukkit允许主类和监听器重叠,当我们制作简单的插件,为避免复杂,可以一个类担当主类和监听器的角色 并且我们也可以使用简单的方式来执行我们的命令。复杂项目中,我们不建议这么做

  1. 注册一个监听器
package net.noyark.www;

import cn.nukkit.event.Listener;
import cn.nukkit.plugin.PluginBase;

/**
 * 实现一个Listener代表了一个监听器注册时监听器才真正生效
 * 另外,Listener是一个接口我们需要实现(implements)它
 */
public class Example extends PluginBase implements Listener {
    
    @Override
    public void onEnable() {
        //插件的管理由PluginManager实现后期会讲解这个组件
        //listener为一个监听器对象这里我们将服务器事先生成的主类对象传入
        //若要调用服务器生成的PluginBase对象我们必须要传入this而不是再new一个
        //当然注册监听器时您可以再new一个但是不建议这么做
        //第二个plugin对象是主类对象这个必须要传入this的
        //可能有人疑惑,那在其他类里该怎么调用之前生成的对象呢?这个疑惑将会在接下来代码实现
        this.getServer().getPluginManager().registerEvents(this,this);
    }
}

如果跨类如何做这件事? 我们这里定义了一个Example类和一个OtherListener类。 OtherListener实现了Listener接口。 如图所示实现了跨类的注册 2-01 那么如何实现在监听器使用实现注册好的主类对象? 下面代码解决了这个问题要注意plugin = this这段代码 要定义在监听器对象被定义之前这样定义一个getPlugin方法就可以在监听器获取到了

package net.noyark.www;


import cn.nukkit.plugin.PluginBase;

public class Example extends PluginBase{

    private static Example plugin;
    @Override
    public void onEnable() {
        plugin = this;
        this.getServer().getPluginManager().registerEvents(new OtherListener(),this);
    }

    public static Example getPlugin() {
        return plugin;
    }
}

在监听器中调用

package net.noyark.www;

import cn.nukkit.event.EventHandler;
import cn.nukkit.event.Listener;
import cn.nukkit.event.player.PlayerJoinEvent;

public class OtherListener implements Listener {
    
    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent e){
        Example.getPlugin().getServer();
    }
}

监听器具体内容将在后面讲解

  1. 注册一个命令 其实注册个命令就很简单,如何跨类等等和上面基本一样,但是主类是不能注册一个命令对象的 (因为命令是继承Command对象) 但是也有简便的方法

第一种: [1]

package net.noyark.www;


import cn.nukkit.command.Command;
import cn.nukkit.command.CommandSender;
import cn.nukkit.plugin.PluginBase;

public class Example extends PluginBase{

    private static Example plugin;
    @Override
    public void onEnable() {
        plugin = this;
        this.getServer().getPluginManager().registerEvents(new OtherListener(),this);
    }

    public static Example getPlugin() {
        return plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        //这里返回true代表执行成功false则不成功
        //sender 是发送命令的对象
        //command 命令对象
        // [1]
        //label 是标签如果注册命令时label为null就会默认为命令名label的组成是fallBackPrefix+:+label
        //label这个地方其实也不是很懂。一般注册时都是""或者null
        //通过源码推测label和fallBackPrefix的组合是命令的唯一标识
        //
        //args 命令参数,比如/hello 1 2的参数为1和2,存储在数组中
        //这里使用命令通过equals
        //如何得到指令名称个人习惯原因
        if("hello".equals(command.getName())){
            //执行相关操作
            return true;//最好加上
        }
        //这种方式虽然方便,但是命令多,且命令功能复杂时会难以维护
        //少部分命令可以使用它
        return true;
    }
}

当然第一种方式命令要真正被监听我们还要在plugin.yml里声明

permissions: #这个标签我们只写一次就ok了
  plugin.hello:
    description: 你好
    default: op #权限组,后期会讲到
commands: #这个标签我们只写一次就ok了
  hello:
    description: 你好
    usage: "/hello"
    permission: plugin.hello

第二种是创建命令类 这个其实不用多说,和前面一样使用

package net.noyark.www;

import cn.nukkit.command.Command;
import cn.nukkit.command.CommandSender;

public class MyCommand extends Command {

    //hello为指令名字,后面description是它的介绍其他功能将后期讲解
    public MyCommand() {
        super("hello","一个测试指令");
    }

    @Override
    public boolean execute(CommandSender commandSender, String label, String[] strings) {
        return true;
    }
}

注册很简单,第一个参数后面会讲解

package net.noyark.www;

import cn.nukkit.plugin.PluginBase;

public class Example extends PluginBase{
    
    @Override
    public void onEnable() {
        this.getServer().getCommandMap().register("",new MyCommand());
    }
    
}

3.计时器部分我们将在后面讲解,它的体系较复杂一些

计时器主要形同java的Runnable线程池等等他们本质也是实现多线程。 也是开发者使用最广泛的一类组件。

  1. 如何写plugin.yml plugin.yml第一章提到过plugin.yml最主要的是

     name: FirstPlugin             
     main: net.noyark.www.Example  
     version: "0.0.1"              
     author: myName
     api: ["1.0.8"]                
     description: My first plugin
    

snake1999曾说: 缺少他们的插件是不被nukkit运行的。 这些都是不能缺少的,在接下来章节中,将会系统的介绍里面常用的标签 目前从现在的维护者知悉api写什么其实并不重要因为nukkit向下兼容,不像 pocketMine一样变动很大,nukkit会淘汰掉过时的函数不会删除因此 可以保证老插件运行,但值得注意的是,不代表淘汰函数会完美运行,能 运行插件不代表不会出现bug但这也是相对pocketMine最方便的优势了。

上一章 下一章