mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-19 02:15:45 +01:00
Fix whitespace [skip actions]
This commit is contained in:
@@ -2,11 +2,11 @@ package emu.grasscutter.server.game;
|
||||
|
||||
public abstract class BaseGameSystem {
|
||||
protected final GameServer server;
|
||||
|
||||
|
||||
public BaseGameSystem(GameServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
|
||||
public GameServer getServer() {
|
||||
return this.server;
|
||||
}
|
||||
|
||||
@@ -51,97 +51,97 @@ import static emu.grasscutter.utils.Language.translate;
|
||||
public final class GameServer extends KcpServer {
|
||||
// Game server base
|
||||
private final InetSocketAddress address;
|
||||
private final GameServerPacketHandler packetHandler;
|
||||
private final GameServerPacketHandler packetHandler;
|
||||
private final Map<Integer, Player> players;
|
||||
private final Set<World> worlds;
|
||||
|
||||
// Server systems
|
||||
private final InventorySystem inventorySystem;
|
||||
private final GachaSystem gachaSystem;
|
||||
private final ShopSystem shopSystem;
|
||||
private final MultiplayerSystem multiplayerSystem;
|
||||
private final DungeonSystem dungeonSystem;
|
||||
private final ExpeditionSystem expeditionSystem;
|
||||
private final DropSystem dropSystem;
|
||||
private final WorldDataSystem worldDataSystem;
|
||||
private final BattlePassSystem battlePassSystem;
|
||||
private final CombineManger combineSystem;
|
||||
private final TowerSystem towerSystem;
|
||||
private final AnnouncementSystem announcementSystem;
|
||||
private final QuestSystem questSystem;
|
||||
|
||||
// Extra
|
||||
private final ServerTaskScheduler scheduler;
|
||||
private final InventorySystem inventorySystem;
|
||||
private final GachaSystem gachaSystem;
|
||||
private final ShopSystem shopSystem;
|
||||
private final MultiplayerSystem multiplayerSystem;
|
||||
private final DungeonSystem dungeonSystem;
|
||||
private final ExpeditionSystem expeditionSystem;
|
||||
private final DropSystem dropSystem;
|
||||
private final WorldDataSystem worldDataSystem;
|
||||
private final BattlePassSystem battlePassSystem;
|
||||
private final CombineManger combineSystem;
|
||||
private final TowerSystem towerSystem;
|
||||
private final AnnouncementSystem announcementSystem;
|
||||
private final QuestSystem questSystem;
|
||||
|
||||
// Extra
|
||||
private final ServerTaskScheduler scheduler;
|
||||
private final CommandMap commandMap;
|
||||
private final TaskMap taskMap;
|
||||
|
||||
private ChatManagerHandler chatManager;
|
||||
|
||||
public GameServer() {
|
||||
this(getAdapterInetSocketAddress());
|
||||
}
|
||||
private ChatManagerHandler chatManager;
|
||||
|
||||
public GameServer(InetSocketAddress address) {
|
||||
ChannelConfig channelConfig = new ChannelConfig();
|
||||
channelConfig.nodelay(true, 40, 2, true);
|
||||
channelConfig.setMtu(1400);
|
||||
channelConfig.setSndwnd(256);
|
||||
channelConfig.setRcvwnd(256);
|
||||
channelConfig.setTimeoutMillis(30 * 1000);//30s
|
||||
channelConfig.setUseConvChannel(true);
|
||||
channelConfig.setAckNoDelay(false);
|
||||
public GameServer() {
|
||||
this(getAdapterInetSocketAddress());
|
||||
}
|
||||
|
||||
this.init(GameSessionManager.getListener(),channelConfig,address);
|
||||
public GameServer(InetSocketAddress address) {
|
||||
ChannelConfig channelConfig = new ChannelConfig();
|
||||
channelConfig.nodelay(true, 40, 2, true);
|
||||
channelConfig.setMtu(1400);
|
||||
channelConfig.setSndwnd(256);
|
||||
channelConfig.setRcvwnd(256);
|
||||
channelConfig.setTimeoutMillis(30 * 1000);//30s
|
||||
channelConfig.setUseConvChannel(true);
|
||||
channelConfig.setAckNoDelay(false);
|
||||
|
||||
DungeonChallenge.initialize();
|
||||
EnergyManager.initialize();
|
||||
StaminaManager.initialize();
|
||||
CookingManager.initialize();
|
||||
CombineManger.initialize();
|
||||
this.init(GameSessionManager.getListener(),channelConfig,address);
|
||||
|
||||
// Game Server base
|
||||
this.address = address;
|
||||
this.packetHandler = new GameServerPacketHandler(PacketHandler.class);
|
||||
this.players = new ConcurrentHashMap<>();
|
||||
this.worlds = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
// Extra
|
||||
this.scheduler = new ServerTaskScheduler();
|
||||
this.commandMap = new CommandMap(true);
|
||||
DungeonChallenge.initialize();
|
||||
EnergyManager.initialize();
|
||||
StaminaManager.initialize();
|
||||
CookingManager.initialize();
|
||||
CombineManger.initialize();
|
||||
|
||||
// Game Server base
|
||||
this.address = address;
|
||||
this.packetHandler = new GameServerPacketHandler(PacketHandler.class);
|
||||
this.players = new ConcurrentHashMap<>();
|
||||
this.worlds = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
// Extra
|
||||
this.scheduler = new ServerTaskScheduler();
|
||||
this.commandMap = new CommandMap(true);
|
||||
this.taskMap = new TaskMap(true);
|
||||
|
||||
// Create game systems
|
||||
this.inventorySystem = new InventorySystem(this);
|
||||
this.gachaSystem = new GachaSystem(this);
|
||||
this.shopSystem = new ShopSystem(this);
|
||||
this.multiplayerSystem = new MultiplayerSystem(this);
|
||||
this.dungeonSystem = new DungeonSystem(this);
|
||||
this.dropSystem = new DropSystem(this);
|
||||
this.expeditionSystem = new ExpeditionSystem(this);
|
||||
this.combineSystem = new CombineManger(this);
|
||||
this.towerSystem = new TowerSystem(this);
|
||||
this.worldDataSystem = new WorldDataSystem(this);
|
||||
this.battlePassSystem = new BattlePassSystem(this);
|
||||
this.announcementSystem = new AnnouncementSystem(this);
|
||||
this.questSystem = new QuestSystem(this);
|
||||
|
||||
// Chata manager
|
||||
this.chatManager = new ChatManager(this);
|
||||
|
||||
// Hook into shutdown event.
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::onServerShutdown));
|
||||
}
|
||||
|
||||
// Create game systems
|
||||
this.inventorySystem = new InventorySystem(this);
|
||||
this.gachaSystem = new GachaSystem(this);
|
||||
this.shopSystem = new ShopSystem(this);
|
||||
this.multiplayerSystem = new MultiplayerSystem(this);
|
||||
this.dungeonSystem = new DungeonSystem(this);
|
||||
this.dropSystem = new DropSystem(this);
|
||||
this.expeditionSystem = new ExpeditionSystem(this);
|
||||
this.combineSystem = new CombineManger(this);
|
||||
this.towerSystem = new TowerSystem(this);
|
||||
this.worldDataSystem = new WorldDataSystem(this);
|
||||
this.battlePassSystem = new BattlePassSystem(this);
|
||||
this.announcementSystem = new AnnouncementSystem(this);
|
||||
this.questSystem = new QuestSystem(this);
|
||||
|
||||
// Chata manager
|
||||
this.chatManager = new ChatManager(this);
|
||||
|
||||
// Hook into shutdown event.
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::onServerShutdown));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ChatManagerHandler getChatManager() {
|
||||
return chatManager;
|
||||
}
|
||||
|
||||
|
||||
@Deprecated
|
||||
public void setChatManager(ChatManagerHandler chatManager) {
|
||||
this.chatManager = chatManager;
|
||||
}
|
||||
|
||||
|
||||
public ChatManagerHandler getChatSystem() {
|
||||
return chatManager;
|
||||
}
|
||||
@@ -150,71 +150,71 @@ public final class GameServer extends KcpServer {
|
||||
this.chatManager = chatManager;
|
||||
}
|
||||
|
||||
private static InetSocketAddress getAdapterInetSocketAddress(){
|
||||
InetSocketAddress inetSocketAddress;
|
||||
if(GAME_INFO.bindAddress.equals("")){
|
||||
inetSocketAddress=new InetSocketAddress(GAME_INFO.bindPort);
|
||||
}else{
|
||||
inetSocketAddress=new InetSocketAddress(
|
||||
GAME_INFO.bindAddress,
|
||||
GAME_INFO.bindPort
|
||||
);
|
||||
}
|
||||
return inetSocketAddress;
|
||||
}
|
||||
private static InetSocketAddress getAdapterInetSocketAddress() {
|
||||
InetSocketAddress inetSocketAddress;
|
||||
if (GAME_INFO.bindAddress.equals("")) {
|
||||
inetSocketAddress=new InetSocketAddress(GAME_INFO.bindPort);
|
||||
}else {
|
||||
inetSocketAddress=new InetSocketAddress(
|
||||
GAME_INFO.bindAddress,
|
||||
GAME_INFO.bindPort
|
||||
);
|
||||
}
|
||||
return inetSocketAddress;
|
||||
}
|
||||
|
||||
public void registerPlayer(Player player) {
|
||||
getPlayers().put(player.getUid(), player);
|
||||
}
|
||||
public void registerPlayer(Player player) {
|
||||
getPlayers().put(player.getUid(), player);
|
||||
}
|
||||
|
||||
public Player getPlayerByUid(int id) {
|
||||
return this.getPlayerByUid(id, false);
|
||||
}
|
||||
public Player getPlayerByUid(int id) {
|
||||
return this.getPlayerByUid(id, false);
|
||||
}
|
||||
|
||||
public Player getPlayerByUid(int id, boolean allowOfflinePlayers) {
|
||||
// Console check
|
||||
if (id == GameConstants.SERVER_CONSOLE_UID) {
|
||||
return null;
|
||||
}
|
||||
public Player getPlayerByUid(int id, boolean allowOfflinePlayers) {
|
||||
// Console check
|
||||
if (id == GameConstants.SERVER_CONSOLE_UID) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get from online players
|
||||
Player player = this.getPlayers().get(id);
|
||||
// Get from online players
|
||||
Player player = this.getPlayers().get(id);
|
||||
|
||||
if (!allowOfflinePlayers) {
|
||||
return player;
|
||||
}
|
||||
if (!allowOfflinePlayers) {
|
||||
return player;
|
||||
}
|
||||
|
||||
// Check database if character isnt here
|
||||
if (player == null) {
|
||||
player = DatabaseHelper.getPlayerByUid(id);
|
||||
}
|
||||
// Check database if character isnt here
|
||||
if (player == null) {
|
||||
player = DatabaseHelper.getPlayerByUid(id);
|
||||
}
|
||||
|
||||
return player;
|
||||
}
|
||||
return player;
|
||||
}
|
||||
|
||||
public Player getPlayerByAccountId(String accountId) {
|
||||
Optional<Player> playerOpt = getPlayers().values().stream().filter(player -> player.getAccount().getId().equals(accountId)).findFirst();
|
||||
return playerOpt.orElse(null);
|
||||
}
|
||||
public Player getPlayerByAccountId(String accountId) {
|
||||
Optional<Player> playerOpt = getPlayers().values().stream().filter(player -> player.getAccount().getId().equals(accountId)).findFirst();
|
||||
return playerOpt.orElse(null);
|
||||
}
|
||||
|
||||
public SocialDetail.Builder getSocialDetailByUid(int id) {
|
||||
// Get from online players
|
||||
Player player = this.getPlayerByUid(id, true);
|
||||
public SocialDetail.Builder getSocialDetailByUid(int id) {
|
||||
// Get from online players
|
||||
Player player = this.getPlayerByUid(id, true);
|
||||
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return player.getSocialDetail();
|
||||
}
|
||||
return player.getSocialDetail();
|
||||
}
|
||||
|
||||
public Account getAccountByName(String username) {
|
||||
Optional<Player> playerOpt = getPlayers().values().stream().filter(player -> player.getAccount().getUsername().equals(username)).findFirst();
|
||||
if (playerOpt.isPresent()) {
|
||||
return playerOpt.get().getAccount();
|
||||
}
|
||||
return DatabaseHelper.getAccountByName(username);
|
||||
}
|
||||
public Account getAccountByName(String username) {
|
||||
Optional<Player> playerOpt = getPlayers().values().stream().filter(player -> player.getAccount().getUsername().equals(username)).findFirst();
|
||||
if (playerOpt.isPresent()) {
|
||||
return playerOpt.get().getAccount();
|
||||
}
|
||||
return DatabaseHelper.getAccountByName(username);
|
||||
}
|
||||
|
||||
public synchronized void onTick() {
|
||||
var tickStart = Instant.now();
|
||||
@@ -244,43 +244,43 @@ public final class GameServer extends KcpServer {
|
||||
event.call();
|
||||
}
|
||||
|
||||
public void registerWorld(World world) {
|
||||
this.getWorlds().add(world);
|
||||
}
|
||||
public void registerWorld(World world) {
|
||||
this.getWorlds().add(world);
|
||||
}
|
||||
|
||||
public void deregisterWorld(World world) {
|
||||
// TODO Auto-generated method stub
|
||||
public void deregisterWorld(World world) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
// Schedule game loop.
|
||||
Timer gameLoop = new Timer();
|
||||
gameLoop.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
onTick();
|
||||
} catch (Exception e) {
|
||||
Grasscutter.getLogger().error(translate("messages.game.game_update_error"), e);
|
||||
}
|
||||
}
|
||||
}, new Date(), 1000L);
|
||||
Grasscutter.getLogger().info(translate("messages.status.free_software"));
|
||||
Grasscutter.getLogger().info(translate("messages.game.port_bind", Integer.toString(address.getPort())));
|
||||
ServerStartEvent event = new ServerStartEvent(ServerEvent.Type.GAME, OffsetDateTime.now());
|
||||
event.call();
|
||||
}
|
||||
public void start() {
|
||||
// Schedule game loop.
|
||||
Timer gameLoop = new Timer();
|
||||
gameLoop.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
onTick();
|
||||
} catch (Exception e) {
|
||||
Grasscutter.getLogger().error(translate("messages.game.game_update_error"), e);
|
||||
}
|
||||
}
|
||||
}, new Date(), 1000L);
|
||||
Grasscutter.getLogger().info(translate("messages.status.free_software"));
|
||||
Grasscutter.getLogger().info(translate("messages.game.port_bind", Integer.toString(address.getPort())));
|
||||
ServerStartEvent event = new ServerStartEvent(ServerEvent.Type.GAME, OffsetDateTime.now());
|
||||
event.call();
|
||||
}
|
||||
|
||||
public void onServerShutdown() {
|
||||
ServerStopEvent event = new ServerStopEvent(ServerEvent.Type.GAME, OffsetDateTime.now()); event.call();
|
||||
public void onServerShutdown() {
|
||||
ServerStopEvent event = new ServerStopEvent(ServerEvent.Type.GAME, OffsetDateTime.now()); event.call();
|
||||
|
||||
// Kick and save all players
|
||||
List<Player> list = new ArrayList<>(this.getPlayers().size());
|
||||
list.addAll(this.getPlayers().values());
|
||||
// Kick and save all players
|
||||
List<Player> list = new ArrayList<>(this.getPlayers().size());
|
||||
list.addAll(this.getPlayers().values());
|
||||
|
||||
for (Player player : list) {
|
||||
player.getSession().close();
|
||||
}
|
||||
}
|
||||
for (Player player : list) {
|
||||
player.getSession().close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,84 +18,84 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class GameServerPacketHandler {
|
||||
private final Int2ObjectMap<PacketHandler> handlers;
|
||||
private final Int2ObjectMap<PacketHandler> handlers;
|
||||
|
||||
public GameServerPacketHandler(Class<? extends PacketHandler> handlerClass) {
|
||||
this.handlers = new Int2ObjectOpenHashMap<>();
|
||||
public GameServerPacketHandler(Class<? extends PacketHandler> handlerClass) {
|
||||
this.handlers = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
this.registerHandlers(handlerClass);
|
||||
}
|
||||
this.registerHandlers(handlerClass);
|
||||
}
|
||||
|
||||
public void registerPacketHandler(Class<? extends PacketHandler> handlerClass) {
|
||||
try {
|
||||
Opcodes opcode = handlerClass.getAnnotation(Opcodes.class);
|
||||
public void registerPacketHandler(Class<? extends PacketHandler> handlerClass) {
|
||||
try {
|
||||
Opcodes opcode = handlerClass.getAnnotation(Opcodes.class);
|
||||
|
||||
if (opcode == null || opcode.disabled() || opcode.value() <= 0) {
|
||||
return;
|
||||
}
|
||||
if (opcode == null || opcode.disabled() || opcode.value() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
PacketHandler packetHandler = handlerClass.getDeclaredConstructor().newInstance();
|
||||
PacketHandler packetHandler = handlerClass.getDeclaredConstructor().newInstance();
|
||||
|
||||
this.handlers.put(opcode.value(), packetHandler);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
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);
|
||||
public void registerHandlers(Class<? extends PacketHandler> handlerClass) {
|
||||
Reflections reflections = new Reflections("emu.grasscutter.server.packet");
|
||||
Set<?> handlerClasses = reflections.getSubTypesOf(handlerClass);
|
||||
|
||||
for (Object obj : handlerClasses) {
|
||||
this.registerPacketHandler((Class<? extends PacketHandler>) obj);
|
||||
}
|
||||
for (Object obj : handlerClasses) {
|
||||
this.registerPacketHandler((Class<? extends PacketHandler>) obj);
|
||||
}
|
||||
|
||||
// Debug
|
||||
Grasscutter.getLogger().debug("Registered " + this.handlers.size() + " " + handlerClass.getSimpleName() + "s");
|
||||
}
|
||||
// Debug
|
||||
Grasscutter.getLogger().debug("Registered " + this.handlers.size() + " " + handlerClass.getSimpleName() + "s");
|
||||
}
|
||||
|
||||
public void handle(GameSession session, int opcode, byte[] header, byte[] payload) {
|
||||
PacketHandler handler = this.handlers.get(opcode);
|
||||
public void handle(GameSession session, int opcode, byte[] header, byte[] payload) {
|
||||
PacketHandler handler = this.handlers.get(opcode);
|
||||
|
||||
if (handler != null) {
|
||||
try {
|
||||
// Make sure session is ready for packets
|
||||
SessionState state = session.getState();
|
||||
if (handler != null) {
|
||||
try {
|
||||
// Make sure session is ready for packets
|
||||
SessionState state = session.getState();
|
||||
|
||||
if (opcode == PacketOpcodes.PingReq) {
|
||||
// Always continue if packet is ping request
|
||||
} else if (opcode == PacketOpcodes.GetPlayerTokenReq) {
|
||||
if (state != SessionState.WAITING_FOR_TOKEN) {
|
||||
return;
|
||||
}
|
||||
} else if (opcode == PacketOpcodes.PlayerLoginReq) {
|
||||
if (state != SessionState.WAITING_FOR_LOGIN) {
|
||||
return;
|
||||
}
|
||||
} else if (opcode == PacketOpcodes.SetPlayerBornDataReq) {
|
||||
if (state != SessionState.PICKING_CHARACTER) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (state != SessionState.ACTIVE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (opcode == PacketOpcodes.PingReq) {
|
||||
// Always continue if packet is ping request
|
||||
} else if (opcode == PacketOpcodes.GetPlayerTokenReq) {
|
||||
if (state != SessionState.WAITING_FOR_TOKEN) {
|
||||
return;
|
||||
}
|
||||
} else if (opcode == PacketOpcodes.PlayerLoginReq) {
|
||||
if (state != SessionState.WAITING_FOR_LOGIN) {
|
||||
return;
|
||||
}
|
||||
} else if (opcode == PacketOpcodes.SetPlayerBornDataReq) {
|
||||
if (state != SessionState.PICKING_CHARACTER) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (state != SessionState.ACTIVE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke event.
|
||||
ReceivePacketEvent event = new ReceivePacketEvent(session, opcode, payload); event.call();
|
||||
if(!event.isCanceled()) // If event is not canceled, continue.
|
||||
handler.handle(session, header, event.getPacketData());
|
||||
} catch (Exception ex) {
|
||||
// TODO Remove this when no more needed
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return; // Packet successfully handled
|
||||
}
|
||||
// Invoke event.
|
||||
ReceivePacketEvent event = new ReceivePacketEvent(session, opcode, payload); event.call();
|
||||
if (!event.isCanceled()) // If event is not canceled, continue.
|
||||
handler.handle(session, header, event.getPacketData());
|
||||
} catch (Exception ex) {
|
||||
// TODO Remove this when no more needed
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return; // Packet successfully handled
|
||||
}
|
||||
|
||||
// Log unhandled packets
|
||||
if (GAME_INFO.logPackets == ServerDebugMode.MISSING) {
|
||||
Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtils.getOpcodeName(opcode));
|
||||
}
|
||||
}
|
||||
// Log unhandled packets
|
||||
if (GAME_INFO.logPackets == ServerDebugMode.MISSING) {
|
||||
Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtils.getOpcodeName(opcode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,108 +21,108 @@ import static emu.grasscutter.config.Configuration.*;
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
public class GameSession implements GameSessionManager.KcpChannel {
|
||||
private final GameServer server;
|
||||
private GameSessionManager.KcpTunnel tunnel;
|
||||
private final GameServer server;
|
||||
private GameSessionManager.KcpTunnel tunnel;
|
||||
|
||||
private Account account;
|
||||
private Player player;
|
||||
private Account account;
|
||||
private Player player;
|
||||
|
||||
private boolean useSecretKey;
|
||||
private SessionState state;
|
||||
private boolean useSecretKey;
|
||||
private SessionState state;
|
||||
|
||||
private int clientTime;
|
||||
private long lastPingTime;
|
||||
private int lastClientSeq = 10;
|
||||
private int clientTime;
|
||||
private long lastPingTime;
|
||||
private int lastClientSeq = 10;
|
||||
|
||||
public GameSession(GameServer server) {
|
||||
this.server = server;
|
||||
this.state = SessionState.WAITING_FOR_TOKEN;
|
||||
this.lastPingTime = System.currentTimeMillis();
|
||||
}
|
||||
public GameSession(GameServer server) {
|
||||
this.server = server;
|
||||
this.state = SessionState.WAITING_FOR_TOKEN;
|
||||
this.lastPingTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public GameServer getServer() {
|
||||
return server;
|
||||
}
|
||||
public GameServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public InetSocketAddress getAddress() {
|
||||
try{
|
||||
return tunnel.getAddress();
|
||||
}catch (Throwable ignore){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public InetSocketAddress getAddress() {
|
||||
try {
|
||||
return tunnel.getAddress();
|
||||
}catch (Throwable ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean useSecretKey() {
|
||||
return useSecretKey;
|
||||
}
|
||||
public boolean useSecretKey() {
|
||||
return useSecretKey;
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
public void setAccount(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public String getAccountId() {
|
||||
return this.getAccount().getId();
|
||||
}
|
||||
public String getAccountId() {
|
||||
return this.getAccount().getId();
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public synchronized void setPlayer(Player player) {
|
||||
this.player = player;
|
||||
this.player.setSession(this);
|
||||
this.player.setAccount(this.getAccount());
|
||||
}
|
||||
public synchronized void setPlayer(Player player) {
|
||||
this.player = player;
|
||||
this.player.setSession(this);
|
||||
this.player.setAccount(this.getAccount());
|
||||
}
|
||||
|
||||
public SessionState getState() {
|
||||
return state;
|
||||
}
|
||||
public SessionState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(SessionState state) {
|
||||
this.state = state;
|
||||
}
|
||||
public void setState(SessionState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public boolean isLoggedIn() {
|
||||
return this.getPlayer() != null;
|
||||
}
|
||||
public boolean isLoggedIn() {
|
||||
return this.getPlayer() != null;
|
||||
}
|
||||
|
||||
public void setUseSecretKey(boolean useSecretKey) {
|
||||
this.useSecretKey = useSecretKey;
|
||||
}
|
||||
public void setUseSecretKey(boolean useSecretKey) {
|
||||
this.useSecretKey = useSecretKey;
|
||||
}
|
||||
|
||||
public int getClientTime() {
|
||||
return this.clientTime;
|
||||
}
|
||||
public int getClientTime() {
|
||||
return this.clientTime;
|
||||
}
|
||||
|
||||
public long getLastPingTime() {
|
||||
return lastPingTime;
|
||||
}
|
||||
public long getLastPingTime() {
|
||||
return lastPingTime;
|
||||
}
|
||||
|
||||
public void updateLastPingTime(int clientTime) {
|
||||
this.clientTime = clientTime;
|
||||
this.lastPingTime = System.currentTimeMillis();
|
||||
}
|
||||
public void updateLastPingTime(int clientTime) {
|
||||
this.clientTime = clientTime;
|
||||
this.lastPingTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public int getNextClientSequence() {
|
||||
return ++lastClientSeq;
|
||||
}
|
||||
public int getNextClientSequence() {
|
||||
return ++lastClientSeq;
|
||||
}
|
||||
|
||||
public void replayPacket(int opcode, String name) {
|
||||
String filePath = PACKET(name);
|
||||
File p = new File(filePath);
|
||||
String filePath = PACKET(name);
|
||||
File p = new File(filePath);
|
||||
|
||||
if (!p.exists()) return;
|
||||
if (!p.exists()) return;
|
||||
|
||||
byte[] packet = FileUtils.read(p);
|
||||
byte[] packet = FileUtils.read(p);
|
||||
|
||||
BasePacket basePacket = new BasePacket(opcode);
|
||||
basePacket.setData(packet);
|
||||
BasePacket basePacket = new BasePacket(opcode);
|
||||
basePacket.setData(packet);
|
||||
|
||||
send(basePacket);
|
||||
send(basePacket);
|
||||
}
|
||||
|
||||
public void logPacket( String sendOrRecv, int opcode, byte[] payload) {
|
||||
@@ -130,162 +130,162 @@ public class GameSession implements GameSessionManager.KcpChannel {
|
||||
System.out.println(Utils.bytesToHex(payload));
|
||||
}
|
||||
public void send(BasePacket packet) {
|
||||
// Test
|
||||
if (packet.getOpcode() <= 0) {
|
||||
Grasscutter.getLogger().warn("Tried to send packet with missing cmd id!");
|
||||
return;
|
||||
}
|
||||
// Test
|
||||
if (packet.getOpcode() <= 0) {
|
||||
Grasscutter.getLogger().warn("Tried to send packet with missing cmd id!");
|
||||
return;
|
||||
}
|
||||
|
||||
// DO NOT REMOVE (unless we find a way to validate code before sending to client which I don't think we can)
|
||||
// Stop WindSeedClientNotify from being sent for security purposes.
|
||||
if(PacketOpcodesUtils.BANNED_PACKETS.contains(packet.getOpcode())) {
|
||||
return;
|
||||
}
|
||||
// DO NOT REMOVE (unless we find a way to validate code before sending to client which I don't think we can)
|
||||
// Stop WindSeedClientNotify from being sent for security purposes.
|
||||
if (PacketOpcodesUtils.BANNED_PACKETS.contains(packet.getOpcode())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Header
|
||||
if (packet.shouldBuildHeader()) {
|
||||
packet.buildHeader(this.getNextClientSequence());
|
||||
}
|
||||
// Header
|
||||
if (packet.shouldBuildHeader()) {
|
||||
packet.buildHeader(this.getNextClientSequence());
|
||||
}
|
||||
|
||||
// Log
|
||||
switch (GAME_INFO.logPackets) {
|
||||
case ALL -> {
|
||||
if (!PacketOpcodesUtils.LOOP_PACKETS.contains(packet.getOpcode())) {
|
||||
// Log
|
||||
switch (GAME_INFO.logPackets) {
|
||||
case ALL -> {
|
||||
if (!PacketOpcodesUtils.LOOP_PACKETS.contains(packet.getOpcode())) {
|
||||
logPacket("SEND", packet.getOpcode(), packet.getData());
|
||||
}
|
||||
}
|
||||
case WHITELIST-> {
|
||||
if (SERVER.debugWhitelist.contains(packet.getOpcode())) {
|
||||
logPacket("SEND", packet.getOpcode(), packet.getData());
|
||||
}
|
||||
}
|
||||
case BLACKLIST-> {
|
||||
}
|
||||
case WHITELIST-> {
|
||||
if (SERVER.debugWhitelist.contains(packet.getOpcode())) {
|
||||
logPacket("SEND", packet.getOpcode(), packet.getData());
|
||||
}
|
||||
}
|
||||
case BLACKLIST-> {
|
||||
if (!SERVER.debugBlacklist.contains(packet.getOpcode())) {
|
||||
logPacket("SEND", packet.getOpcode(), packet.getData());
|
||||
}
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
|
||||
// Invoke event.
|
||||
SendPacketEvent event = new SendPacketEvent(this, packet); event.call();
|
||||
if(!event.isCanceled()) { // If event is not cancelled, continue.
|
||||
tunnel.writeData(event.getPacket().build());
|
||||
}
|
||||
// Invoke event.
|
||||
SendPacketEvent event = new SendPacketEvent(this, packet); event.call();
|
||||
if (!event.isCanceled()) { // If event is not cancelled, continue.
|
||||
tunnel.writeData(event.getPacket().build());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(GameSessionManager.KcpTunnel tunnel) {
|
||||
this.tunnel = tunnel;
|
||||
Grasscutter.getLogger().info(translate("messages.game.connect", this.getAddress().toString()));
|
||||
}
|
||||
@Override
|
||||
public void onConnected(GameSessionManager.KcpTunnel tunnel) {
|
||||
this.tunnel = tunnel;
|
||||
Grasscutter.getLogger().info(translate("messages.game.connect", this.getAddress().toString()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleReceive(byte[] bytes) {
|
||||
// Decrypt and turn back into a packet
|
||||
Crypto.xor(bytes, useSecretKey() ? Crypto.ENCRYPT_KEY : Crypto.DISPATCH_KEY);
|
||||
ByteBuf packet = Unpooled.wrappedBuffer(bytes);
|
||||
@Override
|
||||
public void handleReceive(byte[] bytes) {
|
||||
// Decrypt and turn back into a packet
|
||||
Crypto.xor(bytes, useSecretKey() ? Crypto.ENCRYPT_KEY : Crypto.DISPATCH_KEY);
|
||||
ByteBuf packet = Unpooled.wrappedBuffer(bytes);
|
||||
|
||||
// Log
|
||||
//logPacket(packet);
|
||||
// Handle
|
||||
try {
|
||||
boolean allDebug = GAME_INFO.logPackets == ServerDebugMode.ALL;
|
||||
while (packet.readableBytes() > 0) {
|
||||
// Length
|
||||
if (packet.readableBytes() < 12) {
|
||||
return;
|
||||
}
|
||||
// Packet sanity check
|
||||
int const1 = packet.readShort();
|
||||
if (const1 != 17767) {
|
||||
if(allDebug){
|
||||
Grasscutter.getLogger().error("Bad Data Package Received: got {} ,expect 17767",const1);
|
||||
}
|
||||
return; // Bad packet
|
||||
}
|
||||
// Data
|
||||
int opcode = packet.readShort();
|
||||
int headerLength = packet.readShort();
|
||||
int payloadLength = packet.readInt();
|
||||
byte[] header = new byte[headerLength];
|
||||
byte[] payload = new byte[payloadLength];
|
||||
// Log
|
||||
//logPacket(packet);
|
||||
// Handle
|
||||
try {
|
||||
boolean allDebug = GAME_INFO.logPackets == ServerDebugMode.ALL;
|
||||
while (packet.readableBytes() > 0) {
|
||||
// Length
|
||||
if (packet.readableBytes() < 12) {
|
||||
return;
|
||||
}
|
||||
// Packet sanity check
|
||||
int const1 = packet.readShort();
|
||||
if (const1 != 17767) {
|
||||
if (allDebug) {
|
||||
Grasscutter.getLogger().error("Bad Data Package Received: got {} ,expect 17767",const1);
|
||||
}
|
||||
return; // Bad packet
|
||||
}
|
||||
// Data
|
||||
int opcode = packet.readShort();
|
||||
int headerLength = packet.readShort();
|
||||
int payloadLength = packet.readInt();
|
||||
byte[] header = new byte[headerLength];
|
||||
byte[] payload = new byte[payloadLength];
|
||||
|
||||
packet.readBytes(header);
|
||||
packet.readBytes(payload);
|
||||
// Sanity check #2
|
||||
int const2 = packet.readShort();
|
||||
if (const2 != -30293) {
|
||||
if(allDebug){
|
||||
Grasscutter.getLogger().error("Bad Data Package Received: got {} ,expect -30293",const2);
|
||||
}
|
||||
return; // Bad packet
|
||||
}
|
||||
|
||||
// Log packet
|
||||
switch (GAME_INFO.logPackets) {
|
||||
case ALL -> {
|
||||
if (!PacketOpcodesUtils.LOOP_PACKETS.contains(opcode)) {
|
||||
packet.readBytes(header);
|
||||
packet.readBytes(payload);
|
||||
// Sanity check #2
|
||||
int const2 = packet.readShort();
|
||||
if (const2 != -30293) {
|
||||
if (allDebug) {
|
||||
Grasscutter.getLogger().error("Bad Data Package Received: got {} ,expect -30293",const2);
|
||||
}
|
||||
return; // Bad packet
|
||||
}
|
||||
|
||||
// Log packet
|
||||
switch (GAME_INFO.logPackets) {
|
||||
case ALL -> {
|
||||
if (!PacketOpcodesUtils.LOOP_PACKETS.contains(opcode)) {
|
||||
logPacket("RECV",opcode, payload);
|
||||
}
|
||||
}
|
||||
case WHITELIST-> {
|
||||
if (SERVER.debugWhitelist.contains(opcode)) {
|
||||
logPacket("RECV",opcode, payload);
|
||||
}
|
||||
}
|
||||
case BLACKLIST-> {
|
||||
if (!(SERVER.debugBlacklist.contains(opcode))) {
|
||||
logPacket("RECV",opcode, payload);
|
||||
}
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
case WHITELIST-> {
|
||||
if (SERVER.debugWhitelist.contains(opcode)) {
|
||||
logPacket("RECV",opcode, payload);
|
||||
}
|
||||
}
|
||||
case BLACKLIST-> {
|
||||
if (!(SERVER.debugBlacklist.contains(opcode))) {
|
||||
logPacket("RECV",opcode, payload);
|
||||
}
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
|
||||
// Handle
|
||||
getServer().getPacketHandler().handle(this, opcode, header, payload);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
//byteBuf.release(); //Needn't
|
||||
packet.release();
|
||||
}
|
||||
}
|
||||
// Handle
|
||||
getServer().getPacketHandler().handle(this, opcode, header, payload);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
//byteBuf.release(); //Needn't
|
||||
packet.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleClose() {
|
||||
setState(SessionState.INACTIVE);
|
||||
//send disconnection pack in case of reconnection
|
||||
Grasscutter.getLogger().info(translate("messages.game.disconnect", this.getAddress().toString()));
|
||||
// Save after disconnecting
|
||||
if (this.isLoggedIn()) {
|
||||
Player player = getPlayer();
|
||||
// Call logout event.
|
||||
player.onLogout();
|
||||
}
|
||||
try {
|
||||
send(new BasePacket(PacketOpcodes.ServerDisconnectClientNotify));
|
||||
}catch (Throwable ignore){
|
||||
Grasscutter.getLogger().warn("closing {} error",getAddress().getAddress().getHostAddress());
|
||||
}
|
||||
tunnel = null;
|
||||
}
|
||||
@Override
|
||||
public void handleClose() {
|
||||
setState(SessionState.INACTIVE);
|
||||
//send disconnection pack in case of reconnection
|
||||
Grasscutter.getLogger().info(translate("messages.game.disconnect", this.getAddress().toString()));
|
||||
// Save after disconnecting
|
||||
if (this.isLoggedIn()) {
|
||||
Player player = getPlayer();
|
||||
// Call logout event.
|
||||
player.onLogout();
|
||||
}
|
||||
try {
|
||||
send(new BasePacket(PacketOpcodes.ServerDisconnectClientNotify));
|
||||
}catch (Throwable ignore) {
|
||||
Grasscutter.getLogger().warn("closing {} error",getAddress().getAddress().getHostAddress());
|
||||
}
|
||||
tunnel = null;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
tunnel.close();
|
||||
}
|
||||
public void close() {
|
||||
tunnel.close();
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return getState() == SessionState.ACTIVE;
|
||||
}
|
||||
public boolean isActive() {
|
||||
return getState() == SessionState.ACTIVE;
|
||||
}
|
||||
|
||||
public enum SessionState {
|
||||
INACTIVE,
|
||||
WAITING_FOR_TOKEN,
|
||||
WAITING_FOR_LOGIN,
|
||||
PICKING_CHARACTER,
|
||||
ACTIVE
|
||||
}
|
||||
public enum SessionState {
|
||||
INACTIVE,
|
||||
WAITING_FOR_TOKEN,
|
||||
WAITING_FOR_LOGIN,
|
||||
PICKING_CHARACTER,
|
||||
ACTIVE
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user