mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2026-06-04 14:13:57 +08:00
Implement proper handbook authentication (pt. 1)
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
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;
|
||||
@@ -12,21 +10,25 @@ import emu.grasscutter.utils.Crypto;
|
||||
import emu.grasscutter.utils.DispatchUtils;
|
||||
import emu.grasscutter.utils.JsonUtils;
|
||||
import emu.grasscutter.utils.objects.HandbookBody;
|
||||
import java.net.ConnectException;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
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 java.net.ConnectException;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.DISPATCH_INFO;
|
||||
|
||||
public final class DispatchClient extends WebSocketClient implements IDispatcher {
|
||||
@Getter private final Logger logger = Grasscutter.getLogger();
|
||||
@Getter private final Map<Integer, BiConsumer<WebSocket, JsonElement>> handlers = new HashMap<>();
|
||||
@@ -41,6 +43,7 @@ public final class DispatchClient extends WebSocketClient implements IDispatcher
|
||||
|
||||
this.registerHandler(PacketIds.GachaHistoryReq, this::fetchGachaHistory);
|
||||
this.registerHandler(PacketIds.GmTalkReq, this::handleHandbookAction);
|
||||
this.registerHandler(PacketIds.GetPlayerFieldsReq, this::fetchPlayerFields);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,6 +108,32 @@ public final class DispatchClient extends WebSocketClient implements IDispatcher
|
||||
this.sendMessage(PacketIds.GmTalkRsp, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the fields of an online player.
|
||||
*
|
||||
* @param socket The socket the packet was received from.
|
||||
* @param object The packet data.
|
||||
*/
|
||||
private void fetchPlayerFields(WebSocket socket, JsonElement object) {
|
||||
var message = IDispatcher.decode(object);
|
||||
var playerId = message.get("playerId").getAsInt();
|
||||
var fieldsRaw = message.get("fields").getAsJsonArray();
|
||||
|
||||
// Get the player with the specified ID.
|
||||
var player = Grasscutter.getGameServer().getPlayerByUid(playerId, true);
|
||||
if (player == null) return;
|
||||
|
||||
// Convert the fields array.
|
||||
var fieldsList = new ArrayList<String>();
|
||||
for (var field : fieldsRaw)
|
||||
fieldsList.add(field.getAsString());
|
||||
var fields = fieldsList.toArray(new String[0]);
|
||||
|
||||
// Return the response object.
|
||||
this.sendMessage(PacketIds.GetPlayerFieldsRsp,
|
||||
DispatchUtils.getPlayerFields(playerId, fields));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a serialized encrypted message to the server.
|
||||
*
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
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.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 +19,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 {
|
||||
@@ -39,6 +40,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,6 +86,23 @@ public final class DispatchServer extends WebSocketServer implements IDispatcher
|
||||
this.sendMessage(socket, PacketIds.TokenValidateRsp, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an account by its ID.
|
||||
*
|
||||
* @param socket The socket the packet was received from.
|
||||
* @param object The packet data.
|
||||
*/
|
||||
private void fetchAccount(WebSocket socket, JsonElement object) {
|
||||
var message = IDispatcher.decode(object);
|
||||
var accountId = message.get("accountId").getAsString();
|
||||
|
||||
// Get the account from the database.
|
||||
var account = DatabaseHelper.getAccountById(accountId);
|
||||
// Send the account.
|
||||
this.sendMessage(socket, PacketIds.GetAccountRsp,
|
||||
JSON.toJsonTree(account));
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts an encrypted message to all connected clients.
|
||||
*
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
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;
|
||||
import com.google.gson.JsonObject;
|
||||
import emu.grasscutter.utils.Crypto;
|
||||
import emu.grasscutter.utils.JsonAdapters.ByteArrayAdapter;
|
||||
import org.java_websocket.WebSocket;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import org.java_websocket.WebSocket;
|
||||
import org.slf4j.Logger;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.DISPATCH_INFO;
|
||||
|
||||
public interface IDispatcher {
|
||||
Gson JSON =
|
||||
@@ -24,6 +28,9 @@ public interface IDispatcher {
|
||||
.registerTypeAdapter(byte[].class, new ByteArrayAdapter())
|
||||
.create();
|
||||
|
||||
Function<JsonElement, JsonObject> DEFAULT_PARSER = (packet) ->
|
||||
IDispatcher.decode(packet, JsonObject.class);
|
||||
|
||||
/**
|
||||
* Decodes an escaped JSON message.
|
||||
*
|
||||
@@ -61,6 +68,75 @@ public interface IDispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a request from the other server to be fulfilled.
|
||||
*
|
||||
* @param request The request data.
|
||||
* @param requestId The request packet ID.
|
||||
* @param responseId the response packet ID.
|
||||
* @param parser The parser for the response data.
|
||||
* @return The fulfilled data, or null.
|
||||
* @param <T> The type of data to be returned.
|
||||
*/
|
||||
default <T> T await(JsonObject request, int requestId, int responseId,
|
||||
Function<JsonElement, T> parser) {
|
||||
// Perform the setup for the request.
|
||||
var future = this.async(request, requestId, responseId, parser);
|
||||
|
||||
try {
|
||||
// Try to return the value.
|
||||
return future.get(5L, TimeUnit.SECONDS);
|
||||
} catch (Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback for a packet to be received.
|
||||
* Sends a packet with the provided request.
|
||||
*
|
||||
* @param request The request object.
|
||||
* @param requestId The packet ID of the request packet.
|
||||
* @param responseId The packet ID of the response packet.
|
||||
* @return A promise containing the parsed JSON data.
|
||||
*/
|
||||
default CompletableFuture<JsonObject> async(JsonObject request, int requestId, int responseId) {
|
||||
return this.async(request, requestId, responseId, DEFAULT_PARSER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback for a packet to be received.
|
||||
* Sends a packet with the provided request.
|
||||
*
|
||||
* @param request The request object.
|
||||
* @param requestId The packet ID of the request packet.
|
||||
* @param responseId The packet ID of the response packet.
|
||||
* @param parser The parser for the received data.
|
||||
* @return A promise containing the parsed JSON data.
|
||||
*/
|
||||
default <T> CompletableFuture<T> async(
|
||||
JsonObject request, int requestId, int responseId,
|
||||
Function<JsonElement, T> parser
|
||||
) {
|
||||
// Create the future.
|
||||
var future = new CompletableFuture<T>();
|
||||
// Listen for the response.
|
||||
this.registerCallback(responseId, packet ->
|
||||
future.complete(parser.apply(packet)));
|
||||
// Broadcast the packet.
|
||||
this.sendMessage(requestId, request);
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internally used method to broadcast a packet.
|
||||
*
|
||||
* @param packetId The packet ID.
|
||||
* @param message The packet data.
|
||||
*/
|
||||
void sendMessage(int packetId, Object message);
|
||||
|
||||
/**
|
||||
* Decodes a message from the client.
|
||||
*
|
||||
|
||||
@@ -11,4 +11,8 @@ public interface PacketIds {
|
||||
int GachaHistoryRsp = 5;
|
||||
int GmTalkReq = PacketOpcodes.GmTalkReq;
|
||||
int GmTalkRsp = PacketOpcodes.GmTalkRsp;
|
||||
int GetAccountReq = 6;
|
||||
int GetAccountRsp = 7;
|
||||
int GetPlayerFieldsReq = 8;
|
||||
int GetPlayerFieldsRsp = 9;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user