diff --git a/.gitea/workflows/publish.yaml b/.gitea/workflows/publish.yaml new file mode 100644 index 0000000..8dfff20 --- /dev/null +++ b/.gitea/workflows/publish.yaml @@ -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 diff --git a/common/.classpath b/common/.classpath index 0a3280e..96c4014 100644 --- a/common/.classpath +++ b/common/.classpath @@ -1,5 +1,11 @@ + + + + + + diff --git a/common/src/main/java/online/mineroo/common/ProtocolConstants.java b/common/src/main/java/online/mineroo/common/ProtocolConstants.java new file mode 100644 index 0000000..7a60f23 --- /dev/null +++ b/common/src/main/java/online/mineroo/common/ProtocolConstants.java @@ -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"; +} diff --git a/common/src/online/mineroo/common/ProtocolConstants.java b/common/src/online/mineroo/common/ProtocolConstants.java deleted file mode 100644 index 7b62d9d..0000000 --- a/common/src/online/mineroo/common/ProtocolConstants.java +++ /dev/null @@ -1,4 +0,0 @@ -package online.mineroo.common; - -public class ProtocolConstants { -} diff --git a/kls_database.db b/kls_database.db index 2ea29d5..1f9c905 100644 Binary files a/kls_database.db and b/kls_database.db differ diff --git a/velocity/build.gradle.kts b/velocity/build.gradle.kts index 6ac479a..492f7a7 100644 --- a/velocity/build.gradle.kts +++ b/velocity/build.gradle.kts @@ -27,6 +27,8 @@ dependencies { // This dependency is used internally, and not exposed to consumers on their own compile classpath. implementation(libs.guava) + implementation(project(":common")) + compileOnly("com.velocitypowered:velocity-api:3.4.0-SNAPSHOT") annotationProcessor("com.velocitypowered:velocity-api:3.4.0-SNAPSHOT") } diff --git a/velocity/src/main/java/online/mineroo/velocity/Config.java b/velocity/src/main/java/online/mineroo/velocity/Config.java index 3a068d6..a05ec23 100644 --- a/velocity/src/main/java/online/mineroo/velocity/Config.java +++ b/velocity/src/main/java/online/mineroo/velocity/Config.java @@ -4,6 +4,13 @@ import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.meta.Comment; import org.spongepowered.configurate.objectmapping.meta.Setting; +/** + * Configuration class for the Mineroo Velocity plugin. + *

