一个基于 PicqBotX 机器人类库的插件系统!
一个基于 PicqBotX QQ 机器人类库的插件系统.
( 和 Bukkit 的插件系统一模一样 Credit to @md_5
插件的插件系统的插件的 API 的插件的插件系统
在开发这个插件管理系统之前, 每个 PicqBotX 机器人必须作为一个单独的应用运行.
但是这样, 如果一个开发者开发了一套功能, 比如信息查询,
然后另一个开发者开发了另一套功能, 比如碰数游戏,
但是如果想让一个机器人实例同时运行这两套功能的话,
就必须手动合并这两个项目.
但是如果这两个开发者把他们的功能写成这个插件系统的插件的话.
运行一个插件管理器, 然后把两个构建好的插件 JAR 都丢到运行目录的 Plugins 文件夹里,
就能在一个机器人实例上同时运行两套功能了!
- v1.0.0
- 动态 URLClassLoader 加载插件 JAR
- 每个插件注册指令和事件监听器
- 每个插件单独的 Logger
- 发布一个有功能的插件例子
- 写运行教程
没有添加 JitPack 的 Repo 的话首先添加 Repo, 在 pom 里面把这些粘贴进去:
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
然后添加这个库:
<dependency>
<groupId>com.github.hydevelop</groupId>
<artifactId>PicqBotX-PluginManager</artifactId>
<version>4.15.0.149</version>
<scope>provided</scope>
</dependency>
然后 ReImport 之后就导入好了!
没有添加 JitPack 的 Repo 的话首先添加 Repo, 在 pom 里面把这些粘贴进去:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
然后添加这个库:
dependencies {
implementation 'com.github.hydevelop:PicqBotX-PluginManager:4.15.0.149'
}
基础启动:
@echo off
title PicqBotX 插件管理服务器
java -jar {JAR文件名}.jar
pause
再加一个自动重启和重启次数计数:
@echo off
set a = -1
:loop
set /a a += 1
title PicqBotX 插件管理服务器 [重启次数:%a%]
java -jar {JAR 文件名}.jar
echo ##################### 线程已关闭, 5秒后自动重启... #####################
ping localhost -n 5 >NUL
goto loop
把这段存到运行目录的 start.bat 文件里就行啦! ( jar 文件名替换成你下载的 jar 文件名)
while true
do
java -jar {JAR 文件名}.jar
echo "##################### 线程已关闭, 5秒后自动重启... #####################"
sleep 5
done
把这段存到运行目录的 start.sh 文件里就行啦! (jar 文件名替换成你下载的 jar 文件名)
- UI 版 Windows 的话直接点开 start.bat 就好了!
- 无 UI 版的话要 cd 到当前目录, 然后执行 start.bat (真的有人用无 UI 的 Windows 么...
注意: 不要问我Error: Unable to access jarfile {JAR 文件名}.jar
怎么解决, 仔细想想都知道怎么解决嘛...
- 打开控制台
- 执行 cd {运行目录}
- 执行 sudo chmod +x start.sh
- 执行 ./start.sh
启动第一次后, 会自动生成 config.yml 配置文件:
# ############################ #
# PicqBotX 插件启动器 配置文件 #
# 作者: Hykilpikonna #
# 对应版本: 4.15.0.149 #
# ############################ #
# 连接设置
ConnectionSettings:
# 发送地址
PostURL: '127.0.0.1'
# 发送地址的端口
PostPort: 31091
# 监听端口 (HTTP 服务器端口)
ListeningPort: 31092
# 指令设置
CommandSettings:
# 是否启动指令功能
Enable: true
# 指令前缀
Prefixes:
- 'bot -'
- '!'
- '/'
# 两个插件同时注册一个指令的话怎么办
# ENABLE_LAST : 启用最后注册的
# ENABLE_ALL : 启用所有
# 如果冲突的话, 可以用 /<插件名>:<指令> 来执行某个插件的指令
ConflictOperation: ENABLE_ALL
# 插件加载设置
PluginLoaderSettings:
# 是否启动插件加载
Enable: true
# 插件目录
PluginDir: './plugins/'
# 日志设置
LoggerSettings:
# 是否输出 Debug 日志
Debug: false
# 颜色支持级别
# FORCED : 不传入 Jansi, 强制启用颜色
# PASSTHROUGH : 实际效果和 FORCED 一样, 传入 Jansi 但是不处理
# PRESET_ONLY : 只输出预设颜色, 移除 RGB
# DEFAULT : 默认支持
# OS_DEPENDENT : 取决于 OS, 如果是 Linux 就用 DEFAULT, 如果是 Windows 就用 PRESET_ONLY
ColorSupportLevel: OS_DEPENDENT
# Log 文件输出目录 (相对目录)
LogFileRelativePath: logs
# Log 文件名
LogFileName: PicqBotX-Log
要改的话改完保存然后直接重启就行了.
- 把构建好的插件 JAR 文件放到 plugins 文件夹里 (如果用外部导入的话必须是 shaded).
- 重启就会自动加载了
- 移除的话先关掉, 然后把 JAR 包删掉, 然后启动就行了...
- 现在还没有自动判断导入调整优先级
- 所以... 调整优先级只能通过调整文件名
- 文件名越靠前就先加载
- 比如说如果 插件B 是 插件A 的类库的话
- 那就要重命名成
0-插件B.jar
和1-插件A.jar
来调整加载顺序了
很重要, 如果要用外部导入的话就必须用 Maven.
不会 Maven 的话可以跳过这一步. ( 推荐先去学 Maven
首先设置 SDK 级别, 因为 Picq 是 Java 8 运行的所以推荐插件也用 Java 8 了
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
然后添加导入(看这里)
然后添加构建配置:
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<defaultGoal>clean install</defaultGoal>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>plugin.yml</include>
<include>config.yml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<configuration>
<archive>
<manifestEntries>
<Main-Class>cc.moecraft.icq.pluginmanager.Launcher</Main-Class>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</plugin>
</plugins>
</build>
这个构建配置实现了两件事情:
- 把
resources
里的plugin.yml
和config.yml
放到构建好的JAR里面. - 把外部导入 shade 到 JAR 里面.
- 右键
src/main/resources
路径, 创建一个叫plugin.yml
的文件. (必须全小写 - 写进去需要的信息:
字段 | 重要性 | 代表什么 | 例子 |
---|---|---|---|
name | 必要 | 插件的名字 | TestPlugin |
main | 必要 | 插件的主类 | cc.moecraft.icq.plugins.testplugin.Main |
例子:
name: TestPlugin
main: cc.moecraft.icq.plugins.testplugin.Main
- 创建一个类
- 注意: 这个类的包位置必须和上面
plugin.yml
里面main
字段写的一样 - 让这个类继承
IcqPlugin
类(extends IcqPlugin
). - 实现抽象方法
- 创建完了!
例子:
package cc.moecraft.icq.plugins.testplugin;
import cc.moecraft.icq.command.interfaces.IcqCommand;
import cc.moecraft.icq.event.IcqListener;
import cc.moecraft.icq.pluginmanager.plugin.IcqPlugin;
public class Main extends IcqPlugin
{
@Override
public void onEnable()
{
// 加载插件的时候会运行这个方法
instance = this;
}
@Override
public void onDisable()
{
// 卸载插件的时候会运行这个方法
}
@Override
public IcqCommand[] commands()
{
return new IcqCommand[]
{
};
}
@Override
public IcqListener[] listeners()
{
return new IcqListener[]
{
};
}
private static Main instance;
public static Main getInstance()
{
return instance;
}
}
- 写一个事件监听器类: 看这里
- 在 Main 的 listeners() 方法里添加一个实例
例子:
监听器类 (TestListener.java):
public class TestListener extends IcqListener
{
@EventHandler
public void onMessageEvent(EventMessage event)
{
Main.getInstance().getLogger().log("收到消息事件! 内容 = " + event.toString());
}
}
主类:
@Override
public IcqListener[] listeners()
{
return new IcqListener[]
{
new TestListener()
};
}
- 写一个指令类: 看这里
- 在 Main 的 commands() 方法里添加一个实例
例子:
指令类 (TestCommand.java):
public class TestCommand implements EverywhereCommand
{
@Override
public String run(EventMessage event, User user, String s, ArrayList<String> arrayList)
{
event.getBot().getLogger().log("收到测试指令!");
return "测试指令回复!";
}
@Override
public CommandProperties properties()
{
return new CommandProperties("test");
}
}
主类:
@Override
public IcqCommand[] commands()
{
return new IcqCommand[]
{
new TestCommand()
};
}
- 写一个默认配置文件
config.yml
放进main/src/resources
里 (不然使用getConfig会返回null). - 然后就可以用了
- 存储位置在
运行目录/plugins/插件名/config.yml
.
例子: 默认配置config.yml
:
TestBoolean1: true
TestList1:
- 666666666
- 999999999
TestList2: []
TestKey1:
TestKey2: TestValue
例子: 从程序里访问:
getConfig().getBoolean("TestBoolean1"); // 返回 TestBoolean1 字段的值
getConfig().getStringList("TestList1"); // 返回 TestList1 字段的字符串数组
getConfig().getStringList("TestList2"); // 返回 TestList2 字段的字符串数组
getConfig().getString("TestKey1.TestKey2"); // 返回 TestKey1 下的 TestKey2 字段的值
- 注意:
- Jar 文件会构建到
target
目录下 - 加载到服务器要用
shaded
版本, 作为API发布可以不用shaded
- (不过推荐全都用
shaded
版本, 毕竟万一会有人想直接拿 API 的 jar 加载就抛 class not found 呢...
- 打开右边的
Maven Project
栏 - 展开
Lifecycle
菜单 - 双击
package
运行
- 在项目路径打开任意Bash
mvn package
(不要问我 bash: mvn: command not found 怎么解决...