Upgrade to REL3.7 (#2164)

* Remove hardcoded quest data

* Remove deprecated fields

* Try to fix packet

* Apply fix for token exchange

* Upgrade to REL3.7

* Add obfuscated protocol definitions

* Add missing enum (other protos too maybe)

* Re-add field setters and add note on removal
This commit is contained in:
Magix
2023-05-26 21:29:02 -07:00
committed by GitHub
parent 19bf2dfc69
commit 71f6198361
1382 changed files with 227151 additions and 199655 deletions

View File

@@ -1,9 +1,5 @@
package emu.grasscutter.server.game;
import java.io.File;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.Grasscutter.ServerDebugMode;
import emu.grasscutter.game.Account;
@@ -20,7 +16,12 @@ import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
import static emu.grasscutter.config.Configuration.*;
import java.io.File;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import static emu.grasscutter.config.Configuration.GAME_INFO;
import static emu.grasscutter.config.Configuration.SERVER;
import static emu.grasscutter.utils.Language.translate;
public class GameSession implements GameSessionManager.KcpChannel {
@@ -158,7 +159,10 @@ public class GameSession implements GameSessionManager.KcpChannel {
@Override
public void handleReceive(byte[] bytes) {
// Decrypt and turn back into a packet
Crypto.xor(bytes, useSecretKey() ? Crypto.ENCRYPT_KEY : Crypto.DISPATCH_KEY);
if (this.getState() != SessionState.WAITING_FOR_TOKEN)
Crypto.xor(bytes, useSecretKey() ?
Crypto.ENCRYPT_KEY :
Crypto.DISPATCH_KEY);
ByteBuf packet = Unpooled.wrappedBuffer(bytes);
// Log

View File

@@ -1,110 +1,109 @@
package emu.grasscutter.server.game;
import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.utils.Crypto;
import emu.grasscutter.utils.Utils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.DefaultEventLoop;
import kcp.highway.KcpListener;
import kcp.highway.Ukcp;
public class GameSessionManager {
private static final DefaultEventLoop logicThread = new DefaultEventLoop();
private static final ConcurrentHashMap<Ukcp,GameSession> sessions = new ConcurrentHashMap<>();
private static final KcpListener listener = new KcpListener(){
@Override
public void onConnected(Ukcp ukcp) {
int times = 0;
GameServer server = Grasscutter.getGameServer();
while (server==null){//Waiting server to establish
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
ukcp.close();
return;
}
if(times++>5){
Grasscutter.getLogger().error("Service is not available!");
ukcp.close();
return;
}
server = Grasscutter.getGameServer();
}
GameSession conversation = new GameSession(server);
conversation.onConnected(new KcpTunnel(){
@Override
public InetSocketAddress getAddress() {
return ukcp.user().getRemoteAddress();
}
@Override
public void writeData(byte[] bytes) {
ByteBuf buf = Unpooled.wrappedBuffer(bytes);
ukcp.write(buf);
buf.release();
}
@Override
public void close() {
ukcp.close();
}
@Override
public int getSrtt() {
return ukcp.srtt();
}
});
sessions.put(ukcp,conversation);
}
@Override
public void handleReceive(ByteBuf buf, Ukcp kcp) {
byte[] byteData = Utils.byteBufToArray(buf);
logicThread.execute(() -> {
try {
GameSession conversation = sessions.get(kcp);
if(conversation!=null) {
conversation.handleReceive(byteData);
}
}catch (Exception e){
e.printStackTrace();
}
});
}
@Override
public void handleException(Throwable ex, Ukcp ukcp) {
}
@Override
public void handleClose(Ukcp ukcp) {
GameSession conversation = sessions.get(ukcp);
if(conversation!=null) {
conversation.handleClose();
sessions.remove(ukcp);
}
}
};
public static KcpListener getListener() {
return listener;
}
interface KcpTunnel{
InetSocketAddress getAddress();
void writeData(byte[] bytes);
void close();
int getSrtt();
}
interface KcpChannel{
void onConnected(KcpTunnel tunnel);
void handleClose();
void handleReceive(byte[] bytes);
}
}
package emu.grasscutter.server.game;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.utils.Utils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.DefaultEventLoop;
import kcp.highway.KcpListener;
import kcp.highway.Ukcp;
import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;
public class GameSessionManager {
private static final DefaultEventLoop logicThread = new DefaultEventLoop();
private static final ConcurrentHashMap<Ukcp,GameSession> sessions = new ConcurrentHashMap<>();
private static final KcpListener listener = new KcpListener(){
@Override
public void onConnected(Ukcp ukcp) {
int times = 0;
GameServer server = Grasscutter.getGameServer();
while (server==null){//Waiting server to establish
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
ukcp.close();
return;
}
if(times++>5){
Grasscutter.getLogger().error("Service is not available!");
ukcp.close();
return;
}
server = Grasscutter.getGameServer();
}
GameSession conversation = new GameSession(server);
conversation.onConnected(new KcpTunnel(){
@Override
public InetSocketAddress getAddress() {
return ukcp.user().getRemoteAddress();
}
@Override
public void writeData(byte[] bytes) {
ByteBuf buf = Unpooled.wrappedBuffer(bytes);
ukcp.write(buf);
buf.release();
}
@Override
public void close() {
ukcp.close();
}
@Override
public int getSrtt() {
return ukcp.srtt();
}
});
sessions.put(ukcp,conversation);
}
@Override
public void handleReceive(ByteBuf buf, Ukcp kcp) {
var byteData = Utils.byteBufToArray(buf);
logicThread.execute(() -> {
try {
GameSession conversation = sessions.get(kcp);
if(conversation != null) {
conversation.handleReceive(byteData);
}
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void handleException(Throwable ex, Ukcp ukcp) {
}
@Override
public void handleClose(Ukcp ukcp) {
GameSession conversation = sessions.get(ukcp);
if(conversation!=null) {
conversation.handleClose();
sessions.remove(ukcp);
}
}
};
public static KcpListener getListener() {
return listener;
}
interface KcpTunnel{
InetSocketAddress getAddress();
void writeData(byte[] bytes);
void close();
int getSrtt();
}
interface KcpChannel{
void onConnected(KcpTunnel tunnel);
void handleClose();
void handleReceive(byte[] bytes);
}
}

View File

@@ -12,7 +12,7 @@ public class PacketGachaWishRsp extends BasePacket {
GachaWishRsp proto = GachaWishRsp.newBuilder()
.setGachaType(gachaType)
.setGachaScheduleId(scheduleId)
.setWishItemId(itemId)
.setTenCostItemId(itemId)
.setWishProgress(progress)
.setWishMaxProgress(maxProgress)
.build();

View File

@@ -14,6 +14,7 @@ public class PacketGetPlayerTokenRsp extends BasePacket {
super(PacketOpcodes.GetPlayerTokenRsp, true);
this.setUseDispatchKey(true);
this.shouldEncrypt = false;
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
.setUid(session.getPlayer().getUid())
@@ -37,6 +38,7 @@ public class PacketGetPlayerTokenRsp extends BasePacket {
super(PacketOpcodes.GetPlayerTokenRsp, true);
this.setUseDispatchKey(true);
this.shouldEncrypt = false;
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
.setUid(session.getPlayer().getUid())
@@ -56,6 +58,7 @@ public class PacketGetPlayerTokenRsp extends BasePacket {
super(PacketOpcodes.GetPlayerTokenRsp, true);
this.setUseDispatchKey(true);
this.shouldEncrypt = false;
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
.setUid(session.getPlayer().getUid())

View File

@@ -42,9 +42,11 @@ public class PacketGetShopRsp extends BasePacket {
.setEndTime(info.getEndTime())
.setMinLevel(info.getMinLevel())
.setMaxLevel(info.getMaxLevel())
.setMcoin(info.getMcoin())
.setDisableType(info.getDisableType())
.setSecondarySheetId(info.getSecondarySheetId());
.setMcoin(info.getMcoin());
// These fields are deprecated as of REL3.7
// .setDisableType(info.getDisableType())
// .setSecondarySheetId(info.getSecondarySheetId());
if (info.getCostItemList() != null) {
goods.addAllCostItemList(info.getCostItemList().stream().map(x -> ItemParamOuterClass.ItemParam.newBuilder().setItemId(x.getId()).setCount(x.getCount()).build()).collect(Collectors.toList()));
}