Commit a5720973 authored by Magix's avatar Magix Committed by GitHub
Browse files

Merge branch 'development' into main

parents 708ee021 16318b37
package emu.grasscutter.game.gacha; package emu.grasscutter.game.gacha;
import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.nio.file.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
...@@ -8,6 +10,7 @@ import java.util.concurrent.ThreadLocalRandom; ...@@ -8,6 +10,7 @@ import java.util.concurrent.ThreadLocalRandom;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.sun.nio.file.SensitivityWatchEventModifier;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData; import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.def.ItemData; import emu.grasscutter.data.def.ItemData;
...@@ -21,16 +24,19 @@ import emu.grasscutter.net.proto.GachaTransferItemOuterClass.GachaTransferItem; ...@@ -21,16 +24,19 @@ import emu.grasscutter.net.proto.GachaTransferItemOuterClass.GachaTransferItem;
import emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp; import emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp;
import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.game.GameServerTickEvent;
import emu.grasscutter.server.packet.send.PacketDoGachaRsp; import emu.grasscutter.server.packet.send.PacketDoGachaRsp;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntList;
import org.greenrobot.eventbus.Subscribe;
public class GachaManager { public class GachaManager {
private final GameServer server; private final GameServer server;
private final Int2ObjectMap<GachaBanner> gachaBanners; private final Int2ObjectMap<GachaBanner> gachaBanners;
private GetGachaInfoRsp cachedProto; private GetGachaInfoRsp cachedProto;
WatchService watchService;
private int[] yellowAvatars = new int[] {1003, 1016, 1042, 1035, 1041}; private int[] yellowAvatars = new int[] {1003, 1016, 1042, 1035, 1041};
private int[] yellowWeapons = new int[] {11501, 11502, 12501, 12502, 13502, 13505, 14501, 14502, 15501, 15502}; private int[] yellowWeapons = new int[] {11501, 11502, 12501, 12502, 13502, 13505, 14501, 14502, 15501, 15502};
...@@ -45,6 +51,7 @@ public class GachaManager { ...@@ -45,6 +51,7 @@ public class GachaManager {
this.server = server; this.server = server;
this.gachaBanners = new Int2ObjectOpenHashMap<>(); this.gachaBanners = new Int2ObjectOpenHashMap<>();
this.load(); this.load();
this.startWatcher(server);
} }
public GameServer getServer() { public GameServer getServer() {
...@@ -65,10 +72,17 @@ public class GachaManager { ...@@ -65,10 +72,17 @@ public class GachaManager {
public synchronized void load() { public synchronized void load() {
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Banners.json")) { try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Banners.json")) {
getGachaBanners().clear();
List<GachaBanner> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, GachaBanner.class).getType()); List<GachaBanner> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, GachaBanner.class).getType());
if(banners.size() > 0) {
for (GachaBanner banner : banners) { for (GachaBanner banner : banners) {
getGachaBanners().put(banner.getGachaType(), banner); getGachaBanners().put(banner.getGachaType(), banner);
} }
Grasscutter.getLogger().info("Banners successfully loaded.");
this.cachedProto = createProto();
} else {
Grasscutter.getLogger().error("Unable to load banners. Banners size is 0.");
}
} catch (Exception e) { } catch (Exception e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
...@@ -204,7 +218,6 @@ public class GachaManager { ...@@ -204,7 +218,6 @@ public class GachaManager {
addStarglitter = 2; addStarglitter = 2;
// Add 1 const // Add 1 const
gachaItem.addTransferItems(GachaTransferItem.newBuilder().setItem(ItemParam.newBuilder().setItemId(constItemId).setCount(1)).setIsTransferItemNew(constItem == null)); gachaItem.addTransferItems(GachaTransferItem.newBuilder().setItem(ItemParam.newBuilder().setItemId(constItemId).setCount(1)).setIsTransferItemNew(constItem == null));
gachaItem.addTokenItemList(ItemParam.newBuilder().setItemId(constItemId).setCount(1));
player.getInventory().addItem(constItemId, 1); player.getInventory().addItem(constItemId, 1);
} else { } else {
// Is max const // Is max const
...@@ -267,6 +280,48 @@ public class GachaManager { ...@@ -267,6 +280,48 @@ public class GachaManager {
player.sendPacket(new PacketDoGachaRsp(banner, list)); player.sendPacket(new PacketDoGachaRsp(banner, list));
} }
private synchronized void startWatcher(GameServer server) {
if(this.watchService == null) {
try {
this.watchService = FileSystems.getDefault().newWatchService();
Path path = new File(Grasscutter.getConfig().DATA_FOLDER).toPath();
path.register(watchService, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_MODIFY}, SensitivityWatchEventModifier.HIGH);
server.OnGameServerTick.register(this);
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload");
e.printStackTrace();
}
} else {
Grasscutter.getLogger().error("Cannot reinitialise watcher ");
}
}
@Subscribe
public synchronized void watchBannerJson(GameServerTickEvent tickEvent) {
if(Grasscutter.getConfig().getGameServerOptions().WatchGacha) {
try {
WatchKey watchKey = watchService.take();
for (WatchEvent<?> event : watchKey.pollEvents()) {
final Path changed = (Path) event.context();
if (changed.endsWith("Banners.json")) {
Grasscutter.getLogger().info("Change detected with banners.json. Reloading gacha config");
this.load();
}
}
boolean valid = watchKey.reset();
if (!valid) {
Grasscutter.getLogger().error("Unable to reset Gacha Manager Watch Key. Auto-reload of banners.json will no longer work.");
return;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private synchronized GetGachaInfoRsp createProto() { private synchronized GetGachaInfoRsp createProto() {
GetGachaInfoRsp.Builder proto = GetGachaInfoRsp.newBuilder().setGachaRandom(12345); GetGachaInfoRsp.Builder proto = GetGachaInfoRsp.newBuilder().setGachaRandom(12345);
......
...@@ -37,10 +37,10 @@ public class Inventory implements Iterable<GenshinItem> { ...@@ -37,10 +37,10 @@ public class Inventory implements Iterable<GenshinItem> {
this.store = new Long2ObjectOpenHashMap<>(); this.store = new Long2ObjectOpenHashMap<>();
this.inventoryTypes = new Int2ObjectOpenHashMap<>(); this.inventoryTypes = new Int2ObjectOpenHashMap<>();
this.createInventoryTab(ItemType.ITEM_WEAPON, new EquipInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitWeapon)); this.createInventoryTab(ItemType.ITEM_WEAPON, new EquipInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitWeapon));
this.createInventoryTab(ItemType.ITEM_RELIQUARY, new EquipInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitRelic)); this.createInventoryTab(ItemType.ITEM_RELIQUARY, new EquipInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitRelic));
this.createInventoryTab(ItemType.ITEM_MATERIAL, new MaterialInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitMaterial)); this.createInventoryTab(ItemType.ITEM_MATERIAL, new MaterialInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitMaterial));
this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitFurniture)); this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitFurniture));
} }
public GenshinPlayer getPlayer() { public GenshinPlayer getPlayer() {
......
package emu.grasscutter.game.managers; package emu.grasscutter.game.managers;
import emu.grasscutter.commands.CommandMap; import emu.grasscutter.command.CommandMap;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
......
...@@ -589,7 +589,6 @@ public class InventoryManager { ...@@ -589,7 +589,6 @@ public class InventoryManager {
// Update proud skills // Update proud skills
AvatarSkillDepotData skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId()); AvatarSkillDepotData skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId());
boolean hasAddedProudSkill = false;
if (skillDepot != null && skillDepot.getInherentProudSkillOpens() != null) { if (skillDepot != null && skillDepot.getInherentProudSkillOpens() != null) {
for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) { for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) {
...@@ -599,7 +598,6 @@ public class InventoryManager { ...@@ -599,7 +598,6 @@ public class InventoryManager {
if (openData.getNeedAvatarPromoteLevel() == avatar.getPromoteLevel()) { if (openData.getNeedAvatarPromoteLevel() == avatar.getPromoteLevel()) {
int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1; int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1;
if (GenshinData.getProudSkillDataMap().containsKey(proudSkillId)) { if (GenshinData.getProudSkillDataMap().containsKey(proudSkillId)) {
hasAddedProudSkill = true;
avatar.getProudSkillList().add(proudSkillId); avatar.getProudSkillList().add(proudSkillId);
player.sendPacket(new PacketProudSkillChangeNotify(avatar)); player.sendPacket(new PacketProudSkillChangeNotify(avatar));
} }
...@@ -607,20 +605,13 @@ public class InventoryManager { ...@@ -607,20 +605,13 @@ public class InventoryManager {
} }
} }
// Racalc stats and save avatar
avatar.recalcStats();
avatar.save();
// Resend ability embryos if proud skill has been added
if (hasAddedProudSkill && avatar.getAsEntity() != null) {
player.sendPacket(new PacketAbilityChangeNotify(avatar.getAsEntity()));
}
// TODO Send entity prop update packet to world
// Packets // Packets
player.sendPacket(new PacketAvatarPropNotify(avatar)); player.sendPacket(new PacketAvatarPropNotify(avatar));
player.sendPacket(new PacketAvatarPromoteRsp(avatar)); player.sendPacket(new PacketAvatarPromoteRsp(avatar));
// TODO Send entity prop update packet to world
avatar.recalcStats(true);
avatar.save();
} }
public void upgradeAvatar(GenshinPlayer player, long guid, int itemId, int count) { public void upgradeAvatar(GenshinPlayer player, long guid, int itemId, int count) {
...@@ -827,25 +818,20 @@ public class InventoryManager { ...@@ -827,25 +818,20 @@ public class InventoryManager {
// Apply + recalc // Apply + recalc
avatar.getTalentIdList().add(talentData.getId()); avatar.getTalentIdList().add(talentData.getId());
avatar.setCoreProudSkillLevel(currentTalentLevel + 1); avatar.setCoreProudSkillLevel(currentTalentLevel + 1);
avatar.recalcStats();
// Packet // Packet
player.sendPacket(new PacketAvatarUnlockTalentNotify(avatar, nextTalentId)); player.sendPacket(new PacketAvatarUnlockTalentNotify(avatar, nextTalentId));
player.sendPacket(new PacketUnlockAvatarTalentRsp(avatar, nextTalentId)); player.sendPacket(new PacketUnlockAvatarTalentRsp(avatar, nextTalentId));
// Proud skill bonus map // Proud skill bonus map (Extra skills)
OpenConfigEntry entry = GenshinData.getOpenConfigEntries().get(talentData.getOpenConfig()); OpenConfigEntry entry = GenshinData.getOpenConfigEntries().get(talentData.getOpenConfig());
if (entry != null && entry.getExtraTalentIndex() > 0) { if (entry != null && entry.getExtraTalentIndex() > 0) {
avatar.recalcProudSkillBonusMap(); avatar.recalcProudSkillBonusMap();
player.sendPacket(new PacketProudSkillExtraLevelNotify(avatar, entry.getExtraTalentIndex())); player.sendPacket(new PacketProudSkillExtraLevelNotify(avatar, entry.getExtraTalentIndex()));
} }
// Resend ability embryos // Recalc + save avatar
if (avatar.getAsEntity() != null) { avatar.recalcStats(true);
player.sendPacket(new PacketAbilityChangeNotify(avatar.getAsEntity()));
}
// Save avatar
avatar.save(); avatar.save();
} }
......
...@@ -7,7 +7,7 @@ public class ComboTokenReqJson { ...@@ -7,7 +7,7 @@ public class ComboTokenReqJson {
public String device; public String device;
public String sign; public String sign;
public class LoginTokenData { public static class LoginTokenData {
public String uid; public String uid;
public String token; public String token;
public boolean guest; public boolean guest;
......
...@@ -5,7 +5,7 @@ public class ComboTokenResJson { ...@@ -5,7 +5,7 @@ public class ComboTokenResJson {
public int retcode; public int retcode;
public LoginData data = new LoginData(); public LoginData data = new LoginData();
public class LoginData { public static class LoginData {
public int account_type = 1; public int account_type = 1;
public boolean heartbeat; public boolean heartbeat;
public String combo_id; public String combo_id;
......
...@@ -5,7 +5,7 @@ public class LoginResultJson { ...@@ -5,7 +5,7 @@ public class LoginResultJson {
public int retcode; public int retcode;
public VerifyData data = new VerifyData(); public VerifyData data = new VerifyData();
public class VerifyData { public static class VerifyData {
public VerifyAccountData account = new VerifyAccountData(); public VerifyAccountData account = new VerifyAccountData();
public boolean device_grant_required = false; public boolean device_grant_required = false;
public String realname_operation = "NONE"; public String realname_operation = "NONE";
...@@ -13,7 +13,7 @@ public class LoginResultJson { ...@@ -13,7 +13,7 @@ public class LoginResultJson {
public boolean safe_mobile_required = false; public boolean safe_mobile_required = false;
} }
public class VerifyAccountData { public static class VerifyAccountData {
public String uid; public String uid;
public String name = ""; public String name = "";
public String email; public String email;
......
...@@ -6,7 +6,7 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -6,7 +6,7 @@ import java.util.concurrent.ConcurrentHashMap;
import emu.grasscutter.GenshinConstants; import emu.grasscutter.GenshinConstants;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.commands.CommandMap; import emu.grasscutter.command.CommandMap;
import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.Account; import emu.grasscutter.game.Account;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.GenshinPlayer;
...@@ -19,6 +19,7 @@ import emu.grasscutter.game.shop.ShopManager; ...@@ -19,6 +19,7 @@ import emu.grasscutter.game.shop.ShopManager;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.netty.MihoyoKcpServer; import emu.grasscutter.netty.MihoyoKcpServer;
import org.greenrobot.eventbus.EventBus;
public final class GameServer extends MihoyoKcpServer { public final class GameServer extends MihoyoKcpServer {
private final InetSocketAddress address; private final InetSocketAddress address;
...@@ -34,9 +35,17 @@ public final class GameServer extends MihoyoKcpServer { ...@@ -34,9 +35,17 @@ public final class GameServer extends MihoyoKcpServer {
private final DungeonManager dungeonManager; private final DungeonManager dungeonManager;
private final CommandMap commandMap; private final CommandMap commandMap;
public EventBus OnGameServerStartFinish;
public EventBus OnGameServerTick;
public EventBus OnGameServerStop;
public GameServer(InetSocketAddress address) { public GameServer(InetSocketAddress address) {
super(address); super(address);
OnGameServerStartFinish = EventBus.builder().throwSubscriberException(true).logNoSubscriberMessages(false).build();
OnGameServerTick = EventBus.builder().throwSubscriberException(true).logNoSubscriberMessages(false).build();
OnGameServerStop = EventBus.builder().throwSubscriberException(true).logNoSubscriberMessages(false).build();
this.setServerInitializer(new GameServerInitializer(this)); this.setServerInitializer(new GameServerInitializer(this));
this.address = address; this.address = address;
this.packetHandler = new GameServerPacketHandler(PacketHandler.class); this.packetHandler = new GameServerPacketHandler(PacketHandler.class);
...@@ -145,7 +154,7 @@ public final class GameServer extends MihoyoKcpServer { ...@@ -145,7 +154,7 @@ public final class GameServer extends MihoyoKcpServer {
public Account getAccountByName(String username) { public Account getAccountByName(String username) {
Optional<GenshinPlayer> playerOpt = getPlayers().values().stream().filter(player -> player.getAccount().getUsername().equals(username)).findFirst(); Optional<GenshinPlayer> playerOpt = getPlayers().values().stream().filter(player -> player.getAccount().getUsername().equals(username)).findFirst();
if (playerOpt.get() != null) { if (playerOpt.isPresent()) {
return playerOpt.get().getAccount(); return playerOpt.get().getAccount();
} }
return DatabaseHelper.getAccountByName(username); return DatabaseHelper.getAccountByName(username);
...@@ -155,14 +164,20 @@ public final class GameServer extends MihoyoKcpServer { ...@@ -155,14 +164,20 @@ public final class GameServer extends MihoyoKcpServer {
for (GenshinPlayer player : this.getPlayers().values()) { for (GenshinPlayer player : this.getPlayers().values()) {
player.onTick(); player.onTick();
} }
OnGameServerTick.post(new GameServerTickEvent());
} }
@Override @Override
public void onStartFinish() { public void onStartFinish() {
Grasscutter.getLogger().info("Game Server started on port " + address.getPort()); Grasscutter.getLogger().info("Game Server started on port " + address.getPort());
OnGameServerStartFinish.post(new GameServerStartFinishEvent());
} }
public void onServerShutdown() { public void onServerShutdown() {
OnGameServerStop.post(new GameServerStopEvent());
// Kick and save all players // Kick and save all players
List<GenshinPlayer> list = new ArrayList<>(this.getPlayers().size()); List<GenshinPlayer> list = new ArrayList<>(this.getPlayers().size());
list.addAll(this.getPlayers().values()); list.addAll(this.getPlayers().values());
......
...@@ -87,7 +87,7 @@ public class GameServerPacketHandler { ...@@ -87,7 +87,7 @@ public class GameServerPacketHandler {
} }
// Log unhandled packets // Log unhandled packets
if (Grasscutter.getConfig().LOG_PACKETS) { if (Grasscutter.getConfig().getGameServerOptions().LOG_PACKETS) {
//Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + PacketOpcodesUtil.getOpcodeName(opcode)); //Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + PacketOpcodesUtil.getOpcodeName(opcode));
} }
} }
......
package emu.grasscutter.server.game;
public class GameServerStartFinishEvent {
// Placeholder class for now, probably will get used later
}
package emu.grasscutter.server.game;
public class GameServerStopEvent {
// Placeholder class for now, probably will get used later
}
package emu.grasscutter.server.game;
public class GameServerTickEvent {
// Placeholder class for now, probably will get used later
}
...@@ -165,7 +165,7 @@ public class GameSession extends MihoyoKcpChannel { ...@@ -165,7 +165,7 @@ public class GameSession extends MihoyoKcpChannel {
byte[] data = genshinPacket.build(); byte[] data = genshinPacket.build();
// Log // Log
if (Grasscutter.getConfig().LOG_PACKETS) { if (Grasscutter.getConfig().getGameServerOptions().LOG_PACKETS) {
logPacket(genshinPacket); logPacket(genshinPacket);
} }
...@@ -225,7 +225,7 @@ public class GameSession extends MihoyoKcpChannel { ...@@ -225,7 +225,7 @@ public class GameSession extends MihoyoKcpChannel {
} }
// Log packet // Log packet
if (Grasscutter.getConfig().LOG_PACKETS) { if (Grasscutter.getConfig().getGameServerOptions().LOG_PACKETS) {
Grasscutter.getLogger().info("RECV: " + PacketOpcodesUtil.getOpcodeName(opcode) + " (" + opcode + ")"); Grasscutter.getLogger().info("RECV: " + PacketOpcodesUtil.getOpcodeName(opcode) + " (" + opcode + ")");
System.out.println(Utils.bytesToHex(payload)); System.out.println(Utils.bytesToHex(payload));
} }
......
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
import emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.game.GameSession;
@Opcodes(PacketOpcodes.ClientAbilityInitFinishNotify)
public class HandlerClientAbilityInitFinishNotify extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload);
for (AbilityInvokeEntry entry : notif.getInvokesList()) {
session.getPlayer().getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry);
}
if (notif.getInvokesList().size() > 0) {
session.getPlayer().getClientAbilityInitFinishHandler().update(session.getPlayer());
}
}
}
...@@ -31,8 +31,11 @@ public class HandlerEnterSceneDoneReq extends PacketHandler { ...@@ -31,8 +31,11 @@ public class HandlerEnterSceneDoneReq extends PacketHandler {
// Locations // Locations
session.send(new PacketWorldPlayerLocationNotify(session.getPlayer().getWorld())); session.send(new PacketWorldPlayerLocationNotify(session.getPlayer().getWorld()));
session.send(new PacketScenePlayerLocationNotify(session.getPlayer())); session.send(new PacketScenePlayerLocationNotify(session.getPlayer().getScene()));
session.send(new PacketWorldPlayerRTTNotify(session.getPlayer().getWorld())); session.send(new PacketWorldPlayerRTTNotify(session.getPlayer().getWorld()));
// Reset timer for sending player locations
session.getPlayer().resetSendPlayerLocTime();
} }
} }
...@@ -35,15 +35,15 @@ public class HandlerGetPlayerTokenReq extends PacketHandler { ...@@ -35,15 +35,15 @@ public class HandlerGetPlayerTokenReq extends PacketHandler {
// Has character // Has character
boolean doesPlayerExist = false; boolean doesPlayerExist = false;
if (account.getPlayerId() > 0) { if (account.getPlayerUid() > 0) {
// Set flag for player existing // Set flag for player existing
doesPlayerExist = DatabaseHelper.checkPlayerExists(account.getPlayerId()); doesPlayerExist = DatabaseHelper.checkPlayerExists(account.getPlayerUid());
} }
// Set reserve player id if account doesnt exist // Set reserve player id if account doesnt exist
if (!doesPlayerExist) { if (!doesPlayerExist) {
int id = DatabaseHelper.getNextPlayerId(session.getAccount().getPlayerId()); int id = DatabaseHelper.getNextPlayerId(session.getAccount().getPlayerUid());
if (id != session.getAccount().getPlayerId()) { if (id != session.getAccount().getPlayerUid()) {
session.getAccount().setPlayerId(id); session.getAccount().setPlayerId(id);
session.getAccount().save(); session.getAccount().save();
} }
......
...@@ -16,6 +16,18 @@ import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify; ...@@ -16,6 +16,18 @@ import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify;
@Opcodes(PacketOpcodes.MarkMapReq) @Opcodes(PacketOpcodes.MarkMapReq)
public class HandlerMarkMapReq extends PacketHandler { public class HandlerMarkMapReq extends PacketHandler {
private static boolean isInt(String str) {
try {
@SuppressWarnings("unused")
int x = Integer.parseInt(str);
return true; // String is an Integer
} catch (NumberFormatException e) {
return false; // String is not an Integer
}
}
@Override @Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
MarkMapReq req = MarkMapReq.parseFrom(payload); MarkMapReq req = MarkMapReq.parseFrom(payload);
...@@ -26,15 +38,18 @@ public class HandlerMarkMapReq extends PacketHandler { ...@@ -26,15 +38,18 @@ public class HandlerMarkMapReq extends PacketHandler {
session.getPlayer().getPos().setX(req.getMark().getPos().getX()); session.getPlayer().getPos().setX(req.getMark().getPos().getX());
session.getPlayer().getPos().setZ(req.getMark().getPos().getZ()); session.getPlayer().getPos().setZ(req.getMark().getPos().getZ());
session.getPlayer().getPos().setY(300);
Grasscutter.getLogger().info("Player [" + session.getPlayer().getUid() + ":" + session.getPlayer().getNickname() + "] tp to " + session.getPlayer().getPos() + " Scene id: " + req.getMark().getSceneId()); session.getPlayer().getPos()
.setY(isInt(req.getMark().getName()) ? Integer.parseInt(req.getMark().getName()) : 300);
Grasscutter.getLogger().info("Player [" + session.getPlayer().getUid() + ":" + session.getPlayer().getNickname()
+ "] tp to " + session.getPlayer().getPos() + " Scene id: " + req.getMark().getSceneId());
if (req.getMark().getSceneId() != session.getPlayer().getSceneId()) { if (req.getMark().getSceneId() != session.getPlayer().getSceneId()) {
session.getPlayer().getWorld().transferPlayerToScene(session.getPlayer(), req.getMark().getSceneId(), session.getPlayer().getPos()); session.getPlayer().getWorld().transferPlayerToScene(session.getPlayer(), req.getMark().getSceneId(),
session.getPlayer().getPos());
} else { } else {
session.getPlayer().getScene().broadcastPacket(new PacketSceneEntityAppearNotify(session.getPlayer())); session.getPlayer().getScene().broadcastPacket(new PacketSceneEntityAppearNotify(session.getPlayer()));
} }
} }
} }
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.NpcTalkReqOuterClass.NpcTalkReq;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketNpcTalkRsp;
@Opcodes(PacketOpcodes.NpcTalkReq)
public class HandlerNpcTalkReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
NpcTalkReq req = NpcTalkReq.parseFrom(payload);
session.send(new PacketNpcTalkRsp(req.getNpcEntityId(), req.getTalkId(), req.getEntityId()));
}
}
...@@ -30,7 +30,7 @@ public class HandlerPlayerLoginReq extends PacketHandler { ...@@ -30,7 +30,7 @@ public class HandlerPlayerLoginReq extends PacketHandler {
} }
// Load character from db // Load character from db
GenshinPlayer player = DatabaseHelper.getPlayerById(session.getAccount().getPlayerId()); GenshinPlayer player = DatabaseHelper.getPlayerById(session.getAccount().getPlayerUid());
if (player == null) { if (player == null) {
// Send packets // Send packets
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment