From c780fb79342e88286cced0c08cb3955e3c4d2603 Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Tue, 30 May 2023 13:06:50 -0400 Subject: [PATCH] Add system for sending messages between servers --- .../server/dispatch/DispatchClient.java | 17 +++--- .../server/dispatch/DispatchServer.java | 17 +++--- .../server/dispatch/IDispatcher.java | 55 +++++++++++++++-- .../server/dispatch/PacketIds.java | 1 + .../event/dispatch/ServerMessageEvent.java | 61 +++++++++++++++++++ 5 files changed, 133 insertions(+), 18 deletions(-) create mode 100644 src/main/java/emu/grasscutter/server/event/dispatch/ServerMessageEvent.java diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchClient.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchClient.java index 93f9be29a..42a5396e8 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/DispatchClient.java +++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchClient.java @@ -1,17 +1,22 @@ package emu.grasscutter.server.dispatch; -import static emu.grasscutter.config.Configuration.DISPATCH_INFO; - import com.google.gson.JsonElement; import com.google.gson.JsonObject; import emu.grasscutter.Grasscutter; import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.server.event.dispatch.ServerMessageEvent; import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.http.handlers.GachaHandler; import emu.grasscutter.utils.Crypto; import emu.grasscutter.utils.DispatchUtils; import emu.grasscutter.utils.JsonUtils; import emu.grasscutter.utils.objects.HandbookBody; +import lombok.Getter; +import org.java_websocket.WebSocket; +import org.java_websocket.client.WebSocketClient; +import org.java_websocket.handshake.ServerHandshake; +import org.slf4j.Logger; + import java.net.ConnectException; import java.net.URI; import java.nio.ByteBuffer; @@ -22,11 +27,8 @@ import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; -import lombok.Getter; -import org.java_websocket.WebSocket; -import org.java_websocket.client.WebSocketClient; -import org.java_websocket.handshake.ServerHandshake; -import org.slf4j.Logger; + +import static emu.grasscutter.config.Configuration.DISPATCH_INFO; public final class DispatchClient extends WebSocketClient implements IDispatcher { @Getter private final Logger logger = Grasscutter.getLogger(); @@ -44,6 +46,7 @@ public final class DispatchClient extends WebSocketClient implements IDispatcher this.registerHandler(PacketIds.GmTalkReq, this::handleHandbookAction); this.registerHandler(PacketIds.GetPlayerFieldsReq, this::fetchPlayerFields); this.registerHandler(PacketIds.GetPlayerByAccountReq, this::fetchPlayerByAccount); + this.registerHandler(PacketIds.ServerMessageNotify, ServerMessageEvent::invoke); } /** diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java index 5c11f4194..818d34758 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java +++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java @@ -1,12 +1,17 @@ package emu.grasscutter.server.dispatch; -import static emu.grasscutter.config.Configuration.DISPATCH_INFO; - import com.google.gson.JsonElement; import com.google.gson.JsonObject; import emu.grasscutter.Grasscutter; import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.server.event.dispatch.ServerMessageEvent; import emu.grasscutter.utils.Crypto; +import lombok.Getter; +import org.java_websocket.WebSocket; +import org.java_websocket.handshake.ClientHandshake; +import org.java_websocket.server.WebSocketServer; +import org.slf4j.Logger; + import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @@ -15,11 +20,8 @@ import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; -import lombok.Getter; -import org.java_websocket.WebSocket; -import org.java_websocket.handshake.ClientHandshake; -import org.java_websocket.server.WebSocketServer; -import org.slf4j.Logger; + +import static emu.grasscutter.config.Configuration.DISPATCH_INFO; /* Internal communications server. */ public final class DispatchServer extends WebSocketServer implements IDispatcher { @@ -40,6 +42,7 @@ public final class DispatchServer extends WebSocketServer implements IDispatcher this.registerHandler(PacketIds.LoginNotify, this::handleLogin); this.registerHandler(PacketIds.TokenValidateReq, this::validateToken); this.registerHandler(PacketIds.GetAccountReq, this::fetchAccount); + this.registerHandler(PacketIds.ServerMessageNotify, ServerMessageEvent::invoke); } /** diff --git a/src/main/java/emu/grasscutter/server/dispatch/IDispatcher.java b/src/main/java/emu/grasscutter/server/dispatch/IDispatcher.java index 20abbf249..770f86da2 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/IDispatcher.java +++ b/src/main/java/emu/grasscutter/server/dispatch/IDispatcher.java @@ -1,7 +1,5 @@ package emu.grasscutter.server.dispatch; -import static emu.grasscutter.config.Configuration.DISPATCH_INFO; - import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; @@ -9,7 +7,11 @@ import com.google.gson.JsonObject; import emu.grasscutter.utils.Crypto; import emu.grasscutter.utils.JsonAdapters.ByteArrayAdapter; import emu.grasscutter.utils.objects.JObject; +import org.java_websocket.WebSocket; +import org.slf4j.Logger; + import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -18,8 +20,8 @@ import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; -import org.java_websocket.WebSocket; -import org.slf4j.Logger; + +import static emu.grasscutter.config.Configuration.DISPATCH_INFO; public interface IDispatcher { Gson JSON = @@ -246,6 +248,51 @@ public interface IDispatcher { this.getCallbacks().get(packetId).add(callback); } + /** + * Sends a server message to the client. + * + * @param data The data to send. + * @param binary Whether the data is binary. + */ + default void sendServerMessage(byte[] data, boolean binary) { + var message = new JObject() + .add("binary", binary) + .add("data", Base64.getEncoder().encodeToString(data)) + .gson(); + + this.sendMessage(PacketIds.ServerMessageNotify, message); + } + + /** + * Sends a server message to the client. + * The data is sent as a string. + * + * @param data The data to send. + */ + default void sendServerMessage(String data) { + this.sendServerMessage(data.getBytes(), false); + } + + /** + * Sends a server message to the client. + * The data is sent as a byte array. + * + * @param data The data to send. + */ + default void sendServerMessage(byte[] data) { + this.sendServerMessage(data, true); + } + + /** + * Sends a server message to the client. + * The data is sent as a JSON object. + * + * @param data The data to send. + */ + default void sendServerMessage(Object data) { + this.sendServerMessage(JSON.toJson(data)); + } + /** * @return The logger for the dispatcher. */ diff --git a/src/main/java/emu/grasscutter/server/dispatch/PacketIds.java b/src/main/java/emu/grasscutter/server/dispatch/PacketIds.java index d54f61c3b..a076c46e7 100644 --- a/src/main/java/emu/grasscutter/server/dispatch/PacketIds.java +++ b/src/main/java/emu/grasscutter/server/dispatch/PacketIds.java @@ -17,4 +17,5 @@ public interface PacketIds { int GetPlayerFieldsRsp = 9; int GetPlayerByAccountReq = 10; int GetPlayerByAccountRsp = 11; + int ServerMessageNotify = 12; } diff --git a/src/main/java/emu/grasscutter/server/event/dispatch/ServerMessageEvent.java b/src/main/java/emu/grasscutter/server/event/dispatch/ServerMessageEvent.java new file mode 100644 index 000000000..47954a854 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/event/dispatch/ServerMessageEvent.java @@ -0,0 +1,61 @@ +package emu.grasscutter.server.event.dispatch; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import emu.grasscutter.server.dispatch.IDispatcher; +import emu.grasscutter.server.event.Event; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.java_websocket.WebSocket; + +import java.util.Base64; + +@Getter +@RequiredArgsConstructor +public final class ServerMessageEvent extends Event { + /** + * Invokes the event. + * + * @param client The client that sent the message. + * @param object The message. + */ + public static void invoke(WebSocket client, JsonElement object) { + var message = IDispatcher.decode(object); + var isBinary = message.get("binary").getAsBoolean(); + var data = Base64.getDecoder().decode( + message.get("data").getAsString()); + + // Create the event and invoke it. + new ServerMessageEvent(client, isBinary, data).call(); + } + + private final WebSocket client; + private final boolean isBinary; + private final byte[] message; + + /** + * @return The message as a string. + */ + public String asString() { + if (this.isBinary) + throw new UnsupportedOperationException("Cannot convert binary message to string."); + return new String(this.message); + } + + /** + * @return The message as a JSON object. + */ + public JsonObject asJson() { + return IDispatcher.JSON.fromJson( + this.asString(), JsonObject.class); + } + + /** + * @return The message as a JSON object. + * The type is specified. + */ + public T asJson(Class type) { + return IDispatcher.JSON.fromJson( + this.asString(), type); + } +}