diff --git a/README.md b/README.md index 2d5d52e..32fb6f1 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,14 @@ 一个为第三方客户端开放GC命令执行接口的插件 +自 `1.7.0` 起可以通过 `|` 或者换行来分隔多条命令,例如: +```shell +/a 1 | /a 2 +/a 3 +``` + +调用 `ping` 响应数据将包含插件版本号。 + ## 使用本插件的应用 - [GrasscutterTools](https://github.com/jie65535/GrasscutterCommandGenerator) —— Windows 客户端工具 - [JGrasscutterCommand](https://github.com/jie65535/JGrasscutterCommand) —— [Mirai](https://github.com/mamoe/mirai) 插件,在QQ里执行命令 @@ -15,43 +23,13 @@ 1. 在 [Release](https://github.com/jie65535/gc-opencommand-plugin/releases) 下载 `jar` 2. 放入 `plugins` 文件夹即可 -> 注意,如果出现以下错误: -> ```log -> INFO:PluginManager Enabling plugin: opencommand-plugin -> Exception in thread "main" java.lang.NoSuchMethodError: 'void emu.grasscutter.server.event.EventHandler.register(emu.grasscutter.plugin.Plugin)' -> at com.github.jie65535.opencommand.OpenCommandPlugin.onEnable(OpenCommandPlugin.java:49) -> at emu.grasscutter.plugin.PluginManager.lambda$enablePlugins$3(PluginManager.java:131) -> ``` -> 请使用v1.2.1版本插件,因为该报错表示你的服务端是旧版! - ## 控制台连接 1. 首次启动时,会在 `plugins` 目录下生成一个 `opencommand-plugin` 目录,打开并编辑 `config.json` -2. 设置 `consoleToken` 的值为你的连接秘钥,建议使用至少32字符的长随机字符串。 +2. 设置 `consoleToken` 的值为你的连接秘钥,建议使用至少32字符的长随机字符串。(检测到为空时会自动生成) 3. 重新启动服务端即可生效配置 4. 在客户端中选择控制台身份,并填写你的 `consoleToken` 即可以控制台身份运行指令 -## 多服务器 -### 主服务器 (Dispatch) -1. 在 `opencommand-plugin` 目录下打开 `config.json` -2. 修改 `socketPort` 值为一个未被使用的端口 -3. 设置 `socketToken` 多服务器通信密钥,建议使用至少32字符的长随机字符串。 -4. 重新启动服务端即可生效配置 - -### 子服务器 (Game) -1. 在 `opencommand-plugin` 目录下打开 `config.json` -2. 修改 `socketHost` 和 `socketPort` 值为主服务器的地址和端口 -3. 设置 `socketToken` 和主服务器相同的值 -4. 设置 `socketDisplayName` 值为你的服务器名称 (用途请见[下方](https://github.com/jie65535/gc-opencommand-plugin#%E8%8E%B7%E5%8F%96%E5%A4%9A%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%88%97%E8%A1%A8)) -5. 重新启动服务端即可生效配置 - -## 构建说明 - -1. 克隆仓库 -2. 在目录下新建 `lib` 目录 -3. 将 `grasscutter-1.1.x-dev.jar` 放入 `lib` 目录 -4. `gradle build` - ## 玩家使用流程 1. 在客户端中填写服务地址,确认是否支持 @@ -66,13 +44,34 @@ 3. 使用 `token` 和**4位整数验证码**发送 `verify` 校验 4. 如果验证通过,可以使用该 `token` 执行 `command` 动作 +## 插件构建说明 + +1. 克隆仓库 +2. 在目录下新建 `lib` 目录 +3. 将 `grasscutter-1.1.x-dev.jar` 放入 `lib` 目录 +4. `gradle build` + +## 多服务器 +### 主服务器 (Dispatch) +1. 在 `opencommand-plugin` 目录下打开 `config.json` +2. 修改 `socketPort` 值为一个未被使用的端口 +3. 设置 `socketToken` 多服务器通信密钥,建议使用至少32字符的长随机字符串。 +4. 重新启动服务端即可生效配置 + +### 子服务器 (Game) +1. 在 `opencommand-plugin` 目录下打开 `config.json` +2. 修改 `socketHost` 和 `socketPort` 值为主服务器的地址和端口 +3. 设置 `socketToken` 和主服务器相同的值 +4. 设置 `socketDisplayName` 值为你的服务器名称 (用途请见[下方](https://github.com/jie65535/gc-opencommand-plugin#%E8%8E%B7%E5%8F%96%E5%A4%9A%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%88%97%E8%A1%A8)) +5. 重新启动服务端即可生效配置 + --- ## `config.json` -```json +```json5 { - // 控制台连接令牌 + // 控制台连接令牌(检测到空时会自动生成) "consoleToken": "", // 验证码过期时间(秒) "codeExpirationTime_S": 60, @@ -259,7 +258,7 @@ public final class JsonResponse { | message | `Success` | `String` | | data | `{}` | `JsonObject` | -```json +```json5 { "retcode": 200, "message": "success", diff --git a/README_en-US.md b/README_en-US.md index 2ab1804..d2b4a21 100644 --- a/README_en-US.md +++ b/README_en-US.md @@ -4,10 +4,19 @@ A plugin that opens the GC command execution interface for third-party clients +Since `1.7.0`, multiple commands can be separated by `|` or newline, for example: +```shell +/a 1 | /a 2 +/a 3 +``` + +Invoking `ping` the response data will contain the plugin version. + ## Applications using this plug-in - [GrasscutterTools](https://github.com/jie65535/GrasscutterCommandGenerator) —— Windows Client Tools - [JGrasscutterCommand](https://github.com/jie65535/JGrasscutterCommand) —— [Mirai](https://github.com/mamoe/mirai) Plugin, run commands in QQ -- TODO +- [Yunzai-GrasscutterCommand](https://github.com/Zyy-boop/Yunzai-GrasscutterCommand) —— Yunzai-bot plugin, execute commands in QQ +- More... ## Server installation @@ -19,32 +28,10 @@ A plugin that opens the GC command execution interface for third-party clients 1. When starting for the first time, a `opencommand-plugin` directory will be generated under the `plugins` directory, open and edit `config.json` 2. Set the value of `consoleToken` to your connection key. It is recommended to use a long random string of at least 32 - characters. + characters. (automatically generated when empty is detected) 3. Restart the server to take effect 4. Select the console identity in the client, and fill in your `consoleToken` to run the command as the console identity -## Multi server -### Master server (Dispatch) -1. Open `config.json` in the `opencommand-plugin` directory -2. Modify the `socketPort` value to an unused port -3. Set `sockettoken` multi server communication key. It is recommended to use a long random string of at least 32 characters. -4. Restart the server to make the configuration effective - -### Sub server (Game) -1. Open `config.json` in the `opencommand-plugin` directory -2. Modify the `sockethost` and `socketport` values to the address and port of the primary server -3. Set the same value of `sockettoken` and the primary server -4. Set the `socketDisplayName` value to your server name (See below for usage [Jump](https://github.com/jie65535/gc-opencommand-plugin/blob/master/README_en-US.md#get-mulit-server-list)) -5. Restart the server to make the configuration effective - -## Build - -1. `git clone https://github.com/jie65535/gc-opencommand-plugin` -2. `cd gc-opencommand-plugin` -3. `mkdir lib` -4. `mv path/to/grasscutter-1.x.x-dev.jar ./lib` -5. `gradle build` - ## Player 1. Fill in the service address in the client to confirm whether it supports @@ -60,19 +47,50 @@ A plugin that opens the GC command execution interface for third-party clients 3. Send `verify` check using `token` and **4-digit integer verification code** 4. If the verification is passed, you can use the `token` to execute the `command` action +## Build + +1. `git clone https://github.com/jie65535/gc-opencommand-plugin` +2. `cd gc-opencommand-plugin` +3. `mkdir lib` +4. `mv path/to/grasscutter-1.x.x-dev.jar ./lib` +5. `gradle build` + +## Multi server +### Master server (Dispatch) +1. Open `config.json` in the `opencommand-plugin` directory +2. Modify the `socketPort` value to an unused port +3. Set `sockettoken` multi server communication key. It is recommended to use a long random string of at least 32 characters. +4. Restart the server to make the configuration effective + +### Sub server (Game) +1. Open `config.json` in the `opencommand-plugin` directory +2. Modify the `sockethost` and `socketport` values to the address and port of the primary server +3. Set the same value of `sockettoken` and the primary server +4. Set the `socketDisplayName` value to your server name (See below for usage [Jump](https://github.com/jie65535/gc-opencommand-plugin/blob/master/README_en-US.md#get-mulit-server-list)) +5. Restart the server to make the configuration effective + --- ## `config.json` -```json +```json5 { + // console connection token (automatically generated when empty is detected) "consoleToken": "", + // Verification code expiration time (seconds) "codeExpirationTime_S": 60, + // Temporary token expiration time (seconds) "tempTokenExpirationTime_S": 300, + // Authorization token last used expiration time (hours) "tokenLastUseExpirationTime_H": 48, - "socketPort": 5746, - "socketToken": "", - "socketHost": "127.0.0.1" + // Multi-server communication port + "socketPort": 5746, + // Multi-server communication key + "socketToken": "", + // Multi-server Dispatch server address + "socketHost": "127.0.0.1", + // multi-server display name + "socketDisplayName": "" } ``` @@ -244,7 +262,7 @@ Success | message | `Success` | `String` | | data | `{}` | `JsonObject` | -```json +```json5 { "retcode": 200, "message": "success", diff --git a/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java b/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java index 5761276..9a07644 100644 --- a/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java +++ b/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java @@ -83,7 +83,7 @@ public final class OpenCommandHandler implements Router { } return; } else if (req.action.equals("ping")) { - context.json(new JsonResponse()); + context.json(new JsonResponse(plugin.getVersion())); return; } else if (req.action.equals("online")) { var p = new ArrayList(); @@ -147,7 +147,7 @@ public final class OpenCommandHandler implements Router { // update token expire time client.tokenExpireTime = new Date(now.getTime() + config.tokenLastUseExpirationTime_H * 60L * 60L * 1000L); var player = plugin.getServer().getPlayerByUid(client.playerId); - var command = req.data.toString(); + var rawMessage = req.data.toString(); if (player == null) { context.json(new JsonResponse(404, "Player not found")); return; @@ -158,7 +158,12 @@ public final class OpenCommandHandler implements Router { synchronized (handler) { try { handler.setLength(0); - CommandMap.getInstance().invoke(player, player, command); + for (var command : rawMessage.split("\n[/!]|\\|")) { + if (command.charAt(0) == '/' || command.charAt(0) == '!') { + command = command.substring(1); + } + CommandMap.getInstance().invoke(player, player, command); + } context.json(new JsonResponse(handler.toString())); } catch (Exception e) { plugin.getLogger().warn("Run command failed.", e); diff --git a/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java b/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java index c08d113..7ae7e50 100644 --- a/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java +++ b/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java @@ -26,7 +26,9 @@ import emu.grasscutter.server.event.HandlerPriority; import emu.grasscutter.server.event.game.ReceiveCommandFeedbackEvent; import emu.grasscutter.server.event.player.PlayerJoinEvent; import emu.grasscutter.server.event.player.PlayerQuitEvent; +import emu.grasscutter.utils.Crypto; import emu.grasscutter.utils.JsonUtils; +import emu.grasscutter.utils.Utils; import java.io.*; import java.nio.charset.StandardCharsets; @@ -105,24 +107,24 @@ public final class OpenCommandPlugin extends Plugin { var configFile = new File(getDataFolder(), "config.json"); if (!configFile.exists()) { config = new OpenCommandConfig(); - try (var file = new FileWriter(configFile)) { - file.write(JsonUtils.encode(config)); - } catch (IOException e) { - getLogger().error("[OpenCommand] Unable to write to config file."); - } catch (Exception e) { - getLogger().error("[OpenCommand] Unable to save config file."); - } + saveConfig(); } else { try { config = JsonUtils.decode(Files.readString(configFile.toPath(), StandardCharsets.UTF_8), OpenCommandConfig.class); } catch (Exception exception) { + config = new OpenCommandConfig(); getLogger().error("[OpenCommand] There was an error while trying to load the configuration from config.json. Please make sure that there are no syntax errors. If you want to start with a default configuration, delete your existing config.json."); } - if (config == null) { - config = new OpenCommandConfig(); - } } + + // 检查控制台Token + if (config.consoleToken == null || config.consoleToken.isEmpty()) { + config.consoleToken = Utils.base64Encode(Crypto.createSessionKey(24)); + saveConfig(); + getLogger().warn("Detected that consoleToken is empty, automatically generated Token for you as follows: {}", config.consoleToken); + } + try { runMode = Grasscutter.getConfig().server.runMode; } catch (Exception ex) { @@ -130,6 +132,17 @@ public final class OpenCommandPlugin extends Plugin { } } + private void saveConfig() { + var configFile = new File(getDataFolder(), "config.json"); + try (var file = new FileWriter(configFile)) { + file.write(JsonUtils.encode(config)); + } catch (IOException e) { + getLogger().error("[OpenCommand] Unable to write to config file."); + } catch (Exception e) { + getLogger().error("[OpenCommand] Unable to save config file."); + } + } + private void loadData() { var dataFile = new File(getDataFolder(), "data.json"); if (!dataFile.exists()) {