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

This commit is contained in:
KingRainbow44
2022-05-01 02:14:35 -04:00
19 changed files with 242 additions and 49 deletions

View File

@@ -4,6 +4,7 @@ import java.io.IOException;
import java.util.Arrays;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.Grasscutter.ServerDebugMode;
import express.http.HttpContextHandler;
import express.http.Request;
import express.http.Response;
@@ -30,8 +31,8 @@ public final class DispatchHttpJsonHandler implements HttpContextHandler {
@Override
public void handle(Request req, Response res) throws IOException {
// Checking for ALL here isn't required as when ALL is enabled enableDevLogging() gets enabled
if(Grasscutter.getConfig().DebugMode.equalsIgnoreCase("MISSING") && Arrays.stream(missingRoutes).anyMatch(x -> x == req.baseUrl())) {
Grasscutter.getLogger().info(String.format("[Dispatch] Client %s %s request: ", req.ip(), req.method(), req.baseUrl()) + (Grasscutter.getConfig().DebugMode.equalsIgnoreCase("MISSING") ? "(MISSING)" : ""));
if(Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING && Arrays.stream(missingRoutes).anyMatch(x -> x == req.baseUrl())) {
Grasscutter.getLogger().info(String.format("[Dispatch] Client %s %s request: ", req.ip(), req.method(), req.baseUrl()) + (Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING ? "(MISSING)" : ""));
}
res.send(response);
}

View File

@@ -6,6 +6,8 @@ import com.google.protobuf.ByteString;
import emu.grasscutter.Config;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.Grasscutter.ServerDebugMode;
import emu.grasscutter.Grasscutter.ServerRunMode;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.Account;
import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp;
@@ -62,7 +64,7 @@ public final class DispatchServer {
public QueryCurrRegionHttpRsp getCurrRegion() {
// Needs to be fixed by having the game servers connect to the dispatch server.
if (Grasscutter.getConfig().RunMode.equalsIgnoreCase("HYBRID")) {
if (Grasscutter.getConfig().RunMode == ServerRunMode.HYBRID) {
return regions.get(defaultServerName).parsedRegionQuery;
}
@@ -98,7 +100,7 @@ public final class DispatchServer {
List<RegionSimpleInfo> servers = new ArrayList<>();
List<String> usedNames = new ArrayList<>(); // List to check for potential naming conflicts
if (Grasscutter.getConfig().RunMode.equalsIgnoreCase("HYBRID")) { // Automatically add the game server if in
if (Grasscutter.getConfig().RunMode == ServerRunMode.HYBRID) { // Automatically add the game server if in
// hybrid mode
RegionSimpleInfo server = RegionSimpleInfo.newBuilder()
.setName("os_usa")
@@ -233,7 +235,7 @@ public final class DispatchServer {
});
config.enforceSsl = Grasscutter.getConfig().getDispatchOptions().UseSSL;
if(Grasscutter.getConfig().DebugMode.equalsIgnoreCase("ALL")) {
if(Grasscutter.getConfig().DebugMode == ServerDebugMode.ALL) {
config.enableDevLogging();
}
});
@@ -241,7 +243,7 @@ public final class DispatchServer {
httpServer.get("/", (req, res) -> res.send("Welcome to Grasscutter"));
httpServer.raw().error(404, ctx -> {
if(Grasscutter.getConfig().DebugMode.equalsIgnoreCase("MISSING")) {
if(Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING) {
Grasscutter.getLogger().info(String.format("[Dispatch] Potential unhandled %s request: %s", ctx.method(), ctx.url()));
}
ctx.contentType("text/html");
@@ -317,6 +319,9 @@ public final class DispatchServer {
responseData.data.account.uid = account.getId();
responseData.data.account.token = account.generateSessionKey();
responseData.data.account.email = account.getEmail();
if (responseData.data.account.email == null) {
responseData.data.account.email = "";
}
Grasscutter.getLogger()
.info(String.format("[Dispatch] Client %s failed to log in: Account %s created",
@@ -341,6 +346,9 @@ public final class DispatchServer {
responseData.data.account.uid = account.getId();
responseData.data.account.token = account.generateSessionKey();
responseData.data.account.email = account.getEmail();
if (responseData.data.account.email == null) {
responseData.data.account.email = "";
}
Grasscutter.getLogger().info(String.format("[Dispatch] Client %s logged in as %s", req.ip(),
responseData.data.account.uid));
@@ -381,6 +389,9 @@ public final class DispatchServer {
responseData.data.account.uid = requestData.uid;
responseData.data.account.token = requestData.token;
responseData.data.account.email = account.getEmail();
if (responseData.data.account.email == null) { // null will trigger crash in some client
responseData.data.account.email = "";
}
Grasscutter.getLogger().info(String.format("[Dispatch] Client %s logged in via token as %s",
req.ip(), responseData.data.account.uid));
@@ -437,7 +448,8 @@ public final class DispatchServer {
// hk4e-sdk-os.hoyoverse.com
httpServer.get("/hk4e_global/mdk/agreement/api/getAgreementInfos", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"marketing_agreements\":[]}}"));
// hk4e-sdk-os.hoyoverse.com
httpServer.post("/hk4e_global/combo/granter/api/compareProtocolVersion", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":true,\"protocol\":{\"id\":0,\"app_id\":4,\"language\":\"en\",\"user_proto\":\"\",\"priv_proto\":\"\",\"major\":7,\"minimum\":0,\"create_time\":\"0\",\"teenager_proto\":\"\",\"third_proto\":\"\"}}}"));
// this could be either GET or POST based on the observation of different clients
httpServer.all("/hk4e_global/combo/granter/api/compareProtocolVersion", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":true,\"protocol\":{\"id\":0,\"app_id\":4,\"language\":\"en\",\"user_proto\":\"\",\"priv_proto\":\"\",\"major\":7,\"minimum\":0,\"create_time\":\"0\",\"teenager_proto\":\"\",\"third_proto\":\"\"}}}"));
// Game data
// hk4e-api-os.hoyoverse.com
@@ -479,6 +491,9 @@ public final class DispatchServer {
// log-upload-os.mihoyo.com
httpServer.all("/crash/dataUpload", new ClientLogHandler());
// webstatic-sea.hoyoverse.com
httpServer.get("/admin/mi18n/plat_oversea/m202003048/m202003048-version.json", new DispatchHttpJsonHandler("{\"version\":51}"));
httpServer.get("/gacha", (req, res) -> res.send("<!doctype html><html lang=\"en\"><head><title>Gacha</title></head><body></body></html>"));
httpServer.listen(Grasscutter.getConfig().getDispatchOptions().Port);

View File

@@ -6,6 +6,7 @@ import emu.grasscutter.server.event.game.ReceivePacketEvent;
import org.reflections.Reflections;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.Grasscutter.ServerDebugMode;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
@@ -88,7 +89,7 @@ public class GameServerPacketHandler {
}
// Log unhandled packets
if (Grasscutter.getConfig().DebugMode.equalsIgnoreCase("MISSING")) {
if (Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING) {
Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtil.getOpcodeName(opcode));
}
}

View File

@@ -7,6 +7,7 @@ import java.util.HashSet;
import java.util.Set;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.Grasscutter.ServerDebugMode;
import emu.grasscutter.game.Account;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.packet.BasePacket;
@@ -163,7 +164,7 @@ public class GameSession extends KcpChannel {
}
// Log
if (Grasscutter.getConfig().DebugMode.equalsIgnoreCase("ALL")) {
if (Grasscutter.getConfig().DebugMode == ServerDebugMode.ALL) {
logPacket(packet);
}
@@ -230,7 +231,7 @@ public class GameSession extends KcpChannel {
}
// Log packet
if (Grasscutter.getConfig().DebugMode.equalsIgnoreCase("ALL")) {
if (Grasscutter.getConfig().DebugMode == ServerDebugMode.ALL) {
if (!loopPacket.contains(opcode)) {
Grasscutter.getLogger().info("RECV: " + PacketOpcodesUtil.getOpcodeName(opcode) + " (" + opcode + ")");
System.out.println(Utils.bytesToHex(payload));

View File

@@ -0,0 +1,27 @@
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.McoinExchangeHcoinReqOuterClass;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketMcoinExchangeHcoinRsp;
@Opcodes(PacketOpcodes.McoinExchangeHcoinReq)
public class HandlerMcoinExchangeHcoinReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
McoinExchangeHcoinReqOuterClass.McoinExchangeHcoinReq exchangeReq = McoinExchangeHcoinReqOuterClass.McoinExchangeHcoinReq.parseFrom(payload);
if (session.getPlayer().getCrystals() < exchangeReq.getMCoinNum() && exchangeReq.getMCoinNum() == exchangeReq.getHCoinNum()) {
return;
}
session.getPlayer().setCrystals(session.getPlayer().getCrystals() - exchangeReq.getMCoinNum());
session.getPlayer().setPrimogems(session.getPlayer().getPrimogems() + exchangeReq.getHCoinNum());
session.getPlayer().save();
session.send(new PacketMcoinExchangeHcoinRsp(session.getPlayer().getCrystals(), session.getPlayer().getPrimogems()));
}
}

View File

@@ -0,0 +1,21 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.AvatarSkillMaxChargeCountNotifyOuterClass.AvatarSkillMaxChargeCountNotify;
public class PacketAvatarSkillMaxChargeCountNotify extends BasePacket {
public PacketAvatarSkillMaxChargeCountNotify(Avatar avatar, int skillId, int maxCharges) {
super(PacketOpcodes.AvatarSkillMaxChargeCountNotify);
AvatarSkillMaxChargeCountNotify proto = AvatarSkillMaxChargeCountNotify.newBuilder()
.setAvatarGuid(avatar.getGuid())
.setSkillId(skillId)
.setMaxChargeCount(maxCharges)
.build();
this.setData(proto);
}
}

View File

@@ -0,0 +1,18 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.McoinExchangeHcoinRspOuterClass;
public class PacketMcoinExchangeHcoinRsp extends BasePacket {
public PacketMcoinExchangeHcoinRsp(int mcoin, int hcoin) {
super(PacketOpcodes.McoinExchangeHcoinRsp);
McoinExchangeHcoinRspOuterClass.McoinExchangeHcoinRsp mcoinExchangeHcoinRsp = McoinExchangeHcoinRspOuterClass.McoinExchangeHcoinRsp.newBuilder()
.setMCoinNum(mcoin)
.setHCoinNum(hcoin).build();
this.setData(mcoinExchangeHcoinRsp);
}
}

View File

@@ -2,6 +2,8 @@ package emu.grasscutter.server.packet.send;
import com.google.protobuf.ByteString;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.Grasscutter.ServerDebugMode;
import emu.grasscutter.Grasscutter.ServerRunMode;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.PlayerLoginRspOuterClass.PlayerLoginRsp;
@@ -25,7 +27,7 @@ public class PacketPlayerLoginRsp extends BasePacket {
RegionInfo info;
if(Grasscutter.getConfig().RunMode.equalsIgnoreCase("GAME_ONLY")) {
if (Grasscutter.getConfig().RunMode == ServerRunMode.GAME_ONLY) {
if (regionCache == null) {
try {
File file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_cur_region.txt");