+ * 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 public class Config { @@ -16,8 +23,12 @@ public class Config { @Setting("bind") private ServerSection server = new ServerSection(); - @ConfigSerializable - public static class ServerSection { +@ConfigSerializable + /** + * Represents the server binding section of the configuration. + * Contains address, port, and bind token for the server. + */ + public static class ServerSection { @Setting("address") @Comment("Server Address") @@ -31,29 +42,53 @@ public class Config { @Comment("Server Bind Token") 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; } - public Integer getPort() { +/** + * Gets the server port. + * @return the server port + */ + public Integer getPort() { return port; } - public String getBindToken() { +/** + * Gets the server bind token. + * @return the bind token + */ + public String getBindToken() { return bindToken; } } - public String getServerName() { +/** + * Gets the server bind name. + * @return the server name + */ + public String getServerName() { return serverName; } - public String getDescription() { +/** + * Gets the server bind description. + * @return the server description + */ + public String getDescription() { return description; } - public ServerSection getServer() { +/** + * Gets the server binding section. + * @return the server section + */ + public ServerSection getServer() { return server; } diff --git a/velocity/src/main/java/online/mineroo/velocity/MinerooPlugin.java b/velocity/src/main/java/online/mineroo/velocity/MinerooPlugin.java index 8e06d5a..a37f920 100644 --- a/velocity/src/main/java/online/mineroo/velocity/MinerooPlugin.java +++ b/velocity/src/main/java/online/mineroo/velocity/MinerooPlugin.java @@ -1,5 +1,9 @@ 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.velocitypowered.api.command.CommandManager; import com.velocitypowered.api.event.Subscribe; @@ -26,16 +30,29 @@ import org.spongepowered.configurate.yaml.YamlConfigurationLoader; "YuKun Liu" }) public class MinerooPlugin { + // Reference to the Velocity ProxyServer instance private final ProxyServer server; + // Logger for plugin messages private final Logger logger; + // Directory where plugin data (like config files) is stored private final Path dataDirectory; + // Plugin configuration object private Config config; + // Listener for bind events private BindListener bindListener; + // Manages plugin messages and localization private MessageManager messageManager; + /** + * Constructor for dependency injection. + * + * @param server Velocity ProxyServer instance + * @param logger Logger instance + * @param dataDirectory Directory for plugin data + */ @Inject public MinerooPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { this.server = server; @@ -45,20 +62,27 @@ public class MinerooPlugin { @Subscribe public void onProxyInitialization(ProxyInitializeEvent event) { - + // Register event listeners this.bindListener = new BindListener(); server.getEventManager().register(this, bindListener); + // Load configuration reloadConfig(); + // Initialize message manager this.messageManager = new MessageManager(config); + // Register main command CommandManager commandManager = server.getCommandManager(); commandManager.register(commandManager.metaBuilder("mineroo").build(), new MainCommand(this)); } - // load & create config + /** + * Loads or creates the plugin configuration file. + * + * @return true if config loaded successfully, false otherwise + */ public boolean reloadConfig() { try { if (Files.notExists(dataDirectory)) { @@ -90,22 +114,27 @@ public class MinerooPlugin { } } + // Getter for ProxyServer instance public ProxyServer getServer() { return this.server; } + // Getter for Logger instance public Logger getLogger() { return logger; } + // Getter for Config instance public Config getConfig() { return config; } + // Getter for BindListener instance public BindListener getBindListener() { return bindListener; } + // Getter for MessageManager instance public MessageManager getMessageManager() { return messageManager; } diff --git a/velocity/src/main/java/online/mineroo/velocity/TomlConfigurationLoader.java b/velocity/src/main/java/online/mineroo/velocity/TomlConfigurationLoader.java deleted file mode 100644 index e69de29..0000000 diff --git a/velocity/src/main/java/online/mineroo/velocity/commands/MainCommand.java b/velocity/src/main/java/online/mineroo/velocity/commands/MainCommand.java index 44702a1..3c1ea6b 100644 --- a/velocity/src/main/java/online/mineroo/velocity/commands/MainCommand.java +++ b/velocity/src/main/java/online/mineroo/velocity/commands/MainCommand.java @@ -99,6 +99,13 @@ public class MainCommand implements SimpleCommand { BindRequest request = new BindRequest(logger, bind_token); 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); if (inital_bind) { String motdToken = request.getMotdToken(); diff --git a/velocity/src/main/java/online/mineroo/velocity/listeners/ChannelListener.java b/velocity/src/main/java/online/mineroo/velocity/listeners/ChannelListener.java index 6a693a9..9815b30 100644 --- a/velocity/src/main/java/online/mineroo/velocity/listeners/ChannelListener.java +++ b/velocity/src/main/java/online/mineroo/velocity/listeners/ChannelListener.java @@ -5,10 +5,12 @@ import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.connection.PluginMessageEvent; import com.velocitypowered.api.proxy.ServerConnection; +import online.mineroo.common.ProtocolConstants; + public class ChannelListener { @Subscribe public void onPluginMessage(PluginMessageEvent event) { - if (!event.getIdentifier().getId().equals("mineroo:api")) + if (!event.getIdentifier().getId().equals(ProtocolConstants.PROTOCOL_CHANNEL)) return; if (!(event.getSource() instanceof ServerConnection)) diff --git a/velocity/src/main/java/online/mineroo/velocity/utils/BindRequest.java b/velocity/src/main/java/online/mineroo/velocity/utils/BindRequest.java index 117d73e..7d699b8 100644 --- a/velocity/src/main/java/online/mineroo/velocity/utils/BindRequest.java +++ b/velocity/src/main/java/online/mineroo/velocity/utils/BindRequest.java @@ -15,18 +15,53 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; +/** + * BindRequest handles server binding and verification with the Mineroo API. + *

+ * This class provides methods to: + *

    + *
  • Check if the server is bound using the bind token
  • + *
  • Initiate a MOTD verification request
  • + *
  • Finalize the server binding with additional server details
  • + *
+ * It manages authentication, HTTP requests, and response parsing for the binding process. + */ public class BindRequest { + /** + * The base endpoint for Mineroo API requests. + */ private static final String endpoint = "https://oapi.mineroo.online"; + /** + * Logger instance for logging errors and information. + */ private final Logger logger; + /** + * HTTP client used for sending requests to the Mineroo API. + */ private final HttpClient httpClient; + /** + * The bind token used for authenticating API requests. + */ private final String bindToken; + /** + * The MOTD token received from the API after verification. + */ private String motdToken = ""; + /** + * The session token received from the API after verification. + */ 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) { this.logger = logger; @@ -35,6 +70,50 @@ public class BindRequest { 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 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) throws IOException, InterruptedException, JsonParseException { @@ -83,8 +162,17 @@ public class BindRequest { 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) throws IOException, InterruptedException, JsonParseException { + String uri = endpoint + "/server/server-bind"; 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() { return motdToken; } diff --git a/velocity/src/main/resources/mineroo/messages.properties b/velocity/src/main/resources/mineroo/messages.properties index 9324560..ced46f1 100644 --- a/velocity/src/main/resources/mineroo/messages.properties +++ b/velocity/src/main/resources/mineroo/messages.properties @@ -1,4 +1,5 @@ # Command Bind +command.bind.server.already-bound=当前服务器已在 Mineroo.Online 处于绑定状态。 command.bind.server.start=开始服务器绑定流程,请稍等... command.bind.server.inital.failed=初次握手失败。检查您的令牌或网络。 command.bind.server.wait=正在验证服务器所有权... 数据同步可能需要 2 分钟,请稍候。