diff --git a/build.gradle b/build.gradle index d59af30..438048c 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group 'com.github.jie65535.opencommand' -version '1.7.0' +version '1.0.0' sourceCompatibility = 17 targetCompatibility = 17 @@ -18,7 +18,7 @@ dependencies { } jar { - jar.baseName = 'opencommand' + jar.baseName = 'OpenCommand-LunarCore' destinationDir = file(".") } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 41dfb87..2ec77e5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/com/github/jie65535/opencommand/EventListeners.java b/src/main/java/com/github/jie65535/opencommand/EventListeners.java index fc3a40a..d9b8b26 100644 --- a/src/main/java/com/github/jie65535/opencommand/EventListeners.java +++ b/src/main/java/com/github/jie65535/opencommand/EventListeners.java @@ -1,6 +1,6 @@ /* * gc-opencommand - * Copyright (C) 2022 jie65535 + * Copyright (C) 2022-2023 jie65535 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published @@ -17,103 +17,47 @@ */ package com.github.jie65535.opencommand; -import com.github.jie65535.opencommand.socket.SocketClient; -import com.github.jie65535.opencommand.socket.packet.player.PlayerList; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.event.game.ReceiveCommandFeedbackEvent; -import emu.grasscutter.server.event.player.PlayerJoinEvent; -import emu.grasscutter.server.event.player.PlayerQuitEvent; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.ArrayList; - public final class EventListeners { - private static StringBuilder consoleMessageHandler; - private static final Int2ObjectMap playerMessageHandlers = new Int2ObjectOpenHashMap<>(); - - public static void setConsoleMessageHandler(StringBuilder handler) { - consoleMessageHandler = handler; - } - - /** - * 获取新的玩家消息处理类 - * 获取时将创建或清空消息处理器并返回实例,**在执行命令前获取!** - * @param uid 玩家uid - * @return 新的玩家消息处理类 - */ - public static StringBuilder getPlayerMessageHandler(int uid) { - var handler = playerMessageHandlers.get(uid); - if (handler == null) { - handler = new StringBuilder(); - playerMessageHandlers.put(uid, handler); - } - return handler; - } - - /** - * 命令执行反馈事件处理 - */ - public static void onCommandResponse(ReceiveCommandFeedbackEvent event) { - StringBuilder handler; - if (event.getPlayer() == null) { - handler = consoleMessageHandler; - } else { - handler = playerMessageHandlers.get(event.getPlayer().getUid()); - } - - if (handler != null) { - if (!handler.isEmpty()) { - // New line - handler.append(System.lineSeparator()); - } - handler.append(event.getMessage()); - } - } - - public static void onPlayerJoin(PlayerJoinEvent playerJoinEvent) { - PlayerList playerList = new PlayerList(); - playerList.player = Grasscutter.getGameServer().getPlayers().size(); - ArrayList playerNames = new ArrayList<>(); - playerNames.add(playerJoinEvent.getPlayer().getNickname()); - playerList.playerMap.put(playerJoinEvent.getPlayer().getUid(), playerJoinEvent.getPlayer().getNickname()); - for (Player player : Grasscutter.getGameServer().getPlayers().values()) { - playerNames.add(player.getNickname()); - playerList.playerMap.put(player.getUid(), player.getNickname()); - } - playerList.playerList = playerNames; - - SocketClient.sendPacket(playerList); - } - - /** - * 仅游戏模式下玩家离开事件处理方法 - * 用于更新玩家列表 - */ - public static void onPlayerQuit(PlayerQuitEvent playerQuitEvent) { - PlayerList playerList = new PlayerList(); - playerList.player = Grasscutter.getGameServer().getPlayers().size(); - ArrayList playerNames = new ArrayList<>(); - for (Player player : Grasscutter.getGameServer().getPlayers().values()) { - playerNames.add(player.getNickname()); - playerList.playerMap.put(player.getUid(), player.getNickname()); - } - playerList.playerMap.remove(playerQuitEvent.getPlayer().getUid()); - playerNames.remove(playerQuitEvent.getPlayer().getNickname()); - playerList.playerList = playerNames; - SocketClient.sendPacket(playerList); - } - - /** - * 玩家离开事件处理 2 - * 用于清理内存 - */ - public static void onPlayerQuit2(PlayerQuitEvent playerQuitEvent) { - var uid = playerQuitEvent.getPlayer().getUid(); - if (playerMessageHandlers.containsKey(uid)) { - playerMessageHandlers.remove(uid); - } - } +// private static StringBuilder consoleMessageHandler; +// private static final Int2ObjectMap playerMessageHandlers = new Int2ObjectOpenHashMap<>(); +// +// public static void setConsoleMessageHandler(StringBuilder handler) { +// consoleMessageHandler = handler; +// } +// +// /** +// * 获取新的玩家消息处理类 +// * 获取时将创建或清空消息处理器并返回实例,**在执行命令前获取!** +// * @param uid 玩家uid +// * @return 新的玩家消息处理类 +// */ +// public static StringBuilder getPlayerMessageHandler(int uid) { +// var handler = playerMessageHandlers.get(uid); +// if (handler == null) { +// handler = new StringBuilder(); +// playerMessageHandlers.put(uid, handler); +// } +// return handler; +// } +// +// /** +// * 命令执行反馈事件处理 +// */ +// public static void onCommandResponse(ReceiveCommandFeedbackEvent event) { +// StringBuilder handler; +// if (event.getPlayer() == null) { +// handler = consoleMessageHandler; +// } else { +// handler = playerMessageHandlers.get(event.getPlayer().getUid()); +// } +// +// if (handler != null) { +// if (!handler.isEmpty()) { +// // New line +// handler.append(System.lineSeparator()); +// } +// handler.append(event.getMessage()); +// } +// } } diff --git a/src/main/java/com/github/jie65535/opencommand/OpenCommandConfig.java b/src/main/java/com/github/jie65535/opencommand/OpenCommandConfig.java index 6b11438..c41e0be 100644 --- a/src/main/java/com/github/jie65535/opencommand/OpenCommandConfig.java +++ b/src/main/java/com/github/jie65535/opencommand/OpenCommandConfig.java @@ -1,6 +1,6 @@ /* * gc-opencommand - * Copyright (C) 2022 jie65535 + * Copyright (C) 2022-2023 jie65535 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published @@ -37,24 +37,4 @@ public class OpenCommandConfig { * Token 最后使用过期时间(单位小时) */ public int tokenLastUseExpirationTime_H = 48; - - /** - * Socket 端口 - */ - public int socketPort = 5746; - - /** - * Socket Token - */ - public String socketToken = ""; - - /** - * Socket 主机地址 - */ - public String socketHost = "127.0.0.1"; - - /** - * Socket 显示名称 - */ - public String socketDisplayName = ""; } diff --git a/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java b/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java index 9ab31f2..6de332e 100644 --- a/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java +++ b/src/main/java/com/github/jie65535/opencommand/OpenCommandHandler.java @@ -1,6 +1,6 @@ /* * gc-opencommand - * Copyright (C) 2022 jie65535 + * Copyright (C) 2022-2023 jie65535 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published @@ -20,32 +20,24 @@ package com.github.jie65535.opencommand; import com.github.jie65535.opencommand.json.JsonRequest; import com.github.jie65535.opencommand.json.JsonResponse; import com.github.jie65535.opencommand.model.Client; -import com.github.jie65535.opencommand.socket.SocketData; -import emu.grasscutter.command.CommandMap; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.http.Router; -import emu.grasscutter.utils.Crypto; -import emu.grasscutter.utils.Utils; -import io.javalin.Javalin; +import emu.lunarcore.LunarCore; +import emu.lunarcore.game.player.Player; +import emu.lunarcore.util.Crypto; import io.javalin.http.Context; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import java.util.ArrayList; +import java.security.SecureRandom; import java.util.Date; import java.util.HashMap; import java.util.Map; -public final class OpenCommandHandler implements Router { - - @Override - public void applyRoutes(Javalin javalin) { - javalin.post("/opencommand/api", OpenCommandHandler::handle); - } +public final class OpenCommandHandler { private static final Map codes = new HashMap<>(); private static final Int2ObjectMap codeExpireTime = new Int2ObjectOpenHashMap<>(); + private static final SecureRandom secureRandom = new SecureRandom(); public static void handle(Context context) { var plugin = OpenCommandPlugin.getInstance(); @@ -60,7 +52,7 @@ public final class OpenCommandHandler implements Router { var req = context.bodyAsClass(JsonRequest.class); if (req.action.equals("sendCode")) { int playerId = (int)Double.parseDouble(req.data.toString()); - var player = plugin.getServer().getPlayerByUid(playerId); + var player = LunarCore.getGameServer().getPlayerByUid(playerId, false); if (player == null) { context.json(new JsonResponse(404, "Player Not Found.")); } else { @@ -74,23 +66,18 @@ public final class OpenCommandHandler implements Router { String token = req.token; if (token == null || token.isEmpty()) - token = Utils.bytesToHex(Crypto.createSessionKey(32)); - int code = Utils.randomRange(1000, 9999); + token = Crypto.createSessionKey(player.getAccountUid()); + int code = secureRandom.nextInt(1000, 9999); codeExpireTime.put(playerId, new Date(now.getTime() + config.codeExpirationTime_S * 1000L)); codes.put(token, code); data.addClient(new Client(token, playerId, new Date(now.getTime() + config.tempTokenExpirationTime_S * 1000L))); - player.dropMessage("[Open Command] Verification code: " + code); + player.sendMessage("[Open Command] Verification code: " + code); context.json(new JsonResponse(token)); } return; } else if (req.action.equals("ping")) { context.json(new JsonResponse(plugin.getVersion())); return; - } else if (req.action.equals("online")) { - var p = new ArrayList(); - plugin.getServer().getPlayers().forEach((uid, player) -> p.add(player.getNickname())); - context.json(new JsonResponse(200, "Success", new SocketData.OnlinePlayer(p))); - return; } // token is required @@ -114,13 +101,10 @@ public final class OpenCommandHandler implements Router { synchronized (plugin) { try { plugin.getLogger().info(String.format("IP: %s run command in console > %s", context.ip(), req.data)); - var resultCollector = new StringBuilder(); - EventListeners.setConsoleMessageHandler(resultCollector); - tryInvokeCommand(null, null, req.data.toString()); - context.json(new JsonResponse(resultCollector.toString())); + tryInvokeCommand(null, req.data.toString()); + context.json(new JsonResponse("OK")); } catch (Exception e) { plugin.getLogger().warn("Run command failed.", e); - EventListeners.setConsoleMessageHandler(null); context.json(new JsonResponse(500, "error", e.getLocalizedMessage())); } } @@ -147,23 +131,19 @@ public final class OpenCommandHandler implements Router { if (req.action.equals("command")) { // update token expire time client.tokenExpireTime = new Date(now.getTime() + config.tokenLastUseExpirationTime_H * 60L * 60L * 1000L); - var player = plugin.getServer().getPlayerByUid(client.playerId); + var player = LunarCore.getGameServer().getPlayerByUid(client.playerId, false); if (player == null) { context.json(new JsonResponse(404, "Player not found")); return; } - // Player MessageHandler do not support concurrency - var handler = EventListeners.getPlayerMessageHandler(player.getUid()); - //noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized (handler) { - try { - handler.setLength(0); - tryInvokeCommand(player, player, req.data.toString()); - context.json(new JsonResponse(handler.toString())); - } catch (Exception e) { - plugin.getLogger().warn("Run command failed.", e); - context.json(new JsonResponse(500, "error", e.getLocalizedMessage())); - } + +// var history = player.getChatManager().getHistoryByUid(GameConstants.SERVER_CONSOLE_UID); + try { + tryInvokeCommand(player, req.data.toString()); + context.json(new JsonResponse("OK")); + } catch (Exception e) { + plugin.getLogger().warn("Run command failed.", e); + context.json(new JsonResponse(500, "error", e.getLocalizedMessage())); } return; } @@ -174,14 +154,14 @@ public final class OpenCommandHandler implements Router { } } - private static void tryInvokeCommand(Player sender, Player target, String rawMessage) { + private static void tryInvokeCommand(Player sender, String rawMessage) { for (var command : rawMessage.split("\n[/!]|\\|")) { command = command.trim(); if (command.isEmpty()) continue; if (command.charAt(0) == '/' || command.charAt(0) == '!') { command = command.substring(1); } - CommandMap.getInstance().invoke(sender, target, command); + LunarCore.getCommandManager().invoke(sender, command); } } diff --git a/src/main/java/com/github/jie65535/opencommand/OpenCommandOnlyHttpHandler.java b/src/main/java/com/github/jie65535/opencommand/OpenCommandOnlyHttpHandler.java deleted file mode 100644 index 7a1cc3f..0000000 --- a/src/main/java/com/github/jie65535/opencommand/OpenCommandOnlyHttpHandler.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand; - -import com.github.jie65535.opencommand.json.JsonRequest; -import com.github.jie65535.opencommand.json.JsonResponse; -import com.github.jie65535.opencommand.model.Client; -import com.github.jie65535.opencommand.socket.SocketData; -import com.github.jie65535.opencommand.socket.SocketDataWait; -import com.github.jie65535.opencommand.socket.SocketServer; -import com.github.jie65535.opencommand.socket.packet.HttpPacket; -import com.github.jie65535.opencommand.socket.packet.RunConsoleCommand; -import com.github.jie65535.opencommand.socket.packet.player.Player; -import com.github.jie65535.opencommand.socket.packet.player.PlayerEnum; -import emu.grasscutter.server.http.Router; -import emu.grasscutter.utils.Crypto; -import emu.grasscutter.utils.Utils; -import io.javalin.Javalin; -import io.javalin.http.Context; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -public final class OpenCommandOnlyHttpHandler implements Router { - - @Override - public void applyRoutes(Javalin javalin) { - javalin.post("/opencommand/api", OpenCommandOnlyHttpHandler::handle); - } - - private static final Map codes = new HashMap<>(); - private static final Int2ObjectMap codeExpireTime = new Int2ObjectOpenHashMap<>(); - - public static void handle(Context context) { - var plugin = OpenCommandPlugin.getInstance(); - try { - var config = plugin.getConfig(); - var data = plugin.getData(); - var now = new Date(); - // Trigger cleanup action - cleanupExpiredCodes(); - data.removeExpiredClients(); - - var req = context.bodyAsClass(JsonRequest.class); - if (req.action.equals("sendCode")) { - int playerId = (int)Double.parseDouble(req.data.toString()); - var player = SocketData.getPlayer(playerId); - if (player == null) { - context.json(new JsonResponse(404, "Player Not Found.")); - } else { - if (codeExpireTime.containsKey(playerId)) { - var expireTime = codeExpireTime.get(playerId); - if (now.before(expireTime)) { - context.json(new JsonResponse(403, "Requests are too frequent")); - return; - } - } - - String token = req.token; - if (token == null || token.isEmpty()) - token = Utils.bytesToHex(Crypto.createSessionKey(32)); - int code = Utils.randomRange(1000, 9999); - codeExpireTime.put(playerId, new Date(now.getTime() + config.codeExpirationTime_S * 1000L)); - codes.put(token, code); - data.addClient(new Client(token, playerId, new Date(now.getTime() + config.tempTokenExpirationTime_S * 1000L))); - Player.dropMessage(playerId, "[Open Command] Verification code: " + code); - context.json(new JsonResponse(token)); - } - return; - } else if (req.action.equals("ping")) { - context.json(new JsonResponse()); - return; - } else if (req.action.equals("online")) { - context.json(new JsonResponse(200, "Success", SocketData.getOnlinePlayer())); - return; - } - - // token is required - if (req.token == null || req.token.isEmpty()) { - context.json(new JsonResponse(401, "Unauthorized")); - return; - } - var isConsole = req.token.equals(config.consoleToken); - var client = data.getClientByToken(req.token); - if (!isConsole && client == null) { - context.json(new JsonResponse(401, "Unauthorized")); - return; - } - - if (isConsole) { - if (req.action.equals("verify")) { - context.json(new JsonResponse()); - return; - } else if (req.action.equals("command")) { - var server = SocketServer.getClientInfoByUuid(req.server); - if (server == null) { - context.json(new JsonResponse(404, "Server Not Found.")); - return; - } - plugin.getLogger().info(String.format("IP: %s run command in console > %s", context.ip(), req.data)); - var wait = new SocketDataWait(2000L) { - @Override - public void run() { - } - - @Override - public HttpPacket initData(HttpPacket data) { - return data; - } - - @Override - public void timeout() { - } - }; - - SocketServer.sendPacketAndWait(server.ip, new RunConsoleCommand(req.data.toString()), wait); - var packet = wait.getData(); - if (packet == null) { - context.json(new JsonResponse(408, "Timeout")); - return; - } - context.json(new JsonResponse(packet.code, packet.message, packet.data)); - return; - } else if (req.action.equals("server")) { - context.json(new JsonResponse(200, "Success", SocketServer.getOnlineClient())); - return; - } else if (req.action.equals("runmode")) { - context.json(new JsonResponse(200, "Success", 1)); - return; - } - } else if (codes.containsKey(req.token)) { - if (req.action.equals("verify")) { - if (codes.get(req.token) == (int)Double.parseDouble(req.data.toString())) { - codes.remove(req.token); - // update token expire time - client.tokenExpireTime = new Date(now.getTime() + config.tokenLastUseExpirationTime_H * 60L * 60L * 1000L); - context.json(new JsonResponse()); - plugin.getLogger().info(String.format("Player %d has passed the verification, ip: %s", client.playerId, context.ip())); - plugin.saveData(); - } else { - context.json(new JsonResponse(400, "Verification failed")); - } - return; - } - } else { - if (req.action.equals("command")) { - SocketDataWait socketDataWait = new SocketDataWait<>(1000L * 10L) { - @Override - public void run() { - } - - @Override - public HttpPacket initData(HttpPacket data) { - return data; - } - - @Override - public void timeout() { - } - }; - - // update token expire time - client.tokenExpireTime = new Date(now.getTime() + config.tokenLastUseExpirationTime_H * 60L * 60L * 1000L); - var command = req.data.toString(); - var player = new Player(); - player.uid = client.playerId; - player.type = PlayerEnum.RunCommand; - player.data = command; - - if (!SocketServer.sendUidPacketAndWait(client.playerId, player, socketDataWait)) { - context.json(new JsonResponse(404, "Player Not Found.")); - return; - } - - - HttpPacket httpPacket = socketDataWait.getData(); - if (httpPacket == null) { - context.json(new JsonResponse(500, "error", "Wait timeout")); - return; - } - context.json(new JsonResponse(httpPacket.code, httpPacket.message)); - return; - } - } - context.json(new JsonResponse(403, "forbidden")); - } catch (Exception ex) { - plugin.getLogger().error("[OpenCommand] handler error.", ex); - } - } - - private static void cleanupExpiredCodes() { - var now = new Date(); - codeExpireTime.int2ObjectEntrySet().removeIf(entry -> entry.getValue().before(now)); - if (codeExpireTime.isEmpty()) - codes.clear(); - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java b/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java index 7ae7e50..4caa506 100644 --- a/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java +++ b/src/main/java/com/github/jie65535/opencommand/OpenCommandPlugin.java @@ -1,6 +1,6 @@ /* * gc-opencommand - * Copyright (C) 2022 jie65535 + * Copyright (C) 2022-2023 jie65535 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published @@ -17,20 +17,14 @@ */ package com.github.jie65535.opencommand; -import com.github.jie65535.opencommand.socket.SocketClient; -import com.github.jie65535.opencommand.socket.SocketServer; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.plugin.Plugin; -import emu.grasscutter.server.event.EventHandler; -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 emu.lunarcore.LunarCore; +import emu.lunarcore.plugin.Plugin; +import emu.lunarcore.util.Crypto; +import emu.lunarcore.util.JsonUtils; +import org.slf4j.Logger; import java.io.*; +import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -38,6 +32,10 @@ public final class OpenCommandPlugin extends Plugin { private static OpenCommandPlugin instance; + private OpenCommandPlugin(Identifier identifier, URLClassLoader classLoader, File dataFolder, Logger logger) { + super(identifier, classLoader, dataFolder, logger); + } + public static OpenCommandPlugin getInstance() { return instance; } @@ -46,8 +44,6 @@ public final class OpenCommandPlugin extends Plugin { private OpenCommandData data; - private Grasscutter.ServerRunMode runMode = Grasscutter.ServerRunMode.HYBRID; - @Override public void onLoad() { instance = this; @@ -55,37 +51,11 @@ public final class OpenCommandPlugin extends Plugin { loadConfig(); // 加载数据 loadData(); - // 启动Socket - startSocket(); } @Override public void onEnable() { - // 监听命令执行反馈 - new EventHandler<>(ReceiveCommandFeedbackEvent.class) - .priority(HandlerPriority.HIGH) - .listener(EventListeners::onCommandResponse) - .register(this); - // 监听玩家离开事件 - new EventHandler<>(PlayerQuitEvent.class) - .priority(HandlerPriority.NORMAL) - .listener(EventListeners::onPlayerQuit2) - .register(this); - if (runMode == Grasscutter.ServerRunMode.GAME_ONLY) { - // 仅运行游戏服务器时注册玩家加入和离开事件 - new EventHandler<>(PlayerJoinEvent.class) - .priority(HandlerPriority.HIGH) - .listener(EventListeners::onPlayerJoin) - .register(this); - new EventHandler<>(PlayerQuitEvent.class) - .priority(HandlerPriority.HIGH) - .listener(EventListeners::onPlayerQuit) - .register(this); - } else if (runMode == Grasscutter.ServerRunMode.DISPATCH_ONLY) { - getHandle().addRouter(OpenCommandOnlyHttpHandler.class); - } else { - getHandle().addRouter(OpenCommandHandler.class); - } + LunarCore.getHttpServer().getApp().post("/opencommand/api", OpenCommandHandler::handle); getLogger().info("[OpenCommand] Enabled. https://github.com/jie65535/gc-opencommand-plugin"); } @@ -120,16 +90,10 @@ public final class OpenCommandPlugin extends Plugin { // 检查控制台Token if (config.consoleToken == null || config.consoleToken.isEmpty()) { - config.consoleToken = Utils.base64Encode(Crypto.createSessionKey(24)); + config.consoleToken = Crypto.createSessionKey("1"); 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) { - getLogger().warn("[OpenCommand] Failed to load server configuration, default HYBRID mode is being used."); - } } private void saveConfig() { @@ -170,18 +134,4 @@ public final class OpenCommandPlugin extends Plugin { getLogger().error("[OpenCommand] Unable to save data file."); } } - - private void startSocket() { - if (runMode == Grasscutter.ServerRunMode.GAME_ONLY) { - getLogger().info("[OpenCommand] Starting socket client..."); - SocketClient.connectServer(); - } else if (runMode == Grasscutter.ServerRunMode.DISPATCH_ONLY) { - getLogger().info("[OpenCommand] Starting socket server..."); - try { - SocketServer.startServer(); - } catch (IOException e) { - getLogger().error("[OpenCommand] Unable to start socket server.", e); - } - } - } } diff --git a/src/main/java/com/github/jie65535/opencommand/json/JsonRequest.java b/src/main/java/com/github/jie65535/opencommand/json/JsonRequest.java index ef8dd9f..7c117ff 100644 --- a/src/main/java/com/github/jie65535/opencommand/json/JsonRequest.java +++ b/src/main/java/com/github/jie65535/opencommand/json/JsonRequest.java @@ -1,6 +1,6 @@ /* * gc-opencommand - * Copyright (C) 2022 jie65535 + * Copyright (C) 2022-2023 jie65535 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published diff --git a/src/main/java/com/github/jie65535/opencommand/json/JsonResponse.java b/src/main/java/com/github/jie65535/opencommand/json/JsonResponse.java index 1163142..ab6dff6 100644 --- a/src/main/java/com/github/jie65535/opencommand/json/JsonResponse.java +++ b/src/main/java/com/github/jie65535/opencommand/json/JsonResponse.java @@ -1,6 +1,6 @@ /* * gc-opencommand - * Copyright (C) 2022 jie65535 + * Copyright (C) 2022-2023 jie65535 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published diff --git a/src/main/java/com/github/jie65535/opencommand/socket/ClientInfo.java b/src/main/java/com/github/jie65535/opencommand/socket/ClientInfo.java deleted file mode 100644 index 2d1e767..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/ClientInfo.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket; - -public class ClientInfo { - - public final String uuid; - public final SocketServer.ClientThread clientThread; - public final String ip; - - public ClientInfo(String uuid, String ip, SocketServer.ClientThread clientThread) { - this.uuid = uuid; - this.clientThread = clientThread; - this.ip = ip; - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/SocketClient.java b/src/main/java/com/github/jie65535/opencommand/socket/SocketClient.java deleted file mode 100644 index e32cebd..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/SocketClient.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket; - -import com.github.jie65535.opencommand.EventListeners; -import com.github.jie65535.opencommand.OpenCommandConfig; -import com.github.jie65535.opencommand.OpenCommandPlugin; -import com.github.jie65535.opencommand.socket.packet.*; -import com.github.jie65535.opencommand.socket.packet.player.Player; -import com.github.jie65535.opencommand.socket.packet.player.PlayerList; -import emu.grasscutter.Grasscutter; -import emu.grasscutter.command.CommandMap; -import emu.grasscutter.utils.JsonUtils; -import org.slf4j.Logger; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.util.ArrayList; -import java.util.Timer; -import java.util.TimerTask; - -// Socket 客户端 -public class SocketClient { - public static ClientThread clientThread; - - public static Logger mLogger; - - public static Timer timer; - - public static boolean connect = false; - - public static ReceiveThread receiveThread; - - // 连接服务器 - public static void connectServer() { - if (connect) return; - if (clientThread != null) { - mLogger.warn("[OpenCommand] Retry connecting to the server after 15 seconds"); - try { - Thread.sleep(15000); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - } - OpenCommandConfig config = OpenCommandPlugin.getInstance().getConfig(); - mLogger = OpenCommandPlugin.getInstance().getLogger(); - clientThread = new ClientThread(config.socketHost, config.socketPort); - - if (timer != null) { - timer.cancel(); - } - timer = new Timer(); - timer.schedule(new SendHeartBeatPacket(), 500); - timer.schedule(new SendPlayerListPacket(), 1000); - } - - // 发送数据包 - public static boolean sendPacket(BasePacket packet) { - var p = SocketUtils.getPacket(packet); - if (!clientThread.sendPacket(p)) { - mLogger.warn("[OpenCommand] Send packet to server failed"); - mLogger.info("[OpenCommand] Reconnect to server"); - connect = false; - connectServer(); - return false; - } - return true; - } - - // 发送数据包带数据包ID - public static boolean sendPacket(BasePacket packet, String packetID) { - if (!clientThread.sendPacket(SocketUtils.getPacketAndPackID(packet, packetID))) { - mLogger.warn("[OpenCommand] Send packet to server failed"); - mLogger.info("[OpenCommand] Reconnect to server"); - connect = false; - connectServer(); - return false; - } - return true; - } - - // 心跳包发送 - private static class SendHeartBeatPacket extends TimerTask { - @Override - public void run() { - if (connect) { - sendPacket(new HeartBeat("Pong")); - } - } - } - - private static class SendPlayerListPacket extends TimerTask { - @Override - public void run() { - if (connect) { - PlayerList playerList = new PlayerList(); - playerList.player = Grasscutter.getGameServer().getPlayers().size(); - ArrayList playerNames = new ArrayList<>(); - for (emu.grasscutter.game.player.Player player : Grasscutter.getGameServer().getPlayers().values()) { - playerNames.add(player.getNickname()); - playerList.playerMap.put(player.getUid(), player.getNickname()); - } - playerList.playerList = playerNames; - sendPacket(playerList); - } - } - } - - // 数据包接收 - private static class ReceiveThread extends Thread { - private InputStream is; - private boolean exit = false; - - public ReceiveThread(Socket socket) { - try { - is = socket.getInputStream(); - } catch (IOException e) { - e.printStackTrace(); - } - start(); - } - - @Override - public void run() { - while (true) { - try { - if (exit) { - return; - } - String data = SocketUtils.readString(is); - Packet packet = JsonUtils.decode(data, Packet.class); - switch (packet.type) { - // 玩家类 - case Player: - var player = JsonUtils.decode(packet.data, Player.class); - switch (player.type) { - // 运行命令 - case RunCommand -> { - var command = player.data; - var playerData = OpenCommandPlugin.getInstance().getServer().getPlayerByUid(player.uid); - if (playerData == null) { - sendPacket(new HttpPacket(404, "Player not found."), packet.packetID); - return; - } - // Player MessageHandler do not support concurrency - var handler = EventListeners.getPlayerMessageHandler(playerData.getUid()); - //noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized (handler) { - try { - handler.setLength(0); - CommandMap.getInstance().invoke(playerData, playerData, command); - sendPacket(new HttpPacket(200, handler.toString()), packet.packetID); - } catch (Exception e) { - OpenCommandPlugin.getInstance().getLogger().warn("[OpenCommand] Run command failed.", e); - sendPacket(new HttpPacket(500, "error", e.getLocalizedMessage()), packet.packetID); - } - } - } - // 发送信息 - case DropMessage -> { - var playerData = OpenCommandPlugin.getInstance().getServer().getPlayerByUid(player.uid); - if (playerData == null) { - return; - } - playerData.dropMessage(player.data); - } - } - break; - case RunConsoleCommand: - var consoleCommand = JsonUtils.decode(packet.data, RunConsoleCommand.class); - var plugin = OpenCommandPlugin.getInstance(); - //noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized (plugin) { - try { - var resultCollector = new StringBuilder(); - EventListeners.setConsoleMessageHandler(resultCollector); - CommandMap.getInstance().invoke(null, null, consoleCommand.command); - sendPacket(new HttpPacket(resultCollector.toString()), packet.packetID); - } catch (Exception e) { - mLogger.warn("[OpenCommand] Run command failed.", e); - EventListeners.setConsoleMessageHandler(null); - sendPacket(new HttpPacket(500, "error", e.getLocalizedMessage()), packet.packetID); - } finally { - EventListeners.setConsoleMessageHandler(null); - } - } - } - } catch (Throwable e) { - e.printStackTrace(); - if (!sendPacket(new HeartBeat("Pong"))) { - return; - } - } - } - } - - public void exit() { - exit = true; - } - } - - // 客户端连接线程 - private static class ClientThread extends Thread { - private final String ip; - private final int port; - private Socket socket; - private OutputStream os; - - public ClientThread(String ip, int port) { - this.ip = ip; - this.port = port; - start(); - } - - public Socket getSocket() { - return socket; - } - - public boolean sendPacket(String string) { - return SocketUtils.writeString(os, string); - } - - @Override - public void run() { - try { - connect = true; - if (receiveThread != null) { - receiveThread.exit(); - } - - socket = new Socket(ip, port); - os = socket.getOutputStream(); - mLogger.info("[OpenCommand] Connect to server: " + ip + ":" + port); - SocketClient.sendPacket(new AuthPacket(OpenCommandPlugin.getInstance().getConfig().socketToken, OpenCommandPlugin.getInstance().getConfig().socketDisplayName)); - receiveThread = new ReceiveThread(socket); - } catch (IOException e) { - connect = false; - mLogger.warn("[OpenCommand] Connect to server failed: " + ip + ":" + port); - connectServer(); - } - } - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/SocketData.java b/src/main/java/com/github/jie65535/opencommand/socket/SocketData.java deleted file mode 100644 index 9bf266c..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/SocketData.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket; - -import com.github.jie65535.opencommand.socket.packet.player.PlayerList; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.concurrent.atomic.AtomicReference; - -// Socket 数据保存 -public class SocketData { - public static HashMap playerList = new HashMap<>(); - - public static String getPlayer(int uid) { - for (PlayerList player : playerList.values()) { - if (player.playerMap.get(uid) != null) { - return player.playerMap.get(uid); - } - } - return null; - } - - public static String getPlayerInServer(int uid) { - AtomicReference ret = new AtomicReference<>(); - playerList.forEach((key, value) -> { - if (value.playerMap.get(uid) != null) { - ret.set(key); - } - }); - return ret.get(); - } - - public static OnlinePlayer getOnlinePlayer() { - ArrayList player = new ArrayList<>(); - playerList.forEach((address, playerMap) -> playerMap.playerMap.forEach((uid, name) -> player.add(name))); - return new OnlinePlayer(player); - } - - public static class OnlinePlayer { - public int count; - public ArrayList playerList; - - public OnlinePlayer(ArrayList playerList) { - this.playerList = playerList; - this.count = playerList.size(); - } - - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/SocketDataWait.java b/src/main/java/com/github/jie65535/opencommand/socket/SocketDataWait.java deleted file mode 100644 index 7a1ed71..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/SocketDataWait.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket; - -// 异步等待数据返回 -public abstract class SocketDataWait extends Thread { - public T data; - public long timeout; - public long time; - public String uid; - - /** - * 异步等待数据返回 - * @param timeout 超时时间 - */ - public SocketDataWait(long timeout) { - this.timeout = timeout; - start(); - } - - public abstract void run(); - - /** - * 数据处理 - * @param data 数据 - * @return 处理后的数据 - */ - public abstract T initData(T data); - - /** - * 超时回调 - */ - public abstract void timeout(); - - /** - * 异步设置数据 - * @param data 数据 - */ - public void setData(Object data) { - this.data = initData((T) data); - } - - /** - * 获取异步数据(此操作会一直堵塞直到获取到数据) - * @return 数据 - */ - public T getData() { - while (data == null) { - try { - time += 100; - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (time > timeout) { - timeout(); - return null; - } - } - return data; - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/SocketServer.java b/src/main/java/com/github/jie65535/opencommand/socket/SocketServer.java deleted file mode 100644 index 5837a34..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/SocketServer.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket; - -import com.github.jie65535.opencommand.OpenCommandPlugin; -import com.github.jie65535.opencommand.socket.packet.*; -import com.github.jie65535.opencommand.socket.packet.player.PlayerList; -import emu.grasscutter.utils.JsonUtils; -import org.slf4j.Logger; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.HashMap; -import java.util.Timer; -import java.util.TimerTask; -import java.util.UUID; - -// Socket 服务器 -public class SocketServer { - // 客户端超时时间 - private static final int TIMEOUT = 5000; - private static final HashMap clientList = new HashMap<>(); - - private static final HashMap clientTimeout = new HashMap<>(); - private static Logger mLogger; - - public static HashMap getOnlineClient() { - HashMap onlineClient = new HashMap<>(); - for (var key : clientList.entrySet()) { - onlineClient.put(key.getValue().uuid, key.getValue().clientThread.getDisplayName()); - } - return onlineClient; - } - - public static ClientInfo getClientInfoByUuid(String uuid) { - for (var key : clientList.entrySet()) { - if (key.getValue().uuid.equals(uuid)) { - return key.getValue(); - } - } - return null; - } - - public static void startServer() throws IOException { - int port = OpenCommandPlugin.getInstance().getConfig().socketPort; - mLogger = OpenCommandPlugin.getInstance().getLogger(); - new Timer().schedule(new SocketClientCheck(), 500); - new WaitClientConnect(port); - } - - // 向全部客户端发送数据 - public static boolean sendAllPacket(BasePacket packet) { - var p = SocketUtils.getPacket(packet); - HashMap old = (HashMap) clientList.clone(); - for (var client : old.entrySet()) { - if (!client.getValue().clientThread.sendPacket(p)) { - mLogger.warn("[OpenCommand] Send packet to client {} failed", client.getKey()); - clientList.remove(client.getKey()); - } - } - return false; - } - - // 根据地址发送到相应的客户端 - public static boolean sendPacket(String address, BasePacket packet) { - var p = SocketUtils.getPacket(packet); - var client = clientList.get(address); - if (client != null) { - if (client.clientThread.sendPacket(p)) { - return true; - } - mLogger.warn("[OpenCommand] Send packet to client {} failed", address); - clientList.remove(address); - } - return false; - } - - public static boolean sendPacketAndWait(String address, BasePacket packet, SocketDataWait wait) { - var p = SocketUtils.getPacketAndPackID(packet); - var client = clientList.get(address); - if (client != null) { - wait.uid = p.get(0); - if (client.clientThread.sendPacket(p.get(1), wait)) { - return true; - } - mLogger.warn("[OpenCommand] Send packet to client {} failed", address); - clientList.remove(address); - } - return false; - } - - public static boolean sendUidPacket(Integer playerId, BasePacket player) { - var p = SocketUtils.getPacket(player); - var clientID = SocketData.getPlayerInServer(playerId); - if (clientID == null) return false; - var client = clientList.get(clientID); - if (client != null) { - if (!client.clientThread.sendPacket(p)) { - mLogger.warn("[OpenCommand] Send packet to client {} failed", clientID); - clientList.remove(clientID); - return false; - } - return true; - } - return false; - } - - // 根据Uid发送到相应的客户端异步返回数据 - public static boolean sendUidPacketAndWait(Integer playerId, BasePacket player, SocketDataWait socketDataWait) { - var p = SocketUtils.getPacketAndPackID(player); - var clientID = SocketData.getPlayerInServer(playerId); - if (clientID == null) return false; - var client = clientList.get(clientID); - if (client != null) { - socketDataWait.uid = p.get(0); - if (!client.clientThread.sendPacket(p.get(1), socketDataWait)) { - mLogger.warn("[OpenCommand] Send packet to client {} failed", clientID); - clientList.remove(clientID); - return false; - } - return true; - } - return false; - } - - // 客户端超时检测 - private static class SocketClientCheck extends TimerTask { - @Override - public void run() { - HashMap old = (HashMap) clientTimeout.clone(); - for (var client : old.entrySet()) { - var clientID = client.getKey(); - var clientTime = client.getValue(); - if (clientTime > TIMEOUT) { - mLogger.info("[OpenCommand] Client {} timeout, disconnect.", clientID); - clientList.remove(clientID); - clientTimeout.remove(clientID); - SocketData.playerList.remove(clientID); - } else { - clientTimeout.put(clientID, clientTime + 500); - } - } - } - } - - // 客户端数据包处理 - static class ClientThread extends Thread { - private final Socket socket; - private InputStream is; - private OutputStream os; - private final String address; - private final String token; - private boolean auth = false; - private String displayName = ""; - - private final HashMap> socketDataWaitList = new HashMap<>(); - - public ClientThread(Socket accept) { - socket = accept; - address = socket.getInetAddress() + ":" + socket.getPort(); - token = OpenCommandPlugin.getInstance().getConfig().socketToken; - try { - is = accept.getInputStream(); - os = accept.getOutputStream(); - } catch (IOException e) { - e.printStackTrace(); - } - start(); - } - - public Socket getSocket() { - return socket; - } - - // 发送数据包 - public boolean sendPacket(String packet) { - return SocketUtils.writeString(os, packet); - } - - // 发送异步数据包 - public boolean sendPacket(String packet, SocketDataWait socketDataWait) { - if (SocketUtils.writeString(os, packet)) { - socketDataWaitList.put(socketDataWait.uid, socketDataWait); - return true; - } else { - return false; - } - } - - @Override - public void run() { - while (true) { - try { - String data = SocketUtils.readString(is); - Packet packet = JsonUtils.decode(data, Packet.class); - if (packet.type == PacketEnum.AuthPacket) { - AuthPacket authPacket = JsonUtils.decode(packet.data, AuthPacket.class); - if (authPacket.token.equals(token)) { - auth = true; - displayName = authPacket.displayName; - mLogger.info("[OpenCommand] Client {} auth success, name: {}", address, displayName); - clientList.put(address, new ClientInfo(UUID.randomUUID().toString(), address, this)); - clientTimeout.put(address, 0); - } else { - mLogger.warn("[OpenCommand] Client {} auth failed", address); - socket.close(); - return; - } - } - if (!auth) { - mLogger.warn("[OpenCommand] Client {} auth failed", address); - socket.close(); - return; - } - switch (packet.type) { - // 缓存玩家列表 - case PlayerList -> { - PlayerList playerList = JsonUtils.decode(packet.data, PlayerList.class); - SocketData.playerList.put(address, playerList); - } - // Http信息返回 - case HttpPacket -> { - HttpPacket httpPacket = JsonUtils.decode(packet.data, HttpPacket.class); - var socketWait = socketDataWaitList.get(packet.packetID); - if (socketWait == null) { - mLogger.error("[OpenCommand] HttpPacket: " + packet.packetID + " not found"); - return; - } - socketWait.setData(httpPacket); - socketDataWaitList.remove(packet.packetID); - } - // 心跳包 - case HeartBeat -> clientTimeout.put(address, 0); - } - } catch (Throwable e) { - e.printStackTrace(); - mLogger.error("[OpenCommand] Client {} disconnect.", address); - clientList.remove(address); - clientTimeout.remove(address); - SocketData.playerList.remove(address); - break; - } - } - } - - public String getDisplayName() { - return displayName; - } - } - - // 等待客户端连接 - private static class WaitClientConnect extends Thread { - ServerSocket socketServer; - - public WaitClientConnect(int port) throws IOException { - socketServer = new ServerSocket(port); - start(); - } - - @Override - public void run() { - mLogger.info("[OpenCommand] Start socket server on port " + socketServer.getLocalPort()); - // noinspection InfiniteLoopStatement - while (true) { - try { - Socket accept = socketServer.accept(); - String address = accept.getInetAddress() + ":" + accept.getPort(); - mLogger.info("[OpenCommand] Client connect: " + address); - new ClientThread(accept); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/SocketUtils.java b/src/main/java/com/github/jie65535/opencommand/socket/SocketUtils.java deleted file mode 100644 index 7c7739a..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/SocketUtils.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket; - -import com.github.jie65535.opencommand.socket.packet.BasePacket; -import com.github.jie65535.opencommand.socket.packet.Packet; -import emu.grasscutter.utils.JsonUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -// Socket 工具类 -public class SocketUtils { - - /** - * 获取打包后的数据包 - * - * @param bPacket 数据包 - * @return 打包后的数据包 - */ - public static String getPacket(BasePacket bPacket) { - Packet packet = new Packet(); - packet.type = bPacket.getType(); - packet.data = bPacket.getPacket(); - packet.packetID = UUID.randomUUID().toString(); - return JsonUtils.encode(packet); - } - - /** - * 获取打包后的数据包 - * - * @param bPacket BasePacket - * @return list[0] 是包ID, list[1] 是数据包 - */ - public static List getPacketAndPackID(BasePacket bPacket) { - Packet packet = new Packet(); - packet.type = bPacket.getType(); - packet.data = bPacket.getPacket(); - packet.packetID = UUID.randomUUID().toString(); - - List list = new ArrayList<>(); - list.add(packet.packetID); - list.add(JsonUtils.encode(packet)); - return list; - } - - /** - * 获取打包后的数据包 - * - * @param bPacket 数据包 - * @param packetID 数据包ID - * @return 打包后的数据包 - */ - public static String getPacketAndPackID(BasePacket bPacket, String packetID) { - Packet packet = new Packet(); - packet.type = bPacket.getType(); - packet.data = bPacket.getPacket(); - packet.packetID = packetID; - return JsonUtils.encode(packet); - } - - /** - * 读整数 - * - * @param is 输入流 - * @return 整数 - */ - public static int readInt(InputStream is) { - int[] values = new int[4]; - try { - for (int i = 0; i < 4; i++) { - values[i] = is.read(); - } - } catch (IOException e) { - e.printStackTrace(); - } - - return values[0] << 24 | values[1] << 16 | values[2] << 8 | values[3]; - } - - /** - * 写整数 - * - * @param os 输出流 - * @param value 整数 - */ - public static void writeInt(OutputStream os, int value) { - int[] values = new int[4]; - values[0] = (value >> 24) & 0xFF; - values[1] = (value >> 16) & 0xFF; - values[2] = (value >> 8) & 0xFF; - values[3] = (value) & 0xFF; - - try { - for (int i = 0; i < 4; i++) { - os.write(values[i]); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * 读字符串 - * - * @param is 输入流 - * @return 字符串 - */ - public static String readString(InputStream is) { - int len = readInt(is); - byte[] sByte = new byte[len]; - try { - is.read(sByte); - } catch (IOException e) { - e.printStackTrace(); - } - return new String(sByte); - } - - /** - * 写字符串 - * - * @param os 输出流 - * @param s 字符串 - * @return 是否成功 - */ - public static boolean writeString(OutputStream os, String s) { - try { - byte[] bytes = s.getBytes(); - int len = bytes.length; - writeInt(os, len); - os.write(bytes); - return true; - } catch (IOException e) { - e.printStackTrace(); - } - return false; - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/AuthPacket.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/AuthPacket.java deleted file mode 100644 index dc0b4c8..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/AuthPacket.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket.packet; - -import emu.grasscutter.utils.JsonUtils; - -public class AuthPacket extends BasePacket { - public String token; - public String displayName; - - public AuthPacket(String token, String displayName) { - this.displayName = displayName; - this.token = token; - } - - @Override - public String getPacket() { - return JsonUtils.encode(this); - } - - @Override - public PacketEnum getType() { - return PacketEnum.AuthPacket; - } - - @Override - public String toString() { - return "AuthPacket [token=" + token + ", displayName=" + displayName + "]"; - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/BasePacket.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/BasePacket.java deleted file mode 100644 index 8f52b09..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/BasePacket.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket.packet; - -// 基本数据包 -public abstract class BasePacket { - public abstract String getPacket(); - - public abstract PacketEnum getType(); -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/HeartBeat.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/HeartBeat.java deleted file mode 100644 index cf202c2..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/HeartBeat.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket.packet; - -import emu.grasscutter.utils.JsonUtils; - -// 心跳包 -public class HeartBeat extends BasePacket { - public String ping; - - public HeartBeat(String ping) { - this.ping = ping; - } - - @Override - public String getPacket() { - return JsonUtils.encode(this); - } - - @Override - public PacketEnum getType() { - return PacketEnum.HeartBeat; - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/HttpPacket.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/HttpPacket.java deleted file mode 100644 index ba3339d..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/HttpPacket.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket.packet; - -import emu.grasscutter.utils.JsonUtils; - -// http返回数据 -public class HttpPacket extends BasePacket { - public int code = 200; - public String message = "Success"; - public String data; - - public HttpPacket(int code, String message, String data) { - this.code = code; - this.message = message; - this.data = data; - } - - public HttpPacket(int code, String message) { - this.code = code; - this.message = message; - } - public HttpPacket(String data) { - this.data = data; - } - - @Override - public String getPacket() { - return JsonUtils.encode(this); - } - - @Override - public PacketEnum getType() { - return PacketEnum.HttpPacket; - } - - @Override - public String toString() { - return "HttpPacket [code=" + code + ", message=" + message + ", data=" + data + "]"; - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/Packet.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/Packet.java deleted file mode 100644 index 3e3b175..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/Packet.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket.packet; - -// 数据包结构 -public class Packet { - public PacketEnum type; - public String data; - public String packetID; - - @Override - public String toString() { - return "Packet [type=" + type + ", data=" + data + ", packetID=" + packetID + "]"; - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/PacketEnum.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/PacketEnum.java deleted file mode 100644 index a8dc4ab..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/PacketEnum.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket.packet; - -// 数据包类型列表 -public enum PacketEnum { - PlayerList, - Player, - HttpPacket, - AuthPacket, - RunConsoleCommand, - HeartBeat -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/RunConsoleCommand.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/RunConsoleCommand.java deleted file mode 100644 index 36674ef..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/RunConsoleCommand.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket.packet; - -import emu.grasscutter.utils.JsonUtils; - -public class RunConsoleCommand extends BasePacket { - public String command; - - public RunConsoleCommand(String command) { - this.command = command; - } - - @Override - public String getPacket() { - return JsonUtils.encode(this); - } - - @Override - public PacketEnum getType() { - return PacketEnum.RunConsoleCommand; - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/player/Player.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/player/Player.java deleted file mode 100644 index c821267..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/player/Player.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket.packet.player; - -import com.github.jie65535.opencommand.socket.SocketServer; -import com.github.jie65535.opencommand.socket.packet.BasePacket; -import com.github.jie65535.opencommand.socket.packet.PacketEnum; -import emu.grasscutter.utils.JsonUtils; - -// 玩家操作类 -public class Player extends BasePacket { - public PlayerEnum type; - public int uid; - public String data; - - @Override - public String getPacket() { - return JsonUtils.encode(this); - } - - @Override - public PacketEnum getType() { - return PacketEnum.Player; - } - - public static void dropMessage(int uid, String str) { - Player p = new Player(); - p.type = PlayerEnum.DropMessage; - p.uid = uid; - p.data = str; - SocketServer.sendUidPacket(uid, p); - } -} diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/player/PlayerEnum.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/player/PlayerEnum.java deleted file mode 100644 index 1fa1ce8..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/player/PlayerEnum.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket.packet.player; - -// 玩家操作列表 -public enum PlayerEnum { - DropMessage, - RunCommand -} \ No newline at end of file diff --git a/src/main/java/com/github/jie65535/opencommand/socket/packet/player/PlayerList.java b/src/main/java/com/github/jie65535/opencommand/socket/packet/player/PlayerList.java deleted file mode 100644 index faf8866..0000000 --- a/src/main/java/com/github/jie65535/opencommand/socket/packet/player/PlayerList.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * gc-opencommand - * Copyright (C) 2022 jie65535 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package com.github.jie65535.opencommand.socket.packet.player; - -import com.github.jie65535.opencommand.socket.packet.BasePacket; -import com.github.jie65535.opencommand.socket.packet.PacketEnum; -import emu.grasscutter.utils.JsonUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -// 玩家列表信息 -public class PlayerList extends BasePacket { - public int player = -1; - public List playerList = new ArrayList<>(); - public Map playerMap = new HashMap<>(); - - @Override - public String getPacket() { - return JsonUtils.encode(this); - } - - @Override - public PacketEnum getType() { - return PacketEnum.PlayerList; - } -} diff --git a/src/main/resources/plugin.json b/src/main/resources/plugin.json index d89e52a..e709231 100644 --- a/src/main/resources/plugin.json +++ b/src/main/resources/plugin.json @@ -1,8 +1,8 @@ { "name": "opencommand-plugin", "description": "Open command interface for third-party clients", - "version": "1.7.0", + "version": "1.0.0", "mainClass": "com.github.jie65535.opencommand.OpenCommandPlugin", - "authors": ["jie65535", "方块君"], - "api": 2 + "authors": ["jie65535"], + "api": 1 } \ No newline at end of file