feat: code
This commit is contained in:
51
.gitea/workflows/publish.yaml
Normal file
51
.gitea/workflows/publish.yaml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
name: Build Mineroo Network
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: [ "v*" ]
|
||||||
|
workflow_dispatch:
|
||||||
|
jobs:
|
||||||
|
build-all:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# 1. 检出代码
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# 2. 设置 JDK 环境
|
||||||
|
- name: Set up JDK 21
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '21'
|
||||||
|
distribution: 'temurin'
|
||||||
|
cache: 'gradle' # 开启缓存,加速多模块构建
|
||||||
|
|
||||||
|
# 3. 赋予 Gradle 执行权限
|
||||||
|
- name: Grant execute permission for gradlew
|
||||||
|
run: chmod +x gradlew
|
||||||
|
|
||||||
|
# 4. 执行全量构建
|
||||||
|
- name: Build All Modules
|
||||||
|
run: ./gradlew clean build shadowJar -x test --parallel
|
||||||
|
|
||||||
|
# 5. 整理构建产物 (可选,但推荐)
|
||||||
|
- name: Collect Artifacts
|
||||||
|
run: |
|
||||||
|
mkdir dist
|
||||||
|
|
||||||
|
find velocity/build/libs -name "*.jar" -exec cp {} dist/ \;
|
||||||
|
|
||||||
|
# find paper/build/libs -name "*.jar" -exec cp {} dist/ \;
|
||||||
|
# find fabric/build/libs -name "*.jar" -exec cp {} dist/ \;
|
||||||
|
|
||||||
|
echo "Collected artifacts:"
|
||||||
|
ls -l dist/
|
||||||
|
|
||||||
|
# 6. 上传所有 Jar 包
|
||||||
|
- name: Upload All Plugins
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: mineroo-plugins
|
||||||
|
path: dist/*.jar
|
||||||
|
retention-days: 7
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
|
<classpathentry kind="src" output="bin/main" path="src/main/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="gradle_scope" value="main"/>
|
||||||
|
<attribute name="gradle_used_by_scope" value="main,test"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21/"/>
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21/"/>
|
||||||
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
|
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
|
||||||
<classpathentry kind="output" path="bin/default"/>
|
<classpathentry kind="output" path="bin/default"/>
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package online.mineroo.common;
|
||||||
|
|
||||||
|
public class ProtocolConstants {
|
||||||
|
// Protocol channel name
|
||||||
|
public static String PROTOCOL_CHANNEL = "mineroo:plugin:api";
|
||||||
|
|
||||||
|
// Event names
|
||||||
|
public static String BIND_USER_REQUEST = "user-bind-request";
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
package online.mineroo.common;
|
|
||||||
|
|
||||||
public class ProtocolConstants {
|
|
||||||
}
|
|
||||||
BIN
kls_database.db
BIN
kls_database.db
Binary file not shown.
@@ -27,6 +27,8 @@ dependencies {
|
|||||||
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
|
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
|
||||||
implementation(libs.guava)
|
implementation(libs.guava)
|
||||||
|
|
||||||
|
implementation(project(":common"))
|
||||||
|
|
||||||
compileOnly("com.velocitypowered:velocity-api:3.4.0-SNAPSHOT")
|
compileOnly("com.velocitypowered:velocity-api:3.4.0-SNAPSHOT")
|
||||||
annotationProcessor("com.velocitypowered:velocity-api:3.4.0-SNAPSHOT")
|
annotationProcessor("com.velocitypowered:velocity-api:3.4.0-SNAPSHOT")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
|||||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||||
import org.spongepowered.configurate.objectmapping.meta.Setting;
|
import org.spongepowered.configurate.objectmapping.meta.Setting;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration class for the Mineroo Velocity plugin.
|
||||||
|
* <p>
|
||||||
|
* This class holds the main server configuration, including server name, description,
|
||||||
|
* and server binding details such as address, port, and token. It uses the Configurate
|
||||||
|
* library for serialization and supports comments for each field.
|
||||||
|
*/
|
||||||
@ConfigSerializable
|
@ConfigSerializable
|
||||||
public class Config {
|
public class Config {
|
||||||
|
|
||||||
@@ -16,8 +23,12 @@ public class Config {
|
|||||||
@Setting("bind")
|
@Setting("bind")
|
||||||
private ServerSection server = new ServerSection();
|
private ServerSection server = new ServerSection();
|
||||||
|
|
||||||
@ConfigSerializable
|
@ConfigSerializable
|
||||||
public static class ServerSection {
|
/**
|
||||||
|
* Represents the server binding section of the configuration.
|
||||||
|
* Contains address, port, and bind token for the server.
|
||||||
|
*/
|
||||||
|
public static class ServerSection {
|
||||||
|
|
||||||
@Setting("address")
|
@Setting("address")
|
||||||
@Comment("Server Address")
|
@Comment("Server Address")
|
||||||
@@ -31,29 +42,53 @@ public class Config {
|
|||||||
@Comment("Server Bind Token")
|
@Comment("Server Bind Token")
|
||||||
private String bindToken = "get token from `mineroo.online/resources/servers` page!";
|
private String bindToken = "get token from `mineroo.online/resources/servers` page!";
|
||||||
|
|
||||||
public String getAddress() {
|
/**
|
||||||
|
* Gets the server address.
|
||||||
|
* @return the server address
|
||||||
|
*/
|
||||||
|
public String getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getPort() {
|
/**
|
||||||
|
* Gets the server port.
|
||||||
|
* @return the server port
|
||||||
|
*/
|
||||||
|
public Integer getPort() {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBindToken() {
|
/**
|
||||||
|
* Gets the server bind token.
|
||||||
|
* @return the bind token
|
||||||
|
*/
|
||||||
|
public String getBindToken() {
|
||||||
return bindToken;
|
return bindToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServerName() {
|
/**
|
||||||
|
* Gets the server bind name.
|
||||||
|
* @return the server name
|
||||||
|
*/
|
||||||
|
public String getServerName() {
|
||||||
return serverName;
|
return serverName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription() {
|
/**
|
||||||
|
* Gets the server bind description.
|
||||||
|
* @return the server description
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerSection getServer() {
|
/**
|
||||||
|
* Gets the server binding section.
|
||||||
|
* @return the server section
|
||||||
|
*/
|
||||||
|
public ServerSection getServer() {
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package online.mineroo.velocity;
|
package online.mineroo.velocity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main plugin class for Mineroo Velocity.
|
||||||
|
* Handles plugin initialization, configuration loading, and provides access to core components.
|
||||||
|
*/
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.velocitypowered.api.command.CommandManager;
|
import com.velocitypowered.api.command.CommandManager;
|
||||||
import com.velocitypowered.api.event.Subscribe;
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
@@ -26,16 +30,29 @@ import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
|||||||
"YuKun Liu" })
|
"YuKun Liu" })
|
||||||
public class MinerooPlugin {
|
public class MinerooPlugin {
|
||||||
|
|
||||||
|
// Reference to the Velocity ProxyServer instance
|
||||||
private final ProxyServer server;
|
private final ProxyServer server;
|
||||||
|
// Logger for plugin messages
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
|
// Directory where plugin data (like config files) is stored
|
||||||
private final Path dataDirectory;
|
private final Path dataDirectory;
|
||||||
|
// Plugin configuration object
|
||||||
private Config config;
|
private Config config;
|
||||||
|
|
||||||
|
// Listener for bind events
|
||||||
private BindListener bindListener;
|
private BindListener bindListener;
|
||||||
|
|
||||||
|
// Manages plugin messages and localization
|
||||||
private MessageManager messageManager;
|
private MessageManager messageManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for dependency injection.
|
||||||
|
*
|
||||||
|
* @param server Velocity ProxyServer instance
|
||||||
|
* @param logger Logger instance
|
||||||
|
* @param dataDirectory Directory for plugin data
|
||||||
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
public MinerooPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
|
public MinerooPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
@@ -45,20 +62,27 @@ public class MinerooPlugin {
|
|||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onProxyInitialization(ProxyInitializeEvent event) {
|
public void onProxyInitialization(ProxyInitializeEvent event) {
|
||||||
|
// Register event listeners
|
||||||
this.bindListener = new BindListener();
|
this.bindListener = new BindListener();
|
||||||
server.getEventManager().register(this, bindListener);
|
server.getEventManager().register(this, bindListener);
|
||||||
|
|
||||||
|
// Load configuration
|
||||||
reloadConfig();
|
reloadConfig();
|
||||||
|
|
||||||
|
// Initialize message manager
|
||||||
this.messageManager = new MessageManager(config);
|
this.messageManager = new MessageManager(config);
|
||||||
|
|
||||||
|
// Register main command
|
||||||
CommandManager commandManager = server.getCommandManager();
|
CommandManager commandManager = server.getCommandManager();
|
||||||
commandManager.register(commandManager.metaBuilder("mineroo").build(),
|
commandManager.register(commandManager.metaBuilder("mineroo").build(),
|
||||||
new MainCommand(this));
|
new MainCommand(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// load & create config
|
/**
|
||||||
|
* Loads or creates the plugin configuration file.
|
||||||
|
*
|
||||||
|
* @return true if config loaded successfully, false otherwise
|
||||||
|
*/
|
||||||
public boolean reloadConfig() {
|
public boolean reloadConfig() {
|
||||||
try {
|
try {
|
||||||
if (Files.notExists(dataDirectory)) {
|
if (Files.notExists(dataDirectory)) {
|
||||||
@@ -90,22 +114,27 @@ public class MinerooPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getter for ProxyServer instance
|
||||||
public ProxyServer getServer() {
|
public ProxyServer getServer() {
|
||||||
return this.server;
|
return this.server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getter for Logger instance
|
||||||
public Logger getLogger() {
|
public Logger getLogger() {
|
||||||
return logger;
|
return logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getter for Config instance
|
||||||
public Config getConfig() {
|
public Config getConfig() {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getter for BindListener instance
|
||||||
public BindListener getBindListener() {
|
public BindListener getBindListener() {
|
||||||
return bindListener;
|
return bindListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getter for MessageManager instance
|
||||||
public MessageManager getMessageManager() {
|
public MessageManager getMessageManager() {
|
||||||
return messageManager;
|
return messageManager;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,13 @@ public class MainCommand implements SimpleCommand {
|
|||||||
BindRequest request = new BindRequest(logger, bind_token);
|
BindRequest request = new BindRequest(logger, bind_token);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// Status check before initial bind
|
||||||
|
if (request.checkBindStatus()) {
|
||||||
|
source.sendMessage(msg.get("command.bind.server.already-bound"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
boolean inital_bind = request.initalMotdVerifyRequest(bind_address, bind_port);
|
boolean inital_bind = request.initalMotdVerifyRequest(bind_address, bind_port);
|
||||||
if (inital_bind) {
|
if (inital_bind) {
|
||||||
String motdToken = request.getMotdToken();
|
String motdToken = request.getMotdToken();
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import com.velocitypowered.api.event.Subscribe;
|
|||||||
import com.velocitypowered.api.event.connection.PluginMessageEvent;
|
import com.velocitypowered.api.event.connection.PluginMessageEvent;
|
||||||
import com.velocitypowered.api.proxy.ServerConnection;
|
import com.velocitypowered.api.proxy.ServerConnection;
|
||||||
|
|
||||||
|
import online.mineroo.common.ProtocolConstants;
|
||||||
|
|
||||||
public class ChannelListener {
|
public class ChannelListener {
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onPluginMessage(PluginMessageEvent event) {
|
public void onPluginMessage(PluginMessageEvent event) {
|
||||||
if (!event.getIdentifier().getId().equals("mineroo:api"))
|
if (!event.getIdentifier().getId().equals(ProtocolConstants.PROTOCOL_CHANNEL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(event.getSource() instanceof ServerConnection))
|
if (!(event.getSource() instanceof ServerConnection))
|
||||||
|
|||||||
@@ -15,18 +15,53 @@ import com.google.gson.JsonObject;
|
|||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BindRequest handles server binding and verification with the Mineroo API.
|
||||||
|
* <p>
|
||||||
|
* This class provides methods to:
|
||||||
|
* <ul>
|
||||||
|
* <li>Check if the server is bound using the bind token</li>
|
||||||
|
* <li>Initiate a MOTD verification request</li>
|
||||||
|
* <li>Finalize the server binding with additional server details</li>
|
||||||
|
* </ul>
|
||||||
|
* It manages authentication, HTTP requests, and response parsing for the binding process.
|
||||||
|
*/
|
||||||
public class BindRequest {
|
public class BindRequest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base endpoint for Mineroo API requests.
|
||||||
|
*/
|
||||||
private static final String endpoint = "https://oapi.mineroo.online";
|
private static final String endpoint = "https://oapi.mineroo.online";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger instance for logging errors and information.
|
||||||
|
*/
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
/**
|
||||||
|
* HTTP client used for sending requests to the Mineroo API.
|
||||||
|
*/
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bind token used for authenticating API requests.
|
||||||
|
*/
|
||||||
private final String bindToken;
|
private final String bindToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MOTD token received from the API after verification.
|
||||||
|
*/
|
||||||
private String motdToken = "";
|
private String motdToken = "";
|
||||||
|
/**
|
||||||
|
* The session token received from the API after verification.
|
||||||
|
*/
|
||||||
private String sessionToken = "";
|
private String sessionToken = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a BindRequest instance.
|
||||||
|
*
|
||||||
|
* @param logger Logger for logging errors and information
|
||||||
|
* @param bindToken The bind token for API authentication
|
||||||
|
*/
|
||||||
public BindRequest(Logger logger, String bindToken) {
|
public BindRequest(Logger logger, String bindToken) {
|
||||||
|
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
@@ -35,6 +70,50 @@ public class BindRequest {
|
|||||||
this.httpClient = HttpClient.newHttpClient();
|
this.httpClient = HttpClient.newHttpClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the bind status from the oapi.mineroo.online API.
|
||||||
|
*
|
||||||
|
* @return true if status is 'bound', false otherwise
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Checks the bind status from the oapi.mineroo.online API.
|
||||||
|
*
|
||||||
|
* @return true if status is 'bound', false otherwise
|
||||||
|
*/
|
||||||
|
public boolean checkBindStatus() {
|
||||||
|
String uri = endpoint + "/server/server-bind-status";
|
||||||
|
String basicAuth = "mbind:" + bindToken;
|
||||||
|
String encodedAuth = Base64.getEncoder().encodeToString(basicAuth.getBytes(StandardCharsets.UTF_8));
|
||||||
|
try {
|
||||||
|
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(uri))
|
||||||
|
.header("Authorization", "Basic " + encodedAuth)
|
||||||
|
.GET().build();
|
||||||
|
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
if (response.statusCode() == 200) {
|
||||||
|
JsonObject responseData = JsonParser.parseString(response.body()).getAsJsonObject();
|
||||||
|
boolean bound = responseData.has("bound") && responseData.get("bound").getAsBoolean();
|
||||||
|
if (bound) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
logger.error("Mineroo Bind: Server not bound. 'bound' field is false.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.error("Mineroo Bind: Failed to check bind status. Response: " + response.body());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Mineroo Bind: Exception while checking bind status", e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiates a MOTD verification request to the Mineroo API.
|
||||||
|
*
|
||||||
|
* @param hostname The server hostname
|
||||||
|
* @param port The server port
|
||||||
|
* @return true if both motd_token and session_token are received, false otherwise
|
||||||
|
* @throws IOException, InterruptedException, JsonParseException on request or parsing failure
|
||||||
|
*/
|
||||||
public boolean initalMotdVerifyRequest(String hostname, Integer port)
|
public boolean initalMotdVerifyRequest(String hostname, Integer port)
|
||||||
throws IOException, InterruptedException, JsonParseException {
|
throws IOException, InterruptedException, JsonParseException {
|
||||||
|
|
||||||
@@ -83,8 +162,17 @@ public class BindRequest {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalizes the server binding by sending server details to the Mineroo API.
|
||||||
|
*
|
||||||
|
* @param name The server name (nullable)
|
||||||
|
* @param description The server description (nullable)
|
||||||
|
* @return true if the binding is successful (HTTP 200), false otherwise
|
||||||
|
* @throws IOException, InterruptedException, JsonParseException on request or parsing failure
|
||||||
|
*/
|
||||||
public boolean finalizeServerBinding(@Nullable String name, @Nullable String description)
|
public boolean finalizeServerBinding(@Nullable String name, @Nullable String description)
|
||||||
throws IOException, InterruptedException, JsonParseException {
|
throws IOException, InterruptedException, JsonParseException {
|
||||||
|
|
||||||
String uri = endpoint + "/server/server-bind";
|
String uri = endpoint + "/server/server-bind";
|
||||||
|
|
||||||
JsonObject json = new JsonObject();
|
JsonObject json = new JsonObject();
|
||||||
@@ -106,6 +194,11 @@ public class BindRequest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the MOTD token received from the API.
|
||||||
|
*
|
||||||
|
* @return the motdToken string
|
||||||
|
*/
|
||||||
public String getMotdToken() {
|
public String getMotdToken() {
|
||||||
return motdToken;
|
return motdToken;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# Command Bind
|
# Command Bind
|
||||||
|
command.bind.server.already-bound=<yellow>当前服务器已在 Mineroo.Online 处于绑定状态。</yellow>
|
||||||
command.bind.server.start=<gray>开始服务器绑定流程,请稍等...</gray>
|
command.bind.server.start=<gray>开始服务器绑定流程,请稍等...</gray>
|
||||||
command.bind.server.inital.failed=<red>初次握手失败。检查您的令牌或网络。</red>
|
command.bind.server.inital.failed=<red>初次握手失败。检查您的令牌或网络。</red>
|
||||||
command.bind.server.wait=<aqua>正在验证服务器所有权... 数据同步可能需要 2 分钟,请稍候。</aqua>
|
command.bind.server.wait=<aqua>正在验证服务器所有权... 数据同步可能需要 2 分钟,请稍候。</aqua>
|
||||||
|
|||||||
Reference in New Issue
Block a user