如何制作Nukkit 插件

发表在    Nukkit 10-30 02:38:17

1 5995 4
来源:http://nukkit.ru/threads/99 (Nukkit 俄语社区)// 原标题:С чего начать создание плагинов // 原作者:fromgate // 原语言:俄语 // 译者:Snake1999
本教程为翻译俄语社区的帖子。原帖为系列教程,我翻译时统一在本帖整理,为方便阅读和理解,本文章经过译者重新排版并分页。为适合国(和谐)情,本教程部分语句按照国人习惯的方法来表达,详情请自行翻阅原文。教程内某些链接无法访问的,自备梯子,或者去其它途径搜索。为便于理解对原文补充的部分,因为语法的差异必须要修改的部分,还有译者的吐槽,会用灰色字体表达。特别说明:转载请联系作者,本翻译内容禁止某玩盒子、某芦侠、某戏狗等非 Nukkit 专门讨论区转载。                —— Snake1999


因为考虑到流量党,第一页不放图,全文纯文本超过三万字,篇幅过长,请翻页查看。如果俄语能力好的话,可以去原帖和原文作者交流。本教程使用电脑和 IntelliJ IDEA 作为开发环境,请不要问我手机/AIDE如何制作 Nukkit 插件,请自行搜索相关教程,这里不提供。

感谢各位提醒,图似乎裂了,稍后去修复已更换图床,图裂已修复,请大家放心浏览

WARNING:前方长文章高能,请无关人员迅速撤离!

==== 正文开始 ====
我写了几篇关于编写 Nukkit 教程的文章。我认为这能帮助一些 Nukkit 开发的新手,让他们可以踏出 Nukkit 插件开发的第一步。这个教程包含写作插件的教程,你可以为在公共场合发布而编写开源插件,也可以给你的服务器定制插件。

文章从这里开始:

1. 第一个插件
2. 使用配置文件
3. 事件处理
4. 命令和命令组

祝你好运!


原帖: http://www.mcbbs.net/thread-552265-1-1.html


登录或注册后发布评论
  • 本页文章来源:http://nukkit.ru/threads/98(Nukkit 俄语社区)// 原标题:С чего начать: Команды
    命令和命令组

    我们来继续提高我们的插件 - 添加能够输出信息的能力之后,我们还要能够检查玩家是否拥有某个权限 - 来做到检查这个玩家是否有权限执行这个指令。有时候,有些指令只有某些特定的玩家可以使用。



    1. 注册命令

    首先你需要告诉服务器你的插件拥有一个命令。可以有两种方式完成 - 在 plugin.yml 里编写,或者在复杂的情况下可以添加一个自己的命令组。我们使用在 plugin.yml 中的方法,因为在多数情况下这已经足够了。



    我们在 plugin.yml 中添加这些内容,来定义一个命令:


    1. commands:
    2.   news:
    3.     aliases: ["info"]
    4.     description: Show (and set current news)
    5.     usage: "/news [set <Anouncement>]"

    复制代码

    在这里做一些解释:


    • "news" - 指的是我们的命令组
    • "aliases" - 指的是这个命令所有的名称。需要注意的是,这应该是一个字符串的列表,我们就必须使用["alias1", "alias2"]这样的形式。
    • "description" - 指的是命令组的说明(会在服务器的 /help 菜单中显示)
    • "usage" - 这个命令的使用用法


    2. 添加代码

    如果这个插件的 plugin.yml 定义了一些命令组,Nukkit 会解析命令,并在调用时调用插件类中的 onCommand 方法。要在命令被执行时做出操作,需要重写这个方法:


    1.     @Override
    2.     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    3.     }

    复制代码

    这个方法的参数是这样的:


    • sender - 是谁调用了这个命令组
    • command - 这个命令组的 Command 对象
    • label - 这个命令组被执行时,所使用的命令名称。这里有可能会有同一个命令组以不同的名称显示。
    • args - 一个字符串数组,这将是所有的命令参数。


    所以我们要加入这个指令 /news,需要在聊天窗口输入不带参数的这个指令时,显示特定的文字;在带参数时,命令的发送者可以设置显示的文字。这种情况下,我们需要设置命令的权限,来防止有玩家把文字设置成广告。此外,检查权限不会伤害到被检查的玩家。代码这样写:


    1. @Override
    2.     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    3.         Player player = (sender instanceof Player) ? (Player) sender : null;
    4.         if (args.length==0){
    5.             if (player!=null&&!player.hasPermission("firstplugn.news.show"))
    6.                 sender.sendMessage(TextFormat.RED+"You have not enough permissions!");
    7.             else sender.sendMessage(TextFormat.colorize("&3[NEWS] &b"+this.helloMessage));
    8.         } else {
    9.             if (player!=null&&!player.hasPermission("firstplugn.news.set"))
    10.                 sender.sendMessage(TextFormat.RED+"You have not enough permissions!");
    11.             else {
    12.                 StringBuilder sb = new StringBuilder();
    13.                 for (String s : args) {
    14.                     if (sb.length() > 0) sb.append(" ");
    15.                     sb.append(s);
    16.                 }
    17.                 if (player != null) sb.append(" &3(").append(player.getName()).append(")");
    18.                 this.helloMessage = sb.toString();
    19.                 this.getConfig().set("hello-message",this.helloMessage);
    20.                 this.saveConfig();
    21.                 sender.sendMessage(TextFormat.colorize("&6You configured new announcement:"));
    22.                 sender.sendMessage(TextFormat.colorize("&3[NEWS] &b"+this.helloMessage));
    23.             }
    24.         }
    25.         return true;
    26.     }

    复制代码

    编译运行,启动,然后....



    祝贺!我们的插件正常工作!



    3. 多个指令

    需要注意的是,如果用 plugin.yml 定义的方法,定义多个指令时下面的代码将变得及其庞大并难以阅读,不建议在指令数量多的情况下使用 plugin.yml 的方法定义指令,这个方法只适用于少量的指令,而且是最基础的方法。下面演示的只是一个例子。

    1. @Override
    2.     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    3.         if (command.getLabel().equalsIgnoreCase("command1")){
    4.             // 执行指令 command1
    5.        
    6.         } else if (command.getLabel().equalsIgnoreCase("command2")){
    7.             // 执行指令 command2
    8.        
    9.         } else return false;
    10.         return true;
    11.     }

    复制代码

    插件注册大量的指令有其它的方法,这里不详细讲了,可以看 Command 类的 javadoc。我的建议是,在少量指令的情况下,可以用 plugin.yml 这种很方便的方式。



    全文完


    8年前 0 回复
  • 本页文章来源:http://nukkit.ru/threads/97(Nukkit 俄语社区)// 原标题:С чего начать: Обработка событий
    事件处理

    1. 事件的基本信息

    玩家在游玩服务器时,与服务器的其他玩家和物体会发生一些事件:玩家的移动、玩家发送指令、破坏或放置方块,雪花降落到地面,爬行者的爆炸,和其它诸如此类的事件。当这样的事件发生的时候,服务器会关心那些插件需要的事件。一个插件也许能影响或改变则个事件:插件可以把闯入他人领地的玩家踢出游戏,在玩家发送广告前将其拦截,防止玩家更改领地内的方块,清除下雪天气,把残忍的苦力怕变成可爱的

    (译者:噗)

    。如果我们忽略这段文字中的文学成分,我们能说,服务器内存在某个事件的

    监听器 

    - 这是事件系统中最重要的部分,几乎所有的插件都与处理事件相关。


    现在获取事件列表,最好的方法是翻找

     github 页面

    事件处理过程本身需要这样实现:

    • 插件“表达”它处理事件的愿望,为这个事件编写处理程序,并注册为监听器。事件的处理程序可以作为一个独立的类(数量不限),或者可以和插件主类共用一个类。
    • 在处理程序中表达插件处理这个事件的方法。这些方法将参与到服务器处理整个事件的过程。


    作为例子,我们给 FirstPlugin 插件添加一个监听器,能在玩家进入服务器时弹出消息。



    2. 创建一个监听器

    创建一个监听器,可以和 FirstPlugin 共用一个类,然而我更喜欢把事件处理单独写一个类。要开始创建,我们需要在包里面创建一个新的类:




    我们叫它 FirstListener 好了:




    要把它变为一个事件监听器类,我们需要在类名后面添加" implements Listener":




    3. 注册监听器类

    现在,我们已经创建了一个监听器。虽然它事实上是空的,但是我们依然可以注册这个监听器到 Nukkit。我们现在就开始做吧,以防之后的开发过程中忘记了这一步,来造成调试上不必要的麻烦。



    要注册一个监听器类,在插件主类中的配置文件后面,添加一些这样的代码:


    1.     this.getServer().getPluginManager().registerEvents(new FirstListener(),this);

    复制代码

    现在所有的监听器已经被注册了。



    顺便一提,我想重点说一个内容。我可以创建一个事件监听器的匿名内部类后马上使用 registerEvents 来注册。但是,一般情况下这个监听器类和插件是分离的,这个类只是注册事件方法的一个作为参数的单独对象。匿名累不累只能工作在一种情况下 - 那就是你的监听器需要引用插件主类的其它方法,并以某种形式使用它。在大多数情况下,我们不需要引用插件主类,所以我们就可以把事件监听器类和插件主类分开。



    4. 创建处理事件的方法

    要实现插件对事件的处理,你需要在监听器类中添加一个方法。我们来创建一个空的(至少现在是空的)方法:


    1. public void onPlayerJoin (PlayerJoinEvent event){
    2.     }

    复制代码

    然而,这个方法事实上并不会在事件发生的时候被调用。我们还需要一个注解 - @EventHandler:


    1. @EventHandler (ignoreCancelled = true, priority = EventPriority.NORMAL)
    2.     public void onPlayerJoin (PlayerJoinEvent event){
    3.   
    4.     }

    复制代码

    一般情况下,你直接在方法前添加 @EventHandler,然后就可以工作了。然而,我习惯于把所有参数都写全。这些参数是:


    • ignoreCancelled = true - 意思是如果这个事件被别的插件取消了,那 Nukkit 就不会调用我们的插件的事件监听器的这个方法。
    • priority = EventPriority.NORMAL - 这个决定你的事件监听器的优先级。低优先级的监听器(LOW, LOWEST)会被首先调用,然后高优先级的(HIGH, HIGHER, MONITOR)会在随后调用. 在99%的情况下用普通优先级(NORMAL)就够了.



    现在让我们完善我们的监听器,让它能够在玩家加入时显示之前在配置文件中读取的字符串。



    5. 从事件监听类获取插件主类的方法和变量

    要处理事件,我们需要在另一个类中获取插件主类的消息。为了能够访问插件,我们给 FirstPlugin 类添加 getPlugin 的静态方法,这个方法将返回插件对象本身。要做到这一点,在 FirstPlugin 类中创建一个静态变量,这个变量将会通过这个方法返回:


    1.     private static FirstPlugin plugin;

    复制代码

    我们在 onEnable 中初始化这个变量:


    1.     plugin = this;

    复制代码

    因此,我们这样写 getPlugin 方法:


    1.     public static FirstPlugin getPlugin(){
    2.         return plugin;
    3.     }

    复制代码


    6. 实现监听器

    我们回到监听器类。我想要显示

    “[NEWS]消息”

    格式并带颜色的新闻,我们可以使用 TextFormat 工具类中的 colorize 函数,这当然是一个好消息。

    (译者:顺便一提,Nukkit 中的 colorize 函数就是原文作者本人编写的)

    信息的颜色我们可以在配置文件中设置。我们这样开始:


    1. @EventHandler (ignoreCancelled = true, priority = EventPriority.NORMAL)
    2.     public void onPlayerJoin (PlayerJoinEvent event){
    3.         event.getPlayer().sendMessage(TextFormat.colorize("&3[NEWS] &b"+FirstPlugin.getPlugin().helloMessage));
    4.     }

    复制代码


    我们可以修改插件的默认配置文件:


    1. # 示例配置文件
    2. #
    3. # 选项:hello-message - 是在服务器启动时将要显示的消息
    4. #
    5. hello-message: '&6服务器已经安装了 &4FirstPlugin&6!'

    复制代码

    (译者:原文看折叠:



    要让默认配置文件生效,记得把旧的文件夹和里面的旧配置文件删除。



    然后我要提到一点。字符串内直接使用一些 YAML 的特殊字符时,比如字符“&”,会引起 YAML 引擎报错。要避免这个错误发生 - 请使用引号把字符串包围。



    7. 编译!

    按 ctrl+F9,启动服务器!



    我们看到我们的消息已经被显示了。祝贺!



    8年前 0 回复
  • 本页文章来源:http://nukkit.ru/threads/85(Nukkit 俄语社区)// 原标题:С чего начать: Работа с файлами конфигурации


    使用配置文件

    插件配置文件 - 它是存储设置和少量信息的一个重要途径。基本的配置文件是插件数据文件夹内的 config.yml 文件,要使用这个文件不需要通过它的名字来引用它,可以通过一些简单的方法,比如 PluginBase 类里已经定义的 getConfig()、saveConfig()、reloadConfig()。
    要创建一个这样的文件,我们通常拷贝已有的配置好的模板,里面包含了默认的设置。举个不远的例子 - nukkit.yml,这就是一个配置文件,在 Nukkit 的核心中已经打包并准备好,包含着服务器的设置,并在使用前被拷贝出来。

    我们将以上一节中创建的 FirstPlugin 为例子,来讲解配置文件的使用。

    1. 创建一个配置模板



    在这里,我们给它命名为 config.yml:


    我们来添加这样的内容:
    译者:这里是翻译成中文的配置,原文请看折叠:


    1. # 示例配置文件
    2. #
    3. # 选项:hello-message - 是在服务器启动时将要显示的消息
    4. #
    5. hello-message: 从配置文件读出来的欢迎消息!

    复制代码



    这个模板文件已经编写完成了。你在编译插件时,它将会被包括在插件的jar文件内。
    现在,你需要插件在第一次启动时自动复制jar文件内的配置文件。

    2. 创建一个用于存储在插件目录的配置文件的方法
    (译者:这段文字原文发布时API并未更新,所以较麻烦,我根据更新的内容重新写一下)

    其实非常简单,你只需要一个方法 - saveDefaultConfig()
    我们添加这个方法:

    1.     public void initConfig(){
    2.         saveDefaultConfig();
    3.     }

    复制代码简洁又帅气,就一行代码。

    原文的方法,有兴趣的话可以看看:

    3. 读取 config.yml 中的参数

    我希望在插件中定义一个变量,然后读取配置文件存入这个变量,让插件工作:

    1.     String helloMessage;

    复制代码
    因此,我们这样写代码来读取配置文件到 helloMessage 变量:
    (译者:我翻译一下:Сообщение по умолчанию 默认消息)

    1.     public void loadCfg(){
    2.         this.reloadConfig();
    3.         this.helloMessage = this.getConfig().getString("hello-message","Сообщение по умолчанию");
    4.     }

    复制代码
    这样一来,我们的 onEnable 方法是这样的:

    1.     @Override
    2.     public void onEnable(){
    3.         this.initConfig();
    4.         this.loadCfg();
    5.         this.getLogger().info(TextFormat.RED+this.helloMessage);
    6.     }

    复制代码
    好了,整个插件看起来像这样:


    4. 编译,看结果

    我们按 ctrl+F9 运行服务器:

    正如你所看到的,这个消息已被成功地从配置文件中读取。
    如果检查服务器上的插件目录,你会看到FirstPlugin目录已经被创建,然后出现了config.yml文件。


    8年前 0 回复
  • 本页文章来源:http://nukkit.ru/threads/81(Nukkit 俄语社区)// 原标题:С чего начать: Первый плагин


    第一个插件
    我们来看如何创建第一个插件,对那些 Nukkit 插件的新手我们做一点插件的介绍。

    1. 选择开发使用的 IDE

    虽然在有些情况下你可以用记事本来写代码,但是如果我们用一个特殊的编辑器,那将是很方便的。IDE,即集成开发环境,是辅助编程开发的软件。使用合适的IDE能有效地减少代码语法错误、编译麻烦等问题,加大开发效率。以前我在写bukkit插件或者别的 Java 应用时,我用 eclipse 来开发。但是我写 Nukkit 插件时,我发现使用 IntelliJ IDEA 将是更方便的。

    2. 获得 IntelliJ IDEA

    至于软件,我们需要从它的官网上下载。现在需要看这个链接:https://www.jetbrains.com/idea/download/


    在这里,我们下载“Community(社区)”的版本,它对于大多数的,越来越多的 Nukkit 插件的开发已经是绰绰有余。

    3. 安装并运行

    我们看到了类似的这样的信息:(你的左边的项目列表应该是空的)


    4. 创建项目

    点击“Create New Project(创建新项目)”按钮,出现一个窗口,你需要选择项目创建的类型。我通常选择 Maven 管理的项目 - 如果有必要的话,它会提供让我们可以使用 Maven 仓库来管理的优势。原则上我们需要选择适合 Java 开发的项目类型。


    如果你选择了 Maven,你只需要点击“下一步”,然后填写相关的 Maven 项目的参数:


    你必须指定 GroupId 和 ArtifactId 值。在 Maven 的每个项目中,必须设置有这两个独特的 GroupId 和 ArtifactId。为了避免冲突和混淆,GroupId我们通常冠名为组织或者项目的网站,而 ArtifactId 通常是项目的名称。

    译者:这里有必要做一些详细说明。GroupId 经常也是 Java 项目的包名。Java 项目的包命名规则有这样的约定:以 网站倒着写.项目名字 或者 网站倒着写.项目名字.模块名字 为结构必须以小写字母开头必须与别的 Java 包相区别Nukkit 内核的所有包都是遵循这个规定的 Nukkit 的网站是 nukkit.cn,所以里面包含所有方块(block)的包的包名应该是:cn.nukkit.block各位在编写 Nukkit 插件的时候,需要编写一个独特的、和他人的项目不一样的包名,以便与他人开发的插件相区别。比如译者的网站是 snake1999.com,如果译者编写了一个叫 ExamplePlugin 的 Nukkit 插件,就可以放在包名为 com.snake1999.exampleplugin 的包内。以下包名的结构都是可以使用的:com.snake1999.examplepluginnet.mcbbs.tutorialpluginru.nukkit.nkexampleme.fromgate.firstplugin而以下的包名都是不被推荐使用的:main.java.pluginTestPlugin另外,开发 Nukkit 插件,我们规定不能把插件的任何部分存放在 cn.nukkit 包下,否则后果自负。关于主类的名称,只要能和别人的主类区分开就可以了,但是不推荐使用MainClass之类的名称。


    指定完成后,我们点击“Finish”按钮,现在这个项目已经创建完成了!


    5. 创建一个项目包

    在左边的侧边栏中,展开项目结构,展开src文件夹 - 我们需要在 src/main/java 文件夹内编写我们的代码。鼠标右键点击,创建一个新的包:


    输入包的名称:


    点击“OK”,需要的创建完成了!

    6. 设置依赖库

    我们写 Nukkit 的插件,意味着我们在 Nukkit 原有的功能上做修改或添加。这意味着我们把 Nukkit 内核本身作为一个依赖库。要做到这一点,我们来打开“Project Structure(项目结构)”窗口:


    在这个窗口中,选择“Libraries(依赖库)”,点击“+”,在弹出的菜单中点击“Java”:
    (译者:原文作者写这篇教程时,Nukkit 官方尚未推送内核到 Maven 仓库。以后这里会有更简单的方法)


    在此之后,系统会提示你选择磁盘上的文件 - 我们将选择 Nukkit 服务器的核心 jar 包(需要单独放置在一个文件夹):


    7. 创建项目主类

    我们应该在先前项目自动生成的包里面创建这个主类:


    输入类的名称:


    类已经创建完毕了:


    8. 创建 plugin.yml

    每个插件都有 plugin.yml 文件。这里介绍一些设置,说明这个文件的格式。插件没有这个文件,就不会被 Nukkit 识别和加载。
    这个文件我们放进 resources(资源) 文件夹:


    这个文件名当然是 plugin.yml:


    这个文件的全文应该是类似这样的:

    1. name: FirstPlugin
    2. main: me.fromgate.firstplugin.FirstPlugin
    3. version: "0.0.1"
    4. author: fromgate, nukkit.ru
    5. api: ["1.0.0"]
    6. description: My first plugin

    复制代码在这里每行都有特别的意义:

    • name - 插件的名称
    • main - 插件主类的完整路径,包括包名和主类名
    • version - 版本号,注意这里必须用引号包围,否则会出现错误。(再次感谢 @andylizi 指出typo)
    • api - 这个插件支持的 Nukkit API 版本号。目前总是写["1.0.0"]
    • description - 插件的简要说明



    顺便一提,这个消息出现的时候不要害怕:

    它建议你安装一个 IntelliJ IDEA 的插件,来支持 yml 格式文档更高级的编辑。如果你不需要的话,可以点击"Ignore extension"。

    9. 编写一个简单的代码


    我们回到插件的主类。需要做这几点:在名称后面添加" extends PluginBase",这意味着我们的插件需要继承 PluginBase 类才能让 Nukkit 可以识别。
    我们在主类中创建这样的方法:

    1. @Override
    2. public void onEnable(){
    3.     this.getLogger().info(TextFormat.RED+"My first plugin enabled");
    4. }

    复制代码如果在打字时出现了某些类是未知的类的提示,只需按下 alt+回车,然后在上面点击导入软件包即可。

    我们的第一个插件已经完成了!你可以把他编译,然后就可以使用。


    10. 编译插件

    我们再次按下"Project Structure",转到"Artifacts"栏,点击加号再选择"jar"->"Empty":


    在这个界面你需要做的有:

    • 填写名称("Name")
    • 指定编译输出的目录(我这里填了测试用服务器的插件目录)
    • 在右边 "Available Elements(可用项)" 中双击 "FirstPlugin" 来编译输出
    • 勾选"Build On Make(在编译时生成)"




    点击"OK", 回到编辑器,按下 ctrl+F9,然后等待编译


    编译输出的插件的路径在刚才已经制定过了。你现在可以运行服务器来检查插件!

    11. 检查插件

    要做到这一点,我们只需要运行服务器然后看控制台:

    如果你看到了我们输出的消息,或许这就意味着我们刚才做的一切有了成果。祝贺吧!


    8年前 0 回复