feat: code

This commit is contained in:
2025-12-09 15:56:44 -08:00
parent bcd611a03e
commit 3153b8d5e7
13 changed files with 246 additions and 15 deletions

View File

@@ -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")
}

View File

@@ -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.
* <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
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;
}

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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))

View File

@@ -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.
* <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 {
/**
* 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<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)
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;
}

View File

@@ -1,4 +1,5 @@
# Command Bind
command.bind.server.already-bound=<yellow>当前服务器已在 Mineroo.Online 处于绑定状态。</yellow>
command.bind.server.start=<gray>开始服务器绑定流程,请稍等...</gray>
command.bind.server.inital.failed=<red>初次握手失败。检查您的令牌或网络。</red>
command.bind.server.wait=<aqua>正在验证服务器所有权... 数据同步可能需要 2 分钟,请稍候。</aqua>