feat: adding base
This commit is contained in:
parent
f0dcae301b
commit
2c39144ece
8
.idea/file.template.settings.xml
generated
Normal file
8
.idea/file.template.settings.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExportableFileTemplateSettings">
|
||||
<includes_templates>
|
||||
<template name="version.txt" file-name="version.txt" reformat="true" live-template-enabled="false" />
|
||||
</includes_templates>
|
||||
</component>
|
||||
</project>
|
10
.idea/fileTemplates/code/JavaDoc Class.java
generated
Normal file
10
.idea/fileTemplates/code/JavaDoc Class.java
generated
Normal file
@ -0,0 +1,10 @@
|
||||
* @author wzp
|
||||
* @since ${DATE} ${TIME}
|
||||
* @version #parse("version.txt")
|
||||
|
||||
#foreach($param in $RECORD_COMPONENTS)
|
||||
* @param $param
|
||||
#end
|
||||
#foreach($param in $TYPE_PARAMS)
|
||||
* @param <$param>
|
||||
#end
|
12
.idea/fileTemplates/code/JavaDoc Constructor.java
generated
Normal file
12
.idea/fileTemplates/code/JavaDoc Constructor.java
generated
Normal file
@ -0,0 +1,12 @@
|
||||
* @author wzp
|
||||
* @since ${DATE} ${TIME} v#parse("version.txt")
|
||||
|
||||
#foreach($param in $PARAMS)
|
||||
* @param $param
|
||||
#end
|
||||
#foreach($param in $TYPE_PARAMS)
|
||||
* @param <$param>
|
||||
#end
|
||||
#foreach($exception in $THROWS)
|
||||
* @throws $exception
|
||||
#end
|
2
.idea/fileTemplates/code/JavaDoc Field.java
generated
Normal file
2
.idea/fileTemplates/code/JavaDoc Field.java
generated
Normal file
@ -0,0 +1,2 @@
|
||||
* @since ${DATE} ${TIME} v#parse("version.txt")
|
||||
|
15
.idea/fileTemplates/code/JavaDoc Method.java
generated
Normal file
15
.idea/fileTemplates/code/JavaDoc Method.java
generated
Normal file
@ -0,0 +1,15 @@
|
||||
* @author wzp
|
||||
* @since ${DATE} ${TIME} v#parse("version.txt")
|
||||
|
||||
#foreach($param in $PARAMS)
|
||||
* @param $param
|
||||
#end
|
||||
#if($RETURN_TYPE != "void")
|
||||
* @return
|
||||
#end
|
||||
#foreach($param in $TYPE_PARAMS)
|
||||
* @param <$param>
|
||||
#end
|
||||
#foreach($exception in $THROWS)
|
||||
* @throws $exception
|
||||
#end
|
20
.idea/fileTemplates/code/JavaDoc Overriding Method.java
generated
Normal file
20
.idea/fileTemplates/code/JavaDoc Overriding Method.java
generated
Normal file
@ -0,0 +1,20 @@
|
||||
* @author wzp
|
||||
* @since ${DATE} ${TIME} v#parse("version.txt")
|
||||
|
||||
#foreach ($param in $PARAMS_INHERITED)
|
||||
* @param $param
|
||||
#end
|
||||
#if (!$PARAMS_INHERITED)
|
||||
#foreach ($param in $PARAMS)
|
||||
* @param $param
|
||||
#end
|
||||
#end
|
||||
#if($RETURN_TYPE != "void")
|
||||
* @return
|
||||
#end
|
||||
#foreach($param in $TYPE_PARAMS)
|
||||
* @param <$param>
|
||||
#end
|
||||
#foreach($exception in $THROWS)
|
||||
* @throws $exception
|
||||
#end
|
5
.idea/fileTemplates/includes/File Header.java
generated
Normal file
5
.idea/fileTemplates/includes/File Header.java
generated
Normal file
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* @author wzp
|
||||
* @since ${DATE} ${TIME}
|
||||
* @version #parse("version.txt")
|
||||
*/
|
1
.idea/fileTemplates/includes/Version.txt
generated
Normal file
1
.idea/fileTemplates/includes/Version.txt
generated
Normal file
@ -0,0 +1 @@
|
||||
0.0.1-dev
|
5
.idea/jarRepositories.xml
generated
5
.idea/jarRepositories.xml
generated
@ -16,5 +16,10 @@
|
||||
<option name="name" value="MavenRepo" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven" />
|
||||
<option name="name" value="maven" />
|
||||
<option name="url" value="https://libraries.minecraft.net" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
@ -13,15 +13,21 @@ version = projectVersion
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://libraries.minecraft.net")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.mojang:brigadier:1.0.18")
|
||||
// https://mvnrepository.com/artifact/io.netty/netty-all
|
||||
implementation("io.netty:netty-all:4.1.112.Final")
|
||||
// https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core
|
||||
implementation("org.apache.logging.log4j:log4j-core:2.23.1")
|
||||
// https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2
|
||||
implementation("com.alibaba.fastjson2:fastjson2:2.0.52")
|
||||
// https://mvnrepository.com/artifact/org.yaml/snakeyaml
|
||||
implementation("org.yaml:snakeyaml:2.2")
|
||||
// https://mvnrepository.com/artifact/org.jline/jline
|
||||
implementation("org.jline:jline:3.26.3")
|
||||
// https://mvnrepository.com/artifact/org.projectlombok/lombok
|
||||
compileOnly("org.projectlombok:lombok:1.18.34")
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.34")
|
||||
|
@ -1,10 +1,42 @@
|
||||
package cn.wzpmc;
|
||||
|
||||
import cn.wzpmc.configuration.Configuration;
|
||||
import cn.wzpmc.network.WebSocketConnectionHandler;
|
||||
import cn.wzpmc.utils.TemplateFileUtils;
|
||||
import cn.wzpmc.utils.YamlUtils;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
@Log4j2
|
||||
public class Main {
|
||||
private static final String DEFAULT_CONFIGURATION_FILE_PATH = "templates/config.yaml";
|
||||
@SneakyThrows
|
||||
public static void main(String[] args) {
|
||||
|
||||
log.info("启动MyBot...");
|
||||
File configurationFile = new File("config.yaml");
|
||||
if (TemplateFileUtils.saveDefaultConfig(Main.class.getClassLoader(), DEFAULT_CONFIGURATION_FILE_PATH, configurationFile)) {
|
||||
log.debug("创建日志文件成功!");
|
||||
log.info("首次启动,默认配置文件已创建,请填写后再次启动MyBot!");
|
||||
return;
|
||||
}
|
||||
log.debug("读取配置文件 {}", configurationFile.getAbsolutePath());
|
||||
Configuration configuration = YamlUtils.readYamlFile(configurationFile, Configuration.class);
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(configuration.getWebsocket());
|
||||
} catch (URISyntaxException e) {
|
||||
log.error("无法解析websocket地址");
|
||||
return;
|
||||
}
|
||||
WebSocketConnectionHandler webSocketConnectionHandler = new WebSocketConnectionHandler();
|
||||
ChannelFuture future = webSocketConnectionHandler.connect(uri);
|
||||
Channel channel = future.sync().channel();
|
||||
log.info("连接服务器成功!");
|
||||
}
|
||||
}
|
10
src/main/java/cn/wzpmc/api/commands/BaseCommand.java
Normal file
10
src/main/java/cn/wzpmc/api/commands/BaseCommand.java
Normal file
@ -0,0 +1,10 @@
|
||||
package cn.wzpmc.api.commands;
|
||||
|
||||
/**
|
||||
* 指令基类
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午3:15
|
||||
*/
|
||||
public interface BaseCommand {
|
||||
}
|
20
src/main/java/cn/wzpmc/api/commands/BrigadierCommand.java
Normal file
20
src/main/java/cn/wzpmc/api/commands/BrigadierCommand.java
Normal file
@ -0,0 +1,20 @@
|
||||
package cn.wzpmc.api.commands;
|
||||
|
||||
import cn.wzpmc.api.user.CommandSender;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
|
||||
/**
|
||||
* Brigadier指令
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午2:59
|
||||
*/
|
||||
public interface BrigadierCommand extends BaseCommand {
|
||||
/**
|
||||
* 获取指令节点
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:16 v0.0.1-dev
|
||||
* @return 指令节点
|
||||
*/
|
||||
LiteralArgumentBuilder<CommandSender> getCommandNode();
|
||||
}
|
35
src/main/java/cn/wzpmc/api/commands/RawCommand.java
Normal file
35
src/main/java/cn/wzpmc/api/commands/RawCommand.java
Normal file
@ -0,0 +1,35 @@
|
||||
package cn.wzpmc.api.commands;
|
||||
|
||||
import cn.wzpmc.api.user.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 原始指令
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午2:27
|
||||
*/
|
||||
public interface RawCommand extends BaseCommand {
|
||||
/**
|
||||
* 当指令执行时
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午2:57 v0.0.1-dev
|
||||
* @param commandSender 指令发送者
|
||||
* @param arguments 指令参数,如指令foo若执行/foo a b c则arguments为{"a", "b", "c"}
|
||||
* @return 指令是否执行成功
|
||||
*/
|
||||
boolean onExecute(CommandSender commandSender, List<String> arguments);
|
||||
|
||||
/**
|
||||
* 指令补全
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午2:58 v0.0.1-dev
|
||||
* @param commandSender 指令发送者
|
||||
* @param arguments 指令参数,如指令foo若执行/foo a b c则arguments为{"a", "b", "c"}
|
||||
* @return 当前需要提示的子命令
|
||||
*/
|
||||
default List<String> onTabComplete(CommandSender commandSender, List<String> arguments) {
|
||||
return List.of();
|
||||
}
|
||||
}
|
17
src/main/java/cn/wzpmc/api/message/MessageComponent.java
Normal file
17
src/main/java/cn/wzpmc/api/message/MessageComponent.java
Normal file
@ -0,0 +1,17 @@
|
||||
package cn.wzpmc.api.message;
|
||||
|
||||
/**
|
||||
* 消息对象接口
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午2:33
|
||||
*/
|
||||
public interface MessageComponent {
|
||||
/**
|
||||
* 将其转换为发送的文本
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午2:41 v0.0.1-dev
|
||||
* @return 消息文本
|
||||
*/
|
||||
String toMessageString();
|
||||
}
|
29
src/main/java/cn/wzpmc/api/message/StringMessage.java
Normal file
29
src/main/java/cn/wzpmc/api/message/StringMessage.java
Normal file
@ -0,0 +1,29 @@
|
||||
package cn.wzpmc.api.message;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* 纯文本消息
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午2:34
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class StringMessage implements MessageComponent{
|
||||
private final String message;
|
||||
@Override
|
||||
public String toMessageString() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建纯文本消息
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午2:41 v0.0.1-dev
|
||||
* @param message 消息文本
|
||||
* @return 文本消息对象
|
||||
*/
|
||||
public static StringMessage text(String message){
|
||||
return new StringMessage(message);
|
||||
}
|
||||
}
|
25
src/main/java/cn/wzpmc/api/message/json/JsonMessage.java
Normal file
25
src/main/java/cn/wzpmc/api/message/json/JsonMessage.java
Normal file
@ -0,0 +1,25 @@
|
||||
package cn.wzpmc.api.message.json;
|
||||
|
||||
import cn.wzpmc.api.message.MessageComponent;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* JSON消息
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午2:34
|
||||
*/
|
||||
public class JsonMessage implements MessageComponent {
|
||||
List<JsonMessagePart> messageParts = new ArrayList<>();
|
||||
@Override
|
||||
public String toMessageString() {
|
||||
return JSON.toJSONString(messageParts);
|
||||
}
|
||||
public String toTextDisplay() {
|
||||
return this.messageParts.stream().map(JsonMessagePart::getTextDisplay).collect(Collectors.joining(""));
|
||||
}
|
||||
}
|
47
src/main/java/cn/wzpmc/api/message/json/JsonMessagePart.java
Normal file
47
src/main/java/cn/wzpmc/api/message/json/JsonMessagePart.java
Normal file
@ -0,0 +1,47 @@
|
||||
package cn.wzpmc.api.message.json;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* JSON消息段
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午2:36
|
||||
*/
|
||||
public interface JsonMessagePart {
|
||||
/**
|
||||
* 获取消息的类型
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午2:40 v0.0.1-dev
|
||||
* @return 消息类型字符串
|
||||
*/
|
||||
String getType();
|
||||
|
||||
/**
|
||||
* 获取消息附带的数据
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午2:40 v0.0.1-dev
|
||||
* @return 数据
|
||||
*/
|
||||
Map<String, String> getData();
|
||||
|
||||
/**
|
||||
* 获取当纯文本界面的代替文本
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午2:45 v0.0.1-dev
|
||||
* @return 文本
|
||||
*/
|
||||
default String getTextDisplay(){
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append(this.getType())
|
||||
.append('(')
|
||||
.append('\n');
|
||||
Map<String, String> data = this.getData();
|
||||
int i = 0;
|
||||
data.forEach((key, value) -> stringBuilder.append('\t').append(key).append('=').append(value).append(',').append('\n'));
|
||||
int length = stringBuilder.length();
|
||||
stringBuilder.delete(length - 2, length - 1);
|
||||
stringBuilder.append(')');
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
28
src/main/java/cn/wzpmc/api/plugins/ICommandManager.java
Normal file
28
src/main/java/cn/wzpmc/api/plugins/ICommandManager.java
Normal file
@ -0,0 +1,28 @@
|
||||
package cn.wzpmc.api.plugins;
|
||||
|
||||
import cn.wzpmc.api.commands.BrigadierCommand;
|
||||
import cn.wzpmc.api.commands.RawCommand;
|
||||
|
||||
/**
|
||||
* 指令管理器
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午3:40
|
||||
*/
|
||||
public interface ICommandManager {
|
||||
/**
|
||||
* 注册原始指令
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:34 v0.0.1-dev
|
||||
* @param rawCommand 原始指令
|
||||
* @param name 指令名称
|
||||
*/
|
||||
void registerCommand(RawCommand rawCommand, String name);
|
||||
/**
|
||||
* 注册Brigadier指令
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:35 v0.0.1-dev
|
||||
* @param brigadierCommand 指令对象
|
||||
*/
|
||||
void registerCommand(BrigadierCommand brigadierCommand);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package cn.wzpmc.api.plugins.configuration;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午3:42
|
||||
*/
|
||||
public interface IAuthorizationConfiguration {
|
||||
/**
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:45 v0.0.1-dev
|
||||
* @return 是否启用
|
||||
*/
|
||||
boolean isEnable();
|
||||
|
||||
/**
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:45 v0.0.1-dev
|
||||
* @return token
|
||||
*/
|
||||
String getToken();
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package cn.wzpmc.api.plugins.configuration;
|
||||
|
||||
/**
|
||||
* 配置
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午3:42
|
||||
*/
|
||||
public interface IConfiguration {
|
||||
/**
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:48 v0.0.1-dev
|
||||
* @return WebSocket连接URL
|
||||
*/
|
||||
String getWebsocket();
|
||||
|
||||
/**
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:48 v0.0.1-dev
|
||||
* @return 通信验证
|
||||
*/
|
||||
IAuthorizationConfiguration getAuthorization();
|
||||
|
||||
/**
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:49 v0.0.1-dev
|
||||
* @return 失败消息提示
|
||||
*/
|
||||
IFallbackConfiguration getFallback();
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package cn.wzpmc.api.plugins.configuration;
|
||||
|
||||
/**
|
||||
* 通信验证配置
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午3:43
|
||||
*/
|
||||
public interface IFallbackConfiguration {
|
||||
/**
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:47 v0.0.1-dev
|
||||
* @return 当指令执行失败时
|
||||
*/
|
||||
String getCommand();
|
||||
|
||||
/**
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:47 v0.0.1-dev
|
||||
* @return 当出现未捕获的异常时
|
||||
*/
|
||||
String getErrorUncaught();
|
||||
}
|
34
src/main/java/cn/wzpmc/api/user/CommandSender.java
Normal file
34
src/main/java/cn/wzpmc/api/user/CommandSender.java
Normal file
@ -0,0 +1,34 @@
|
||||
package cn.wzpmc.api.user;
|
||||
|
||||
import cn.wzpmc.api.message.MessageComponent;
|
||||
|
||||
/**
|
||||
* 消息发送者
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午2:32
|
||||
*/
|
||||
public interface CommandSender {
|
||||
/**
|
||||
* 获取用户ID
|
||||
* @author wzp
|
||||
* @since 2024/7/30 下午11:48 v0.0.1-dev
|
||||
* @return 用户ID
|
||||
*/
|
||||
Long getId();
|
||||
|
||||
/**
|
||||
* 获取用户名
|
||||
* @author wzp
|
||||
* @since 2024/7/30 下午11:48 v0.0.1-dev
|
||||
* @return 用户名
|
||||
*/
|
||||
Long getName();
|
||||
/**
|
||||
* 发送消息
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午2:42 v0.0.1-dev
|
||||
* @param messageComponent 消息组件
|
||||
*/
|
||||
void sendMessage(MessageComponent messageComponent);
|
||||
}
|
28
src/main/java/cn/wzpmc/api/user/IBot.java
Normal file
28
src/main/java/cn/wzpmc/api/user/IBot.java
Normal file
@ -0,0 +1,28 @@
|
||||
package cn.wzpmc.api.user;
|
||||
|
||||
import cn.wzpmc.api.plugins.ICommandManager;
|
||||
import cn.wzpmc.api.plugins.configuration.IConfiguration;
|
||||
|
||||
/**
|
||||
* 机器人接口
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午2:31
|
||||
*/
|
||||
public interface IBot extends CommandSender {
|
||||
/**
|
||||
* 获取配置文件
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午2:55 v0.0.1-dev
|
||||
* @return 配置文件
|
||||
*/
|
||||
IConfiguration getConfiguration();
|
||||
|
||||
/**
|
||||
* 获取指令管理器
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:42 v0.0.1-dev
|
||||
* @return 指令管理器
|
||||
*/
|
||||
ICommandManager getCommandManager();
|
||||
}
|
11
src/main/java/cn/wzpmc/api/user/IUser.java
Normal file
11
src/main/java/cn/wzpmc/api/user/IUser.java
Normal file
@ -0,0 +1,11 @@
|
||||
package cn.wzpmc.api.user;
|
||||
|
||||
/**
|
||||
* 用户接口
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/30 下午11:42
|
||||
*/
|
||||
public interface IUser extends CommandSender {
|
||||
|
||||
}
|
9
src/main/java/cn/wzpmc/commands/StopCommand.java
Normal file
9
src/main/java/cn/wzpmc/commands/StopCommand.java
Normal file
@ -0,0 +1,9 @@
|
||||
package cn.wzpmc.commands;
|
||||
|
||||
/**
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午2:26
|
||||
*/
|
||||
public class StopCommand {
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.wzpmc.configuration;
|
||||
|
||||
import cn.wzpmc.api.plugins.configuration.IAuthorizationConfiguration;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 通信验证配置类
|
||||
* @author wzp
|
||||
* @since 2024/7/30 下午11:50
|
||||
* @version 0.0.1-dev
|
||||
*/
|
||||
@Data
|
||||
public class AuthorizationConfiguration implements IAuthorizationConfiguration {
|
||||
/**
|
||||
* 是否启用
|
||||
* @since 2024/7/30 下午11:50 v0.0.1-dev
|
||||
*/
|
||||
private boolean enable;
|
||||
/**
|
||||
* token
|
||||
* @since 2024/7/30 下午11:50 v0.0.1-dev
|
||||
*/
|
||||
private String token;
|
||||
}
|
29
src/main/java/cn/wzpmc/configuration/Configuration.java
Normal file
29
src/main/java/cn/wzpmc/configuration/Configuration.java
Normal file
@ -0,0 +1,29 @@
|
||||
package cn.wzpmc.configuration;
|
||||
|
||||
import cn.wzpmc.api.plugins.configuration.IConfiguration;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 配置类
|
||||
* @author wzp
|
||||
* @since 2024/7/30 下午11:48
|
||||
* @version 0.0.1-dev
|
||||
*/
|
||||
@Data
|
||||
public class Configuration implements IConfiguration {
|
||||
/**
|
||||
* WebSocket连接URL
|
||||
* @since 2024/7/30 下午11:48 v0.0.1-dev
|
||||
*/
|
||||
private String websocket;
|
||||
/**
|
||||
* 通信验证
|
||||
* @since 2024/7/30 下午11:49 v0.0.1-dev
|
||||
*/
|
||||
private AuthorizationConfiguration authorization;
|
||||
/**
|
||||
* 失败消息提示
|
||||
* @since 2024/7/30 下午11:49 v0.0.1-dev
|
||||
*/
|
||||
private FallbackConfiguration fallback;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.wzpmc.configuration;
|
||||
|
||||
import cn.wzpmc.api.plugins.configuration.IFallbackConfiguration;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 当失败时报错消息配置实现
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:44
|
||||
* @version 0.0.1-dev
|
||||
*/
|
||||
@Data
|
||||
public class FallbackConfiguration implements IFallbackConfiguration {
|
||||
/**
|
||||
* 当指令执行失败时
|
||||
* @since 2024/7/31 上午3:44 v0.0.1-dev
|
||||
*/
|
||||
private String command;
|
||||
/**
|
||||
* 当出现未捕获的异常时
|
||||
* @since 2024/7/31 上午3:44 v0.0.1-dev
|
||||
*/
|
||||
private String errorUncaught;
|
||||
}
|
37
src/main/java/cn/wzpmc/entities/user/bot/MyBot.java
Normal file
37
src/main/java/cn/wzpmc/entities/user/bot/MyBot.java
Normal file
@ -0,0 +1,37 @@
|
||||
package cn.wzpmc.entities.user.bot;
|
||||
|
||||
import cn.wzpmc.api.message.MessageComponent;
|
||||
import cn.wzpmc.api.message.StringMessage;
|
||||
import cn.wzpmc.api.message.json.JsonMessage;
|
||||
import cn.wzpmc.api.user.IBot;
|
||||
import cn.wzpmc.configuration.Configuration;
|
||||
import cn.wzpmc.plugins.CommandManager;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
/**
|
||||
* 机器人实现类
|
||||
* @author wzp
|
||||
* @since 2024/7/30 下午11:46
|
||||
* @version 0.0.1-dev
|
||||
*/
|
||||
@Log4j2
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class MyBot implements IBot {
|
||||
private final Configuration configuration;
|
||||
private final Long id;
|
||||
private final Long name;
|
||||
private final CommandManager commandManager = new CommandManager();
|
||||
|
||||
@Override
|
||||
public void sendMessage(MessageComponent messageComponent) {
|
||||
if (messageComponent instanceof StringMessage){
|
||||
log.info(messageComponent.toMessageString());
|
||||
}
|
||||
if (messageComponent instanceof JsonMessage){
|
||||
log.info(((JsonMessage) messageComponent).toTextDisplay());
|
||||
}
|
||||
}
|
||||
}
|
31
src/main/java/cn/wzpmc/network/PacketHandler.java
Normal file
31
src/main/java/cn/wzpmc/network/PacketHandler.java
Normal file
@ -0,0 +1,31 @@
|
||||
package cn.wzpmc.network;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
/**
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午12:14
|
||||
*/
|
||||
@Log4j2
|
||||
@RequiredArgsConstructor
|
||||
public class PacketHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
|
||||
private final WebSocketClientHandshaker handshaker;
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
log.debug("开始WebSocket握手");
|
||||
this.handshaker.handshake(ctx.channel());
|
||||
log.debug("握手完成");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext channelHandlerContext, WebSocketFrame webSocketFrame) throws Exception {
|
||||
System.out.println(webSocketFrame);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.wzpmc.network;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.handler.codec.http.HttpClientCodec;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* WebSocket连接初始化
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午1:19
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class WebSocketChannelInitializer extends ChannelInitializer<SocketChannel> {
|
||||
private final ChannelHandler handler;
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||
ChannelPipeline pipeline = socketChannel.pipeline();
|
||||
pipeline.addLast(new HttpClientCodec());
|
||||
pipeline.addLast(new ChunkedWriteHandler());
|
||||
pipeline.addLast(new HttpObjectAggregator(64 * 1024));
|
||||
pipeline.addLast(handler);
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package cn.wzpmc.network;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* 此类用于建立WebSocket连接
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/30 下午11:54
|
||||
*/
|
||||
@Log4j2
|
||||
public class WebSocketConnectionHandler {
|
||||
private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
|
||||
/**
|
||||
* 建立连接
|
||||
* @author wzp
|
||||
* @since 2024/7/30 下午11:55 v0.0.1-dev
|
||||
* @param websocket websocket连接地址
|
||||
*/
|
||||
public ChannelFuture connect(URI websocket){
|
||||
log.info("正在连接websocket");
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
WebSocketClientHandshaker clientHandshaker = WebSocketClientHandshakerFactory.newHandshaker(websocket, WebSocketVersion.V13, null, false, new DefaultHttpHeaders());
|
||||
PacketHandler handler = new PacketHandler(clientHandshaker);
|
||||
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new WebSocketChannelInitializer(handler));
|
||||
return bootstrap.connect(websocket.getHost(), websocket.getPort());
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制结束通信
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午2:04 v0.0.1-dev
|
||||
*/
|
||||
public void kill(){
|
||||
this.eventLoopGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
96
src/main/java/cn/wzpmc/plugins/CommandManager.java
Normal file
96
src/main/java/cn/wzpmc/plugins/CommandManager.java
Normal file
@ -0,0 +1,96 @@
|
||||
package cn.wzpmc.plugins;
|
||||
|
||||
import cn.wzpmc.api.commands.BrigadierCommand;
|
||||
import cn.wzpmc.api.commands.RawCommand;
|
||||
import cn.wzpmc.api.plugins.ICommandManager;
|
||||
import cn.wzpmc.api.user.CommandSender;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.suggestion.Suggestion;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 指令管理器实现类
|
||||
* @author wzp
|
||||
* @version 0.0.1-dev
|
||||
* @since 2024/7/31 上午3:13
|
||||
*/
|
||||
@Log4j2
|
||||
@NoArgsConstructor
|
||||
public class CommandManager implements ICommandManager {
|
||||
private final CommandDispatcher<CommandSender> dispatcher = new CommandDispatcher<>();
|
||||
private final ConcurrentHashMap<String, RawCommand> rawCommands = new ConcurrentHashMap<>();
|
||||
@Override
|
||||
public void registerCommand(RawCommand rawCommand, String name) {
|
||||
if (rawCommands.containsKey(name)){
|
||||
log.error("指令{}已经被注册,注册失败!", name);
|
||||
return;
|
||||
}
|
||||
this.rawCommands.put(name, rawCommand);
|
||||
}
|
||||
@Override
|
||||
public void registerCommand(BrigadierCommand brigadierCommand){
|
||||
dispatcher.register(brigadierCommand.getCommandNode());
|
||||
}
|
||||
private static final class CommandPart {
|
||||
private final String name;
|
||||
private final List<String> args;
|
||||
public CommandPart(String rawCommandLine) {
|
||||
List<String> list = Arrays.asList(rawCommandLine.split(" "));
|
||||
this.name = list.get(0);
|
||||
this.args = list.subList(1, list.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行指令
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:35 v0.0.1-dev
|
||||
* @param sender 发送者
|
||||
* @param rawCommandLine 完整命令行
|
||||
* @return 是否执行成功
|
||||
*/
|
||||
public boolean execute(CommandSender sender, String rawCommandLine){
|
||||
CommandPart commandPart = new CommandPart(rawCommandLine);
|
||||
if (rawCommands.containsKey(commandPart.name)) {
|
||||
return rawCommands.get(commandPart.name).onExecute(sender, commandPart.args);
|
||||
}else {
|
||||
try {
|
||||
dispatcher.execute(rawCommandLine, sender);
|
||||
} catch (CommandSyntaxException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* tab补全的结果
|
||||
* @author wzp
|
||||
* @since 2024/7/31 上午3:36 v0.0.1-dev
|
||||
* @param sender 消息发送者
|
||||
* @param rawCommandLine 完整命令行
|
||||
* @return 所有被补全的指令
|
||||
*/
|
||||
@SneakyThrows
|
||||
public List<String> tabComplete(CommandSender sender, String rawCommandLine){
|
||||
CommandPart commandPart = new CommandPart(rawCommandLine);
|
||||
List<String> result = new ArrayList<>();
|
||||
if (rawCommands.containsKey(commandPart.name)) {
|
||||
result.addAll(rawCommands.get(commandPart.name).onTabComplete(sender, commandPart.args));
|
||||
}
|
||||
Suggestions suggestions = dispatcher.getCompletionSuggestions(dispatcher.parse(rawCommandLine, sender)).get();
|
||||
result.addAll(suggestions.getList().stream().map(Suggestion::getText).collect(Collectors.toList()));
|
||||
return result;
|
||||
}
|
||||
}
|
43
src/main/java/cn/wzpmc/utils/TemplateFileUtils.java
Normal file
43
src/main/java/cn/wzpmc/utils/TemplateFileUtils.java
Normal file
@ -0,0 +1,43 @@
|
||||
package cn.wzpmc.utils;
|
||||
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* 模板文件工具类
|
||||
* @author wzp
|
||||
* @since 2024/07/30 23:28:25
|
||||
* @version 0.0.1-dev
|
||||
*/
|
||||
@Log4j2
|
||||
public class TemplateFileUtils {
|
||||
/**
|
||||
* 写入默认配置文件
|
||||
* @param loader 读取默认配置所使用的类加载器
|
||||
* @param path 默认配置的路径
|
||||
* @param saved 保存到的文件
|
||||
* @return 是否写入
|
||||
*/
|
||||
public static boolean saveDefaultConfig(ClassLoader loader, String path, File saved){
|
||||
log.debug("创建默认配置文件从ClassLoader {} -> {} ==> {}", loader, path, saved);
|
||||
try(InputStream sourceInputStream = loader.getResourceAsStream(path)){
|
||||
if (sourceInputStream == null){
|
||||
throw new RuntimeException(new FileNotFoundException("Didn't find " + path + " from class loader: " + loader.getName()));
|
||||
}
|
||||
if (saved.exists()){
|
||||
return false;
|
||||
}
|
||||
if (!saved.createNewFile()) {
|
||||
throw new IOException("Cannot create file " + saved.getAbsolutePath());
|
||||
}
|
||||
try(FileOutputStream targetFileStream = new FileOutputStream(saved)){
|
||||
sourceInputStream.transferTo(targetFileStream);
|
||||
}
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
log.throwing(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
50
src/main/java/cn/wzpmc/utils/YamlUtils.java
Normal file
50
src/main/java/cn/wzpmc/utils/YamlUtils.java
Normal file
@ -0,0 +1,50 @@
|
||||
package cn.wzpmc.utils;
|
||||
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Yaml工具类
|
||||
* @author wzp
|
||||
* @since 2024/7/30 下午11:46
|
||||
* @version 0.0.1-dev
|
||||
*/
|
||||
@Log4j2
|
||||
public class YamlUtils {
|
||||
/**
|
||||
* 读取Yaml文件并将其序列化为一个类
|
||||
* @param file yaml文件
|
||||
* @param clazz 需要序列化的类
|
||||
* @return 一个对象
|
||||
* @param <T> 序列化的类型(需要空参构造方法)
|
||||
*/
|
||||
public static <T> T readYamlFile(File file, Class<T> clazz){
|
||||
log.debug("读取Yaml文件 {},并写入到类 {}", file, clazz);
|
||||
try(FileInputStream fis = new FileInputStream(file)){
|
||||
Yaml yaml = new Yaml();
|
||||
return yaml.loadAs(fis, clazz);
|
||||
} catch (IOException e) {
|
||||
log.throwing(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一个类序列化为Yaml文件
|
||||
* @param file yaml文件
|
||||
* @param obj 数据类
|
||||
* @param <T> 序列化的对象
|
||||
*/
|
||||
public static <T> void writeYamlFile(File file, T obj){
|
||||
log.debug("将对象:{} 写入Yaml文件:{}中", obj, file);
|
||||
try(FileWriter writer = new FileWriter(file)){
|
||||
Yaml yaml = new Yaml();
|
||||
yaml.dump(obj, writer);
|
||||
} catch (IOException e) {
|
||||
log.throwing(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user