mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-22 07:37:43 +00:00
Merge remote-tracking branch 'origin/unstable' into unstable
This commit is contained in:
commit
964cc8143b
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 =
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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())));
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user