Merge remote-tracking branch 'origin/unstable' into unstable

This commit is contained in:
KingRainbow44 2023-05-15 03:46:29 -04:00
commit 964cc8143b
No known key found for this signature in database
GPG Key ID: FC2CB64B00D257BE
8 changed files with 91 additions and 114 deletions

View File

@ -1,5 +1,7 @@
package emu.grasscutter.database;
import static com.mongodb.client.model.Filters.eq;
import com.mongodb.client.result.DeleteResult;
import dev.morphia.query.FindOptions;
import dev.morphia.query.Sort;
@ -20,12 +22,9 @@ import emu.grasscutter.game.mail.Mail;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.game.world.SceneGroupInstance;
import java.util.List;
import java.util.stream.Stream;
import static com.mongodb.client.model.Filters.eq;
public final class DatabaseHelper {
public static Account createAccount(String username) {
return createAccountWithUid(username, 0);
@ -219,8 +218,8 @@ public final class DatabaseHelper {
}
/**
* Use {@link DatabaseHelper#getPlayerByAccount(Account, Class)} for creating a real player.
* This method is used for fetching the player's data.
* Use {@link DatabaseHelper#getPlayerByAccount(Account, Class)} for creating a real player. This
* method is used for fetching the player's data.
*
* @param accountId The account's ID.
* @return The player.

View File

@ -8,7 +8,6 @@ import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.server.packet.send.PacketAddNoGachaAvatarCardNotify;
import emu.grasscutter.utils.objects.HandbookBody.*;
import java.util.Objects;
/** Commands executed by the handbook. */
@ -22,8 +21,7 @@ public interface HandbookActions {
static Response grantAvatar(GrantAvatar request) {
// Validate the request.
if (request.getPlayer() == null || request.getAvatar() == null) {
return Response.builder().status(400)
.message("Invalid request.").build();
return Response.builder().status(400).message("Invalid request.").build();
}
try {
@ -37,12 +35,10 @@ public interface HandbookActions {
// Validate the request.
if (player == null) {
return Response.builder().status(1)
.message("Player not found.").build();
return Response.builder().status(1).message("Player not found.").build();
}
if (avatarData == null) {
return Response.builder().status(400)
.message("Invalid avatar ID.").build();
return Response.builder().status(400).message("Invalid avatar ID.").build();
}
// Create the new avatar.
@ -58,17 +54,16 @@ public interface HandbookActions {
// Add the avatar.
player.addAvatar(avatar);
player.sendPacket(new PacketAddNoGachaAvatarCardNotify(
avatar, ActionReason.Gm));
return Response.builder().status(200)
.message("Avatar granted.").build();
player.sendPacket(new PacketAddNoGachaAvatarCardNotify(avatar, ActionReason.Gm));
return Response.builder().status(200).message("Avatar granted.").build();
} catch (NumberFormatException ignored) {
return Response.builder().status(500)
.message("Invalid player UID or avatar ID.").build();
return Response.builder().status(500).message("Invalid player UID or avatar ID.").build();
} catch (Exception exception) {
Grasscutter.getLogger().debug("A handbook command error occurred.", exception);
return Response.builder().status(500)
.message("An error occurred while granting the avatar.").build();
return Response.builder()
.status(500)
.message("An error occurred while granting the avatar.")
.build();
}
}
@ -81,8 +76,7 @@ public interface HandbookActions {
static Response giveItem(GiveItem request) {
// Validate the request.
if (request.getPlayer() == null || request.getItem() == null) {
return Response.builder().status(400)
.message("Invalid request.").build();
return Response.builder().status(400).message("Invalid request.").build();
}
try {
@ -96,12 +90,10 @@ public interface HandbookActions {
// Validate the request.
if (player == null) {
return Response.builder().status(1)
.message("Player not found.").build();
return Response.builder().status(1).message("Player not found.").build();
}
if (itemData == null) {
return Response.builder().status(400)
.message("Invalid player UID or item ID.").build();
return Response.builder().status(400).message("Invalid player UID or item ID.").build();
}
// Add the item to the player's inventory.
@ -122,15 +114,15 @@ public interface HandbookActions {
var itemStack = new GameItem(itemData, (int) amount);
player.getInventory().addItem(itemStack, ActionReason.Gm);
return Response.builder().status(200)
.message("Item granted.").build();
return Response.builder().status(200).message("Item granted.").build();
} catch (NumberFormatException ignored) {
return Response.builder().status(500)
.message("Invalid player UID or item ID.").build();
return Response.builder().status(500).message("Invalid player UID or item ID.").build();
} catch (Exception exception) {
Grasscutter.getLogger().debug("A handbook command error occurred.", exception);
return Response.builder().status(500)
.message("An error occurred while granting the item.").build();
return Response.builder()
.status(500)
.message("An error occurred while granting the item.")
.build();
}
}
@ -143,8 +135,7 @@ public interface HandbookActions {
static Response teleportTo(TeleportTo request) {
// Validate the request.
if (request.getPlayer() == null || request.getScene() == null) {
return Response.builder().status(400)
.message("Invalid request.").build();
return Response.builder().status(400).message("Invalid request.").build();
}
try {
@ -157,15 +148,13 @@ public interface HandbookActions {
// Validate the request.
if (player == null) {
return Response.builder().status(1)
.message("Player not found.").build();
return Response.builder().status(1).message("Player not found.").build();
}
// Find the scene in the player's world.
var scene = player.getWorld().getSceneById(sceneId);
if (scene == null) {
return Response.builder().status(400)
.message("Invalid scene ID.").build();
return Response.builder().status(400).message("Invalid scene ID.").build();
}
// Resolve the correct teleport position.
@ -175,15 +164,15 @@ public interface HandbookActions {
scene.getWorld().transferPlayerToScene(player, scene.getId(), position);
player.getRotation().set(rotation);
return Response.builder().status(200)
.message("Player teleported.").build();
return Response.builder().status(200).message("Player teleported.").build();
} catch (NumberFormatException ignored) {
return Response.builder().status(400)
.message("Invalid player UID or scene ID.").build();
return Response.builder().status(400).message("Invalid player UID or scene ID.").build();
} catch (Exception exception) {
Grasscutter.getLogger().debug("A handbook command error occurred.", exception);
return Response.builder().status(500)
.message("An error occurred while teleporting to the scene.").build();
return Response.builder()
.status(500)
.message("An error occurred while teleporting to the scene.")
.build();
}
}
@ -196,8 +185,7 @@ public interface HandbookActions {
static Response spawnEntity(SpawnEntity request) {
// Validate the request.
if (request.getPlayer() == null || request.getEntity() == null) {
return Response.builder().status(400)
.message("Invalid request.").build();
return Response.builder().status(400).message("Invalid request.").build();
}
try {
@ -211,20 +199,17 @@ public interface HandbookActions {
// Validate the request.
if (player == null) {
return Response.builder().status(1)
.message("Player not found.").build();
return Response.builder().status(1).message("Player not found.").build();
}
if (entityData == null) {
return Response.builder().status(400)
.message("Invalid entity ID.").build();
return Response.builder().status(400).message("Invalid entity ID.").build();
}
// Validate request properties.
var scene = player.getScene();
var level = request.getLevel();
if (scene == null || level > 200 || level < 1) {
return Response.builder().status(400)
.message("Invalid scene or level.").build();
return Response.builder().status(400).message("Invalid scene or level.").build();
}
// Create the entity.
@ -233,15 +218,15 @@ public interface HandbookActions {
scene.addEntity(entity);
}
return Response.builder().status(200)
.message("Entity(s) spawned.").build();
return Response.builder().status(200).message("Entity(s) spawned.").build();
} catch (NumberFormatException ignored) {
return Response.builder().status(400)
.message("Invalid player UID or entity ID.").build();
return Response.builder().status(400).message("Invalid player UID or entity ID.").build();
} catch (Exception exception) {
Grasscutter.getLogger().debug("A handbook command error occurred.", exception);
return Response.builder().status(500)
.message("An error occurred while teleporting to the scene.").build();
return Response.builder()
.status(500)
.message("An error occurred while teleporting to the scene.")
.build();
}
}
}

View File

@ -1,5 +1,7 @@
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;
@ -10,12 +12,6 @@ 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;
@ -25,8 +21,11 @@ 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;
import lombok.Getter;
import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
public final class DispatchClient extends WebSocketClient implements IDispatcher {
@Getter private final Logger logger = Grasscutter.getLogger();
@ -89,7 +88,10 @@ public final class DispatchClient extends WebSocketClient implements IDispatcher
var action = HandbookBody.Action.valueOf(actionStr);
// Produce a handbook response.
var response = DispatchUtils.performHandbookAction(action, switch (action) {
var response =
DispatchUtils.performHandbookAction(
action,
switch (action) {
case GRANT_AVATAR -> JsonUtils.decode(data, HandbookBody.GrantAvatar.class);
case GIVE_ITEM -> JsonUtils.decode(data, HandbookBody.GiveItem.class);
case TELEPORT_TO -> JsonUtils.decode(data, HandbookBody.TeleportTo.class);

View File

@ -1,22 +1,21 @@
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.function.BiConsumer;
import java.util.function.Consumer;
import static emu.grasscutter.config.Configuration.DISPATCH_INFO;
import org.java_websocket.WebSocket;
import org.slf4j.Logger;
public interface IDispatcher {
Gson JSON =

View File

@ -1,5 +1,7 @@
package emu.grasscutter.server.http.documentation;
import static emu.grasscutter.config.Configuration.HANDBOOK;
import emu.grasscutter.server.http.Router;
import emu.grasscutter.utils.DispatchUtils;
import emu.grasscutter.utils.FileUtils;
@ -8,8 +10,6 @@ import emu.grasscutter.utils.objects.HandbookBody.Action;
import io.javalin.Javalin;
import io.javalin.http.Context;
import static emu.grasscutter.config.Configuration.HANDBOOK;
/** Handles requests for the new GM Handbook. */
public final class HandbookHandler implements Router {
private final byte[] handbook;
@ -74,11 +74,9 @@ public final class HandbookHandler implements Router {
// Parse the request body into a class.
var request = ctx.bodyAsClass(HandbookBody.GrantAvatar.class);
// Get the response.
var response = DispatchUtils.performHandbookAction(
Action.GRANT_AVATAR, request);
var response = DispatchUtils.performHandbookAction(Action.GRANT_AVATAR, request);
// Send the response.
ctx.status(response.getStatus() > 100 ?
response.getStatus() : 500).json(response);
ctx.status(response.getStatus() > 100 ? response.getStatus() : 500).json(response);
}
/**
@ -96,11 +94,9 @@ public final class HandbookHandler implements Router {
// Parse the request body into a class.
var request = ctx.bodyAsClass(HandbookBody.GiveItem.class);
// Get the response.
var response = DispatchUtils.performHandbookAction(
Action.GIVE_ITEM, request);
var response = DispatchUtils.performHandbookAction(Action.GIVE_ITEM, request);
// Send the response.
ctx.status(response.getStatus() > 100 ?
response.getStatus() : 500).json(response);
ctx.status(response.getStatus() > 100 ? response.getStatus() : 500).json(response);
}
/**
@ -118,11 +114,9 @@ public final class HandbookHandler implements Router {
// Parse the request body into a class.
var request = ctx.bodyAsClass(HandbookBody.TeleportTo.class);
// Get the response.
var response = DispatchUtils.performHandbookAction(
Action.TELEPORT_TO, request);
var response = DispatchUtils.performHandbookAction(Action.TELEPORT_TO, request);
// Send the response.
ctx.status(response.getStatus() > 100 ?
response.getStatus() : 500).json(response);
ctx.status(response.getStatus() > 100 ? response.getStatus() : 500).json(response);
}
/**
@ -138,13 +132,10 @@ public final class HandbookHandler implements Router {
}
// Parse the request body into a class.
var request = ctx.bodyAsClass(
HandbookBody.SpawnEntity.class);
var request = ctx.bodyAsClass(HandbookBody.SpawnEntity.class);
// Get the response.
var response = DispatchUtils.performHandbookAction(
Action.SPAWN_ENTITY, request);
var response = DispatchUtils.performHandbookAction(Action.SPAWN_ENTITY, request);
// Send the response.
ctx.status(response.getStatus() > 100 ?
response.getStatus() : 500).json(response);
ctx.status(response.getStatus() > 100 ? response.getStatus() : 500).json(response);
}
}

View File

@ -1,5 +1,7 @@
package emu.grasscutter.server.http.handlers;
import static emu.grasscutter.utils.Language.translate;
import com.google.gson.JsonObject;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.database.DatabaseHelper;
@ -11,16 +13,13 @@ import emu.grasscutter.utils.Utils;
import io.javalin.Javalin;
import io.javalin.http.ContentType;
import io.javalin.http.Context;
import lombok.Getter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.LinkedHashSet;
import static emu.grasscutter.utils.Language.translate;
import lombok.Getter;
/** Handles all gacha-related HTTP requests. */
public final class GachaHandler implements Router {
@ -164,7 +163,6 @@ public final class GachaHandler implements Router {
public void applyRoutes(Javalin javalin) {
javalin.get("/gacha", GachaHandler::gachaRecords);
javalin.get("/gacha/details", GachaHandler::gachaDetails);
javalin.get("/gacha/mappings", ctx ->
ctx.result(FileUtils.read(gachaMappingsPath.toString())));
javalin.get("/gacha/mappings", ctx -> ctx.result(FileUtils.read(gachaMappingsPath.toString())));
}
}

View File

@ -1,5 +1,7 @@
package emu.grasscutter.utils;
import static emu.grasscutter.config.Configuration.DISPATCH_INFO;
import com.google.gson.JsonObject;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest;
@ -12,13 +14,10 @@ import emu.grasscutter.server.http.handlers.GachaHandler;
import emu.grasscutter.server.http.objects.LoginTokenRequestJson;
import emu.grasscutter.utils.objects.HandbookBody;
import emu.grasscutter.utils.objects.HandbookBody.*;
import javax.annotation.Nullable;
import java.net.http.HttpClient;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import static emu.grasscutter.config.Configuration.DISPATCH_INFO;
import javax.annotation.Nullable;
public interface DispatchUtils {
/** HTTP client used for dispatch queries. */
@ -136,8 +135,9 @@ public interface DispatchUtils {
var future = new CompletableFuture<Response>();
// Listen for the response.
var server = Grasscutter.getDispatchServer();
server.registerCallback(PacketIds.GmTalkRsp, packet ->
future.complete(IDispatcher.decode(packet, Response.class)));
server.registerCallback(
PacketIds.GmTalkRsp,
packet -> future.complete(IDispatcher.decode(packet, Response.class)));
// Broadcast the request.
server.sendMessage(PacketIds.GmTalkReq, request);
@ -146,8 +146,10 @@ public interface DispatchUtils {
// Wait for the response.
yield future.get(5L, TimeUnit.SECONDS);
} catch (Exception ignored) {
yield Response.builder().status(400)
.message("No response received from any server.").build();
yield Response.builder()
.status(400)
.message("No response received from any server.")
.build();
}
}
case HYBRID, GAME_ONLY -> switch (action) {

View File

@ -6,7 +6,8 @@ import lombok.Getter;
/** HTTP request object for handbook controls. */
@SuppressWarnings("FieldMayBeFinal")
public interface HandbookBody {
@Builder @Getter
@Builder
@Getter
class Response {
private int status;
private String message;