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

This commit is contained in:
KingRainbow44
2022-05-01 20:15:27 -04:00
24 changed files with 460 additions and 54 deletions

View File

@@ -32,7 +32,7 @@ public final class DispatchHttpJsonHandler implements HttpContextHandler {
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 == 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)" : ""));
Grasscutter.getLogger().info(String.format("[Dispatch] Client %s %s request: %s", req.ip(), req.method(), req.baseUrl()) + (Grasscutter.getConfig().DebugMode == ServerDebugMode.MISSING ? "(MISSING)" : ""));
}
res.send(response);
}

View File

@@ -18,6 +18,7 @@ import emu.grasscutter.server.dispatch.json.*;
import emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData;
import emu.grasscutter.server.event.dispatch.QueryAllRegionsEvent;
import emu.grasscutter.server.event.dispatch.QueryCurrentRegionEvent;
import emu.grasscutter.server.http.gacha.GachaRecordHandler;
import emu.grasscutter.utils.FileUtils;
import express.Express;
import org.eclipse.jetty.server.Connector;
@@ -319,9 +320,6 @@ 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",
@@ -346,9 +344,6 @@ 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));
@@ -389,9 +384,6 @@ 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));
@@ -494,7 +486,7 @@ public final class DispatchServer {
// 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.get("/gacha", new GachaRecordHandler());
httpServer.listen(Grasscutter.getConfig().getDispatchOptions().Port);
Grasscutter.getLogger().info("[Dispatch] Dispatch server started on port " + httpServer.raw().port());

View File

@@ -16,7 +16,7 @@ public class LoginResultJson {
public static class VerifyAccountData {
public String uid;
public String name = "";
public String email;
public String email = "";
public String mobile = "";
public String is_email_verify = "0";
public String realname = "";

View File

@@ -22,27 +22,29 @@ public class GameServerPacketHandler {
this.registerHandlers(handlerClass);
}
public void registerPacketHandler(Class<? extends PacketHandler> handlerClass) {
try {
Opcodes opcode = handlerClass.getAnnotation(Opcodes.class);
if (opcode == null || opcode.disabled() || opcode.value() <= 0) {
return;
}
PacketHandler packetHandler = (PacketHandler) handlerClass.newInstance();
this.handlers.put(opcode.value(), packetHandler);
} catch (Exception e) {
e.printStackTrace();
}
}
public void registerHandlers(Class<? extends PacketHandler> handlerClass) {
Reflections reflections = new Reflections("emu.grasscutter.server.packet");
Set<?> handlerClasses = reflections.getSubTypesOf(handlerClass);
for (Object obj : handlerClasses) {
Class<?> c = (Class<?>) obj;
try {
Opcodes opcode = c.getAnnotation(Opcodes.class);
if (opcode == null || opcode.disabled() || opcode.value() <= 0) {
continue;
}
PacketHandler packetHandler = (PacketHandler) c.newInstance();
this.handlers.put(opcode.value(), packetHandler);
} catch (Exception e) {
e.printStackTrace();
}
this.registerPacketHandler((Class<? extends PacketHandler>) obj);
}
// Debug

View File

@@ -0,0 +1,52 @@
package emu.grasscutter.server.http.gacha;
import java.io.File;
import java.io.IOException;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.Account;
import emu.grasscutter.utils.FileUtils;
import express.http.HttpContextHandler;
import express.http.Request;
import express.http.Response;
public final class GachaRecordHandler implements HttpContextHandler {
String render_template;
public GachaRecordHandler() {
File template = new File(Grasscutter.getConfig().DATA_FOLDER + "gacha_records.html");
if (template.exists()) {
// Load from cache
render_template = new String(FileUtils.read(template));
} else {
render_template = "{{REPLACE_RECORD}}";
}
}
@Override
public void handle(Request req, Response res) throws IOException {
// Grasscutter.getLogger().info( req.query().toString() );
String sessionKey = req.query("s");
int page = 0;
int gachaType = 0;
if (req.query("p") != null) {
page = Integer.valueOf(req.query("p"));
}
if (req.query("gachaType") != null) {
gachaType = Integer.valueOf(req.query("gachaType"));
}
Account account = DatabaseHelper.getAccountBySessionKey(sessionKey);
if (account != null) {
String records = DatabaseHelper.getGachaRecords(account.getPlayerUid(), page, gachaType).toString();
// Grasscutter.getLogger().info(records);
String response = render_template.replace("{{REPLACE_RECORD}}", records)
.replace("{{REPLACE_MAXPAGE}}", String.valueOf(DatabaseHelper.getGachaRecordsMaxPage(account.getPlayerUid(), page, gachaType)));
res.send(response);
} else {
res.send("404");
}
}
}

View File

@@ -54,7 +54,7 @@ public class HandlerBuyGoodsReq extends PacketHandler {
session.getPlayer().save();
}
if (bought + buyGoodsReq.getBoughtNum() > sg.getBuyLimit()) {
if ((bought + buyGoodsReq.getBoughtNum() > sg.getBuyLimit()) && sg.getBuyLimit() != 0) {
return;
}

View File

@@ -11,7 +11,10 @@ public class HandlerGetGachaInfoReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
session.send(new PacketGetGachaInfoRsp(session.getServer().getGachaManager()));
session.send(new PacketGetGachaInfoRsp(session.getServer().getGachaManager(),
// TODO: use other Nonce/key insteadof session key to ensure the overall security for the player
session.getPlayer().getAccount().getSessionKey())
);
}
}

View File

@@ -4,6 +4,7 @@ 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.net.proto.RetcodeOuterClass;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketMcoinExchangeHcoinRsp;
@@ -15,13 +16,13 @@ public class HandlerMcoinExchangeHcoinReq extends PacketHandler {
McoinExchangeHcoinReqOuterClass.McoinExchangeHcoinReq exchangeReq = McoinExchangeHcoinReqOuterClass.McoinExchangeHcoinReq.parseFrom(payload);
if (session.getPlayer().getCrystals() < exchangeReq.getMCoinNum() && exchangeReq.getMCoinNum() == exchangeReq.getHCoinNum()) {
session.send(new PacketMcoinExchangeHcoinRsp(RetcodeOuterClass.Retcode.RET_UNKNOWN_ERROR_VALUE));
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()));
session.send(new PacketMcoinExchangeHcoinRsp(RetcodeOuterClass.Retcode.RET_SUCC_VALUE));
}
}

View File

@@ -6,9 +6,17 @@ import emu.grasscutter.net.packet.PacketOpcodes;
public class PacketGetGachaInfoRsp extends BasePacket {
@Deprecated
public PacketGetGachaInfoRsp(GachaManager manager) {
super(PacketOpcodes.GetGachaInfoRsp);
this.setData(manager.toProto());
}
public PacketGetGachaInfoRsp(GachaManager manager, String sessionKey) {
super(PacketOpcodes.GetGachaInfoRsp);
this.setData(manager.toProto(sessionKey));
}
}

View File

@@ -4,13 +4,19 @@ import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.GetShopmallDataRspOuterClass.GetShopmallDataRsp;
import java.util.List;
public class PacketGetShopmallDataRsp extends BasePacket {
public PacketGetShopmallDataRsp() {
super(PacketOpcodes.GetShopmallDataRsp);
GetShopmallDataRsp proto = GetShopmallDataRsp.newBuilder().build();
List<Integer> shop_malls = List.of(900, 1052, 902, 1001, 903);
GetShopmallDataRsp proto = GetShopmallDataRsp.newBuilder()
.addAllShopTypeList(shop_malls)
.build();
this.setData(proto);
}
}

View File

@@ -6,13 +6,13 @@ import emu.grasscutter.net.proto.McoinExchangeHcoinRspOuterClass;
public class PacketMcoinExchangeHcoinRsp extends BasePacket {
public PacketMcoinExchangeHcoinRsp(int mcoin, int hcoin) {
public PacketMcoinExchangeHcoinRsp(int retCode) {
super(PacketOpcodes.McoinExchangeHcoinRsp);
McoinExchangeHcoinRspOuterClass.McoinExchangeHcoinRsp mcoinExchangeHcoinRsp = McoinExchangeHcoinRspOuterClass.McoinExchangeHcoinRsp.newBuilder()
.setMCoinNum(mcoin)
.setHCoinNum(hcoin).build();
McoinExchangeHcoinRspOuterClass.McoinExchangeHcoinRsp proto = McoinExchangeHcoinRspOuterClass.McoinExchangeHcoinRsp.newBuilder()
.setRetcode(retCode)
.build();
this.setData(mcoinExchangeHcoinRsp);
this.setData(proto);
}
}