一、第一个插件

这一章节,我们会开发第一个属于自己的插件
在这之前,我们还需了解plugin.yml和config.yml,并大概了解插件的原理

plugin.yml

这个文件必须存在,否则读不出来。

右键项目,新建文件,文件名:plugin.yml

先不要往里面写什么,因为你还不知道我们该写些什么(废话)

Bukkit对yml文件的要求十分严格,打错一个字就整个都不读


config.yml

这个文件可以存在,也可以不存在。

右键项目,新建文件,文件名:config.yml

这个是配置文件,在之后的教程中会用到,有很大的用处。一些优秀的插件往往都离不开它。


原理

一个插件在服务器加载时会发生什么?

在这里插入图片描述

首先,服务器会先加载整个服务端,然后开启端口,此时我们的插件才会去加载,然后加载整个世界,最后插件加载完成,服务器才会真正完成加载。

还记得插件是什么吗?我们调用Bukkit的API,就是在用Bukkit提供给我们的接口。如果插件脱离了Bukkit就无法正常运行,因为没有BukkitAPI。

启动服务端时,有一个线程,名叫PluginLoader,它是专门用来加载服务器插件的。


我们的插件依赖服务器的核心文件,我们调用服务器的API来去完成自己的工作,从而服务玩家。

在这里插入图片描述
可以看到,服务器核心文件下的有诸多api:

文件夹 描述
block 方块
command 命令
entity 实体
event 事件监听
inventory 容器
material 存放所有物品
generator 创建巨人实体等操作
scoreboard 计分板

当然,不止这些。


NMS(net.minecraft.server)

在核心文件中的net.minecraft.server下有许多类,共3680个(截止1.16.5版本),如BlockAir.classChatMessage.classEntityBee.class等。

在这里插入图片描述

看这些类名会发现:空气方块、聊天信息、蜜蜂实体……这些每一个类都对应游戏中的每一个方块、服务器中的每一条信息、每一个实体。

NMS(net.minecraft.server),它就是bukkit服务端下的底层实现

我们已经有了BukkitAPI,已经能够帮助我们解决很多问题了,为什么需要接触底层(到底层锻炼锻炼)?

确实,NMS是不得已的情况下再使用为好,非必要请使用BukkitAPI。NMS的兼容性较差,各版本之间无法很好的相互兼容,并且方法、字段名已被混淆

不过,Bukkit已经反混淆过了。运用Java的反射机制,使得类也是一个对象。这使得我们的插件可以兼容绝大多数版本。

NMS在net.minecraft.server.v版_本_R下,也就是我们刚刚看到的文件夹net.minecraft.server.v1_16_R3下。

此章节暂不做详细讲解,再后面的章节实体Entity中我们自定义实体会首次接触到它,在第九章,我们专门讲解一下NMS和Java反射机制


编写教程

请自己手打代码,复制粘贴你永远也学不会
请自己手打代码,复制粘贴你永远也学不会
请自己手打代码,复制粘贴你永远也学不会
在你建好的包包下新建一个Java文件,类名请遵循帕斯卡命名法1

之后继承JavaPlugin

public class MyPlugin extends JavaPlugin {
	
}

重写加载卸载两个方法

@Override
public void onEnable() {
	//加载
}

@Override
public void onDisable() {
	//卸载
}

强烈推荐大家创建一个方法say用来输出日志

public void say(String s) {
	CommandSender sender = Bukkit.getConsoleSender();
	sender.sendMessage(s);
}

要输出日志的时候只需say("");即可
只要你创建了这个方法,那么只需往加载和卸载方法中写入

@Override
public void onEnable() {
	say("插件已加载!");
}

@Override
public void onDisable() {
	say("插件已卸载!");
}

源代码

package com.qq.lesson;

import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;

public class Example extends JavaPlugin {
    public void onEnable() {
        say("插件已加载");
    }

    public void onDisable() {
        say("插件已卸载");
    }

    public void say(String s) {
        CommandSender sender = Bukkit.getConsoleSender();
        sender.sendMessage(s);
    }
}

等等,还没结束!
前面我们提到plugin.yml一定要加上去
现在来看看到底要写什么

属性 必需 描述
main 主类
version 插件版本
name 插件名字
description 不是 介绍这个插件
author 不是 插件作者
authors 不是 多个插件作者
commands 不是 命令
permissions 不是 权限
depend 不是 依赖,比如这个插件依赖另外的插件
database 不是 数据库

必需那一列是是的必填。而由于我们才刚刚开发插件,其他的可以不写。

格式如下:

# 插件的名字
name: MyFirstPlugin
# 插件的版本
version: 1.0.0
# 插件的主类
main: com.qq.lesson.MyPlugin
# 插件的作者
author: XXX
# 插件的介绍
description: My First Plugin

注意事项:
每个冒号的后面必须打上一个空格,不然读不出来
如果需要分层,请在开头打上两个空格,不然读不出来
之后打包放进plugin文件夹里就可以了

导出插件

当我们写完以后,右键我们的项目,点击“打开模块设置”

在这里插入图片描述

打开后,选择“工件”:

在这里插入图片描述

点击右边的加号,选择JAR,选择Empty(空):

在这里插入图片描述

双击右边的编译输出

在这里插入图片描述

plugin.yml是我们插件的命根子,所以我们也要将其收入囊中:

在这里插入图片描述
选择我们的plugin.yml,然后点击确定就OK了。

回到主页面,选择上方的构建,点击构建工件,等待构建完成之后,我们会发现项目中会多出一个out文件夹,而out文件夹下的artifacts文件夹中的jar文件就是我们的插件。

将jar文件丢进服务器的plugins文件夹,重启服务器,我们就会发现插件正常启动了。

开发小知识

如果觉得输出很没有特色,试试彩色字?
在这里插入图片描述
只需要在你想要打彩色字的前面加上去就可以了
例:
我想打出黄色字你好!
就可以这么写:

say("§6你好");

后期我们开发插件时可以专门写一个在游戏里可以打彩色字的插件

闲谈

Bukkit中的线程PluginLoader加载插件,对于每一个插件(也就是jar文件)先找到并读取plugin.yml,如果这个文件有误或根本不存在就报错。然后开始尝试加载,如果加载失败(比如没找到变量或方法)就报错,一些写插件的新手写错了会在服务器控制台中突然看到一大串英文,那就是报错(Java的安全性很高)而重新修改又会花掉大量时间(包括编译、打包、重启服务端)所以在编写插件时错是可以的,同一个错一犯再犯是不容许的。


上一篇:我的世界Bukkit服务器插件开发教程(零)环境搭建
下一篇:我的世界Bukkit服务器插件开发教程(二)命令


  1. 帕斯卡命名法 ↩︎

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