Merge branch 'development' of https://github.com/Melledy/Grasscutter into development

This commit is contained in:
Benjamin Elsdon 2022-04-21 18:11:51 +08:00
commit 1500d2e885
28 changed files with 155 additions and 119 deletions

View File

@ -19,7 +19,7 @@
"bannerType": "EVENT", "bannerType": "EVENT",
"prefabPath": "GachaShowPanel_A079", "prefabPath": "GachaShowPanel_A079",
"previewPrefabPath": "UI_Tab_GachaShowPanel_A079", "previewPrefabPath": "UI_Tab_GachaShowPanel_A079",
"titlePath": "UI_GACHA_SHOW_PANEL_A079_TITLE", "titlePath": "UI_GACHA_SHOW_PANEL_A048_TITLE",
"costItem": 223, "costItem": 223,
"beginTime": 0, "beginTime": 0,
"endTime": 1924992000, "endTime": 1924992000,
@ -34,7 +34,7 @@
"bannerType": "WEAPON", "bannerType": "WEAPON",
"prefabPath": "GachaShowPanel_A080", "prefabPath": "GachaShowPanel_A080",
"previewPrefabPath": "UI_Tab_GachaShowPanel_A080", "previewPrefabPath": "UI_Tab_GachaShowPanel_A080",
"titlePath": "UI_GACHA_SHOW_PANEL_A080_TITLE", "titlePath": "UI_GACHA_SHOW_PANEL_A021_TITLE",
"costItem": 223, "costItem": 223,
"beginTime": 0, "beginTime": 0,
"endTime": 1924992000, "endTime": 1924992000,

View File

@ -27,6 +27,7 @@ public final class Config {
public String Ip = "127.0.0.1"; public String Ip = "127.0.0.1";
public String PublicIp = ""; public String PublicIp = "";
public int Port = 443; public int Port = 443;
public int OverseaLogPort = 8888;
public int UploadLogPort = 80; public int UploadLogPort = 80;
public String KeystorePath = "./keystore.p12"; public String KeystorePath = "./keystore.p12";
public String KeystorePassword = ""; public String KeystorePassword = "";

View File

@ -46,7 +46,7 @@ public final class AccountCommand implements CommandHandler {
CommandHandler.sendMessage(null, "Account already exists."); CommandHandler.sendMessage(null, "Account already exists.");
return; return;
} else { } else {
CommandHandler.sendMessage(null, "Account created with UID " + account.getPlayerId() + "."); CommandHandler.sendMessage(null, "Account created with UID " + account.getPlayerUid() + ".");
account.addPermission("*"); // Grant the player superuser permissions. account.addPermission("*"); // Grant the player superuser permissions.
account.save(); // Save account to database. account.save(); // Save account to database.
} }

View File

@ -23,11 +23,17 @@ public final class ChangeSceneCommand implements CommandHandler {
try { try {
int sceneId = Integer.parseInt(args.get(0)); int sceneId = Integer.parseInt(args.get(0));
if (sceneId == sender.getSceneId()) {
CommandHandler.sendMessage(sender, "You are already in that scene");
return;
}
boolean result = sender.getWorld().transferPlayerToScene(sender, sceneId, sender.getPos()); boolean result = sender.getWorld().transferPlayerToScene(sender, sceneId, sender.getPos());
CommandHandler.sendMessage(sender, "Changed to scene " + sceneId); CommandHandler.sendMessage(sender, "Changed to scene " + sceneId);
if (!result) { if (!result) {
CommandHandler.sendMessage(sender, "Scene does not exist or you are already in it"); CommandHandler.sendMessage(sender, "Scene does not exist");
} }
} catch (Exception e) { } catch (Exception e) {
CommandHandler.sendMessage(sender, "Usage: changescene <scene id>"); CommandHandler.sendMessage(sender, "Usage: changescene <scene id>");

View File

@ -22,7 +22,7 @@ public final class KickCommand implements CommandHandler {
} }
if (sender != null) { if (sender != null) {
CommandHandler.sendMessage(sender, String.format("Player [%s:%s] has kicked player [%s:%s]", sender.getAccount().getPlayerId(), sender.getAccount().getUsername(), target, targetPlayer.getAccount().getUsername())); CommandHandler.sendMessage(sender, String.format("Player [%s:%s] has kicked player [%s:%s]", sender.getAccount().getPlayerUid(), sender.getAccount().getUsername(), target, targetPlayer.getAccount().getUsername()));
} }
CommandHandler.sendMessage(sender, String.format("Kicking player [%s:%s]", target, targetPlayer.getAccount().getUsername())); CommandHandler.sendMessage(sender, String.format("Kicking player [%s:%s]", target, targetPlayer.getAccount().getUsername()));

View File

@ -1,5 +1,6 @@
package emu.grasscutter.game; package emu.grasscutter.game;
import dev.morphia.annotations.AlsoLoad;
import dev.morphia.annotations.Collation; import dev.morphia.annotations.Collation;
import dev.morphia.annotations.Entity; import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id; import dev.morphia.annotations.Id;
@ -24,7 +25,7 @@ public class Account {
private String username; private String username;
private String password; // Unused for now private String password; // Unused for now
private int playerId; @AlsoLoad("playerUid") private int playerId;
private String email; private String email;
private String token; private String token;
@ -68,7 +69,7 @@ public class Account {
this.token = token; this.token = token;
} }
public int getPlayerId() { public int getPlayerUid() {
return this.playerId; return this.playerId;
} }

View File

@ -31,6 +31,7 @@ import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason; import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason;
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo; import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketAbilityInvocationsNotify; import emu.grasscutter.server.packet.send.PacketAbilityInvocationsNotify;
@ -49,9 +50,11 @@ import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify;
import emu.grasscutter.server.packet.send.PacketPlayerPropNotify; import emu.grasscutter.server.packet.send.PacketPlayerPropNotify;
import emu.grasscutter.server.packet.send.PacketPlayerStoreNotify; import emu.grasscutter.server.packet.send.PacketPlayerStoreNotify;
import emu.grasscutter.server.packet.send.PacketPrivateChatNotify; import emu.grasscutter.server.packet.send.PacketPrivateChatNotify;
import emu.grasscutter.server.packet.send.PacketScenePlayerLocationNotify;
import emu.grasscutter.server.packet.send.PacketSetNameCardRsp; import emu.grasscutter.server.packet.send.PacketSetNameCardRsp;
import emu.grasscutter.server.packet.send.PacketStoreWeightLimitNotify; import emu.grasscutter.server.packet.send.PacketStoreWeightLimitNotify;
import emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify; import emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify;
import emu.grasscutter.server.packet.send.PacketWorldPlayerLocationNotify;
import emu.grasscutter.server.packet.send.PacketWorldPlayerRTTNotify; import emu.grasscutter.server.packet.send.PacketWorldPlayerRTTNotify;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
@ -101,6 +104,7 @@ public class GenshinPlayer {
@Transient private int enterSceneToken; @Transient private int enterSceneToken;
@Transient private SceneLoadState sceneState; @Transient private SceneLoadState sceneState;
@Transient private boolean hasSentAvatarDataNotify; @Transient private boolean hasSentAvatarDataNotify;
@Transient private long nextSendPlayerLocTime = 0;
@Transient private final Int2ObjectMap<CoopRequest> coopRequests; @Transient private final Int2ObjectMap<CoopRequest> coopRequests;
@Transient private final InvokeHandler<CombatInvokeEntry> combatInvokeHandler; @Transient private final InvokeHandler<CombatInvokeEntry> combatInvokeHandler;
@ -121,6 +125,12 @@ public class GenshinPlayer {
} }
this.properties.put(prop.getId(), 0); this.properties.put(prop.getId(), 0);
} }
this.gachaInfo = new PlayerGachaInfo();
this.nameCardList = new HashSet<>();
this.flyCloakList = new HashSet<>();
this.costumeList = new HashSet<>();
this.setSceneId(3); this.setSceneId(3);
this.setRegionId(1); this.setRegionId(1);
this.sceneState = SceneLoadState.NONE; this.sceneState = SceneLoadState.NONE;
@ -140,11 +150,6 @@ public class GenshinPlayer {
this.nickname = "Traveler"; this.nickname = "Traveler";
this.signature = ""; this.signature = "";
this.teamManager = new TeamManager(this); this.teamManager = new TeamManager(this);
this.gachaInfo = new PlayerGachaInfo();
this.playerProfile = new PlayerProfile(this);
this.nameCardList = new HashSet<>();
this.flyCloakList = new HashSet<>();
this.costumeList = new HashSet<>();
this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, 1); this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, 1);
this.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, 1); this.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, 1);
this.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, 50); this.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, 50);
@ -165,6 +170,7 @@ public class GenshinPlayer {
public void setUid(int id) { public void setUid(int id) {
this.id = id; this.id = id;
this.getProfile().syncWithCharacter(this);
} }
public long getNextGenshinGuid() { public long getNextGenshinGuid() {
@ -654,6 +660,13 @@ public class GenshinPlayer {
return social; return social;
} }
public WorldPlayerLocationInfo getWorldPlayerLocationInfo() {
return WorldPlayerLocationInfo.newBuilder()
.setSceneId(this.getSceneId())
.setPlayerLoc(this.getPlayerLocationInfo())
.build();
}
public PlayerLocationInfo getPlayerLocationInfo() { public PlayerLocationInfo getPlayerLocationInfo() {
return PlayerLocationInfo.newBuilder() return PlayerLocationInfo.newBuilder()
.setUid(this.getUid()) .setUid(this.getUid())
@ -679,9 +692,22 @@ public class GenshinPlayer {
} }
// Ping // Ping
if (this.getWorld() != null) { if (this.getWorld() != null) {
this.sendPacket(new PacketWorldPlayerRTTNotify(this.getWorld())); // Player ping // RTT notify - very important to send this often
this.sendPacket(new PacketWorldPlayerRTTNotify(this.getWorld()));
// Update player locations if in multiplayer every 5 seconds
long time = System.currentTimeMillis();
if (this.getWorld().isMultiplayer() && this.getScene() != null && time > nextSendPlayerLocTime) {
this.sendPacket(new PacketWorldPlayerLocationNotify(this.getWorld()));
this.sendPacket(new PacketScenePlayerLocationNotify(this.getScene()));
this.resetSendPlayerLocTime();
}
} }
} }
public void resetSendPlayerLocTime() {
this.nextSendPlayerLocTime = System.currentTimeMillis() + 5000;
}
@PostLoad @PostLoad
private void onLoad() { private void onLoad() {
@ -696,12 +722,8 @@ public class GenshinPlayer {
// Make sure these exist // Make sure these exist
if (this.getTeamManager() == null) { if (this.getTeamManager() == null) {
this.teamManager = new TeamManager(this); this.teamManager = new TeamManager(this);
} if (this.getGachaInfo() == null) { } if (this.getProfile().getUid() == 0) {
this.gachaInfo = new PlayerGachaInfo(); this.getProfile().syncWithCharacter(this);
} if (this.nameCardList == null) {
this.nameCardList = new HashSet<>();
} if (this.costumeList == null) {
this.costumeList = new HashSet<>();
} }
// Check if player object exists in server // Check if player object exists in server

View File

@ -206,28 +206,9 @@ public class World implements Iterable<GenshinPlayer> {
public void deregisterScene(GenshinScene scene) { public void deregisterScene(GenshinScene scene) {
this.getScenes().remove(scene.getId()); this.getScenes().remove(scene.getId());
} }
public boolean forceTransferPlayerToScene(GenshinPlayer player, int sceneId, Position pos) {
// Forces the client to reload the scene map to prevent the player from falling off the map.
if (GenshinData.getSceneDataMap().get(sceneId) == null) {
return false;
}
if (player.getScene() != null) {
player.getScene().removePlayer(player);
}
GenshinScene scene = this.getSceneById(sceneId);
scene.addPlayer(player);
player.getPos().set(pos);
// Teleport packet
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterSelf, EnterReason.TransPoint, sceneId, pos));
return true;
}
public boolean transferPlayerToScene(GenshinPlayer player, int sceneId, Position pos) { public boolean transferPlayerToScene(GenshinPlayer player, int sceneId, Position pos) {
if (player.getScene().getId() == sceneId || GenshinData.getSceneDataMap().get(sceneId) == null) { if (GenshinData.getSceneDataMap().get(sceneId) == null) {
return false; return false;
} }

View File

@ -13,6 +13,7 @@ import dev.morphia.annotations.Indexed;
import dev.morphia.annotations.PostLoad; import dev.morphia.annotations.PostLoad;
import dev.morphia.annotations.PrePersist; import dev.morphia.annotations.PrePersist;
import dev.morphia.annotations.Transient; import dev.morphia.annotations.Transient;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData; import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.common.FightPropData; import emu.grasscutter.data.common.FightPropData;
import emu.grasscutter.data.custom.OpenConfigEntry; import emu.grasscutter.data.custom.OpenConfigEntry;
@ -42,6 +43,7 @@ import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo; import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo;
import emu.grasscutter.net.proto.AvatarInfoOuterClass.AvatarInfo; import emu.grasscutter.net.proto.AvatarInfoOuterClass.AvatarInfo;
import emu.grasscutter.server.packet.send.PacketAbilityChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify; import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarFightPropNotify; import emu.grasscutter.server.packet.send.PacketAvatarFightPropNotify;
import emu.grasscutter.utils.ProtoHelper; import emu.grasscutter.utils.ProtoHelper;
@ -69,7 +71,7 @@ public class GenshinAvatar {
@Transient private final Int2ObjectMap<GenshinItem> equips; @Transient private final Int2ObjectMap<GenshinItem> equips;
@Transient private final Int2FloatOpenHashMap fightProp; @Transient private final Int2FloatOpenHashMap fightProp;
@Transient private final Set<String> bonusAbilityList; @Transient private Set<String> extraAbilityEmbryos;
private Map<Integer, Integer> skillLevelMap; // Talent levels private Map<Integer, Integer> skillLevelMap; // Talent levels
private Map<Integer, Integer> proudSkillBonusMap; // Talent bonus levels (from const) private Map<Integer, Integer> proudSkillBonusMap; // Talent bonus levels (from const)
@ -86,7 +88,7 @@ public class GenshinAvatar {
// Morhpia only! // Morhpia only!
this.equips = new Int2ObjectOpenHashMap<>(); this.equips = new Int2ObjectOpenHashMap<>();
this.fightProp = new Int2FloatOpenHashMap(); this.fightProp = new Int2FloatOpenHashMap();
this.bonusAbilityList = new HashSet<>(); this.extraAbilityEmbryos = new HashSet<>();
this.proudSkillBonusMap = new HashMap<>(); // TODO Move to genshin avatar this.proudSkillBonusMap = new HashMap<>(); // TODO Move to genshin avatar
} }
@ -260,8 +262,8 @@ public class GenshinAvatar {
return proudSkillBonusMap; return proudSkillBonusMap;
} }
public Set<String> getBonusAbilityList() { public Set<String> getExtraAbilityEmbryos() {
return bonusAbilityList; return extraAbilityEmbryos;
} }
public float getCurrentHp() { public float getCurrentHp() {
@ -347,14 +349,14 @@ public class GenshinAvatar {
item.setEquipCharacter(this.getAvatarId()); item.setEquipCharacter(this.getAvatarId());
item.save(); item.save();
if (this.getPlayer().hasSentAvatarDataNotify()) {
this.getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(this, item));
}
if (shouldRecalc) { if (shouldRecalc) {
this.recalcStats(); this.recalcStats();
} }
if (this.getPlayer().hasSentAvatarDataNotify()) {
this.getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(this, item));
}
return true; return true;
} }
@ -371,11 +373,18 @@ public class GenshinAvatar {
} }
public void recalcStats() { public void recalcStats() {
recalcStats(false);
}
public void recalcStats(boolean forceSendAbilityChange) {
// Setup // Setup
AvatarData data = this.getAvatarData(); AvatarData data = this.getAvatarData();
AvatarPromoteData promoteData = GenshinData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel()); AvatarPromoteData promoteData = GenshinData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel());
Int2IntOpenHashMap setMap = new Int2IntOpenHashMap(); Int2IntOpenHashMap setMap = new Int2IntOpenHashMap();
this.getBonusAbilityList().clear();
// Extra ability embryos
Set<String> prevExtraAbilityEmbryos = this.getExtraAbilityEmbryos();
this.extraAbilityEmbryos = new HashSet<>();
// Get hp percent, set to 100% if none // Get hp percent, set to 100% if none
float hpPercent = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 ? 1f : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); float hpPercent = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 ? 1f : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
@ -458,7 +467,7 @@ public class GenshinAvatar {
} }
// Add any skill strings from this affix // Add any skill strings from this affix
this.addToAbilityList(affix.getOpenConfig(), true); this.addToExtraAbilityEmbryos(affix.getOpenConfig(), true);
} else { } else {
break; break;
} }
@ -505,7 +514,7 @@ public class GenshinAvatar {
} }
// Add any skill strings from this affix // Add any skill strings from this affix
this.addToAbilityList(affix.getOpenConfig(), true); this.addToExtraAbilityEmbryos(affix.getOpenConfig(), true);
} }
} }
} }
@ -538,7 +547,7 @@ public class GenshinAvatar {
} }
// Add any skill strings from this proud skill // Add any skill strings from this proud skill
this.addToAbilityList(proudSkillData.getOpenConfig(), true); this.addToExtraAbilityEmbryos(proudSkillData.getOpenConfig(), true);
} }
// Constellations // Constellations
@ -550,7 +559,7 @@ public class GenshinAvatar {
} }
// Add any skill strings from this constellation // Add any skill strings from this constellation
this.addToAbilityList(avatarTalentData.getOpenConfig(), false); this.addToExtraAbilityEmbryos(avatarTalentData.getOpenConfig(), false);
} }
} }
@ -573,11 +582,17 @@ public class GenshinAvatar {
// Packet // Packet
if (getPlayer() != null && getPlayer().hasSentAvatarDataNotify()) { if (getPlayer() != null && getPlayer().hasSentAvatarDataNotify()) {
// Update stats for client
getPlayer().sendPacket(new PacketAvatarFightPropNotify(this)); getPlayer().sendPacket(new PacketAvatarFightPropNotify(this));
// Update client abilities
EntityAvatar entity = this.getAsEntity();
if (entity != null && (!this.getExtraAbilityEmbryos().equals(prevExtraAbilityEmbryos) || forceSendAbilityChange)) {
getPlayer().sendPacket(new PacketAbilityChangeNotify(entity));
}
} }
} }
public void addToAbilityList(String openConfig, boolean forceAdd) { public void addToExtraAbilityEmbryos(String openConfig, boolean forceAdd) {
if (openConfig == null || openConfig.length() == 0) { if (openConfig == null || openConfig.length() == 0) {
return; return;
} }
@ -586,14 +601,14 @@ public class GenshinAvatar {
if (entry == null) { if (entry == null) {
if (forceAdd) { if (forceAdd) {
// Add config string to ability skill list anyways // Add config string to ability skill list anyways
this.getBonusAbilityList().add(openConfig); this.getExtraAbilityEmbryos().add(openConfig);
} }
return; return;
} }
if (entry.getAddAbilities() != null) { if (entry.getAddAbilities() != null) {
for (String ability : entry.getAddAbilities()) { for (String ability : entry.getAddAbilities()) {
this.getBonusAbilityList().add(ability); this.getExtraAbilityEmbryos().add(ability);
} }
} }
} }

View File

@ -223,8 +223,8 @@ public class EntityAvatar extends GenshinEntity {
} }
} }
// Add equip abilities // Add equip abilities
if (this.getAvatar().getBonusAbilityList().size() > 0) { if (this.getAvatar().getExtraAbilityEmbryos().size() > 0) {
for (String skill : this.getAvatar().getBonusAbilityList()) { for (String skill : this.getAvatar().getExtraAbilityEmbryos()) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder() AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId) .setAbilityId(++embryoId)
.setAbilityNameHash(Utils.abilityHash(skill)) .setAbilityNameHash(Utils.abilityHash(skill))

View File

@ -220,7 +220,7 @@ public class FriendsList {
friendship.setOwner(getPlayer()); friendship.setOwner(getPlayer());
// Check if friend is online // Check if friend is online
GenshinPlayer friend = getPlayer().getSession().getServer().getPlayerByUid(friendship.getFriendProfile().getId()); GenshinPlayer friend = getPlayer().getSession().getServer().getPlayerByUid(friendship.getFriendProfile().getUid());
if (friend != null) { if (friend != null) {
// Set friend to online mode // Set friend to online mode
friendship.setFriendProfile(friend); friendship.setFriendProfile(friend);

View File

@ -88,7 +88,7 @@ public class Friendship {
public FriendBrief toProto() { public FriendBrief toProto() {
FriendBrief proto = FriendBrief.newBuilder() FriendBrief proto = FriendBrief.newBuilder()
.setUid(getFriendProfile().getId()) .setUid(getFriendProfile().getUid())
.setNickname(getFriendProfile().getName()) .setNickname(getFriendProfile().getName())
.setLevel(getFriendProfile().getPlayerLevel()) .setLevel(getFriendProfile().getPlayerLevel())
.setAvatar(HeadImage.newBuilder().setAvatarId(getFriendProfile().getAvatarId())) .setAvatar(HeadImage.newBuilder().setAvatarId(getFriendProfile().getAvatarId()))

View File

@ -7,7 +7,7 @@ import emu.grasscutter.utils.Utils;
public class PlayerProfile { public class PlayerProfile {
@Transient private GenshinPlayer player; @Transient private GenshinPlayer player;
private int id; @AlsoLoad("id") private int uid;
private int nameCard; private int nameCard;
private int avatarId; private int avatarId;
private String name; private String name;
@ -22,12 +22,12 @@ public class PlayerProfile {
public PlayerProfile() { } public PlayerProfile() { }
public PlayerProfile(GenshinPlayer player) { public PlayerProfile(GenshinPlayer player) {
this.id = player.getUid(); this.uid = player.getUid();
this.syncWithCharacter(player); this.syncWithCharacter(player);
} }
public int getId() { public int getUid() {
return id; return uid;
} }
public GenshinPlayer getPlayer() { public GenshinPlayer getPlayer() {
@ -87,6 +87,7 @@ public class PlayerProfile {
return; return;
} }
this.uid = player.getUid();
this.name = player.getNickname(); this.name = player.getNickname();
this.avatarId = player.getHeadImage(); this.avatarId = player.getHeadImage();
this.signature = player.getSignature(); this.signature = player.getSignature();

View File

@ -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 {
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 {
} }
} }
// 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 {
// 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();
} }

View File

@ -456,7 +456,7 @@ public final class DispatchServer {
Grasscutter.getLogger().info("Dispatch server started on port " + getAddress().getPort()); Grasscutter.getLogger().info("Dispatch server started on port " + getAddress().getPort());
// Logging servers // Logging servers
HttpServer overseaLogServer = HttpServer.create(new InetSocketAddress(Grasscutter.getConfig().getDispatchOptions().Ip, 8888), 0); HttpServer overseaLogServer = HttpServer.create(new InetSocketAddress(Grasscutter.getConfig().getDispatchOptions().Ip, Grasscutter.getConfig().getDispatchOptions().OverseaLogPort), 0);
overseaLogServer.createContext( // overseauspider.yuanshen.com overseaLogServer.createContext( // overseauspider.yuanshen.com
"/log", "/log",
new DispatchHttpJsonHandler("{\"code\":0}") new DispatchHttpJsonHandler("{\"code\":0}")

View File

@ -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();
} }
} }

View File

@ -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();
} }

View File

@ -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

View File

@ -1,11 +1,15 @@
package emu.grasscutter.server.packet.recv; package emu.grasscutter.server.packet.recv;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.custom.ScenePointEntry;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.SceneTransToPointReqOuterClass.SceneTransToPointReq; import emu.grasscutter.net.proto.SceneTransToPointReqOuterClass.SceneTransToPointReq;
import emu.grasscutter.net.proto.SceneTransToPointRspOuterClass.SceneTransToPointRsp;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketSceneTransToPointRsp; import emu.grasscutter.server.packet.send.PacketSceneTransToPointRsp;
import emu.grasscutter.utils.Position;
@Opcodes(PacketOpcodes.SceneTransToPointReq) @Opcodes(PacketOpcodes.SceneTransToPointReq)
public class HandlerSceneTransToPointReq extends PacketHandler { public class HandlerSceneTransToPointReq extends PacketHandler {
@ -13,7 +17,20 @@ public class HandlerSceneTransToPointReq extends PacketHandler {
@Override @Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
SceneTransToPointReq req = SceneTransToPointReq.parseFrom(payload); SceneTransToPointReq req = SceneTransToPointReq.parseFrom(payload);
session.send(new PacketSceneTransToPointRsp(session.getPlayer(), req.getPointId(), req.getSceneId()));
String code = req.getSceneId() + "_" + req.getPointId();
ScenePointEntry scenePointEntry = GenshinData.getScenePointEntries().get(code);
if (scenePointEntry != null) {
float x = scenePointEntry.getPointData().getTranPos().getX();
float y = scenePointEntry.getPointData().getTranPos().getY();
float z = scenePointEntry.getPointData().getTranPos().getZ();
session.getPlayer().getWorld().transferPlayerToScene(session.getPlayer(), req.getSceneId(), new Position(x, y, z));
session.send(new PacketSceneTransToPointRsp(session.getPlayer(), req.getPointId(), req.getSceneId()));
} else {
session.send(new PacketSceneTransToPointRsp());
}
} }
} }

View File

@ -3,6 +3,7 @@ package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.SetEntityClientDataNotifyOuterClass.SetEntityClientDataNotify;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
@ -16,8 +17,11 @@ public class HandlerSetEntityClientDataNotify extends PacketHandler {
return; return;
} }
// Make sure packet is a valid proto before replaying it to the other players
SetEntityClientDataNotify notif = SetEntityClientDataNotify.parseFrom(payload);
GenshinPacket packet = new GenshinPacket(PacketOpcodes.SetEntityClientDataNotify, true); GenshinPacket packet = new GenshinPacket(PacketOpcodes.SetEntityClientDataNotify, true);
packet.setData(payload); packet.setData(notif);
session.getPlayer().getScene().broadcastPacketToOthers(session.getPlayer(), packet); session.getPlayer().getScene().broadcastPacketToOthers(session.getPlayer(), packet);
} }

View File

@ -43,7 +43,7 @@ public class HandlerSetPlayerBornDataReq extends PacketHandler {
try { try {
// Save to db // Save to db
DatabaseHelper.createPlayer(player, session.getAccount().getPlayerId()); DatabaseHelper.createPlayer(player, session.getAccount().getPlayerUid());
// Create avatar // Create avatar
if (player.getAvatars().getAvatarCount() == 0) { if (player.getAvatars().getAvatarCount() == 0) {

View File

@ -8,8 +8,8 @@ import emu.grasscutter.net.proto.AbilityChangeNotifyOuterClass.AbilityChangeNoti
public class PacketAbilityChangeNotify extends GenshinPacket { public class PacketAbilityChangeNotify extends GenshinPacket {
public PacketAbilityChangeNotify(EntityAvatar entity) { public PacketAbilityChangeNotify(EntityAvatar entity) {
super(PacketOpcodes.AbilityChangeNotify); super(PacketOpcodes.AbilityChangeNotify, true);
AbilityChangeNotify proto = AbilityChangeNotify.newBuilder() AbilityChangeNotify proto = AbilityChangeNotify.newBuilder()
.setEntityId(entity.getId()) .setEntityId(entity.getId())
.setAbilityControlBlock(entity.getAbilityControlBlock()) .setAbilityControlBlock(entity.getAbilityControlBlock())

View File

@ -23,7 +23,6 @@ public class PacketGetPlayerFriendListRsp extends GenshinPacket {
.setWorldLevel(0) .setWorldLevel(0)
.setSignature("") .setSignature("")
.setLastActiveTime((int) (System.currentTimeMillis() / 1000f)) .setLastActiveTime((int) (System.currentTimeMillis() / 1000f))
.setIsMpModeAvailable(true)
.setNameCardId(210001) .setNameCardId(210001)
.setOnlineState(FriendOnlineState.FRIEND_ONLINE) .setOnlineState(FriendOnlineState.FRIEND_ONLINE)
.setParam(1) .setParam(1)

View File

@ -16,7 +16,7 @@ public class PacketGetPlayerTokenRsp extends GenshinPacket {
this.setUseDispatchKey(true); this.setUseDispatchKey(true);
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder() GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
.setPlayerUid(session.getAccount().getPlayerId()) .setPlayerUid(session.getAccount().getPlayerUid())
.setAccountToken(session.getAccount().getToken()) .setAccountToken(session.getAccount().getToken())
.setAccountType(1) .setAccountType(1)
.setIsProficientPlayer(doesPlayerExist) // Not sure where this goes .setIsProficientPlayer(doesPlayerExist) // Not sure where this goes

View File

@ -1,19 +1,20 @@
package emu.grasscutter.server.packet.send; package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.GenshinScene;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.ScenePlayerLocationNotifyOuterClass.ScenePlayerLocationNotify; import emu.grasscutter.net.proto.ScenePlayerLocationNotifyOuterClass.ScenePlayerLocationNotify;
public class PacketScenePlayerLocationNotify extends GenshinPacket { public class PacketScenePlayerLocationNotify extends GenshinPacket {
public PacketScenePlayerLocationNotify(GenshinPlayer player) { public PacketScenePlayerLocationNotify(GenshinScene scene) {
super(PacketOpcodes.ScenePlayerLocationNotify); super(PacketOpcodes.ScenePlayerLocationNotify);
ScenePlayerLocationNotify.Builder proto = ScenePlayerLocationNotify.newBuilder() ScenePlayerLocationNotify.Builder proto = ScenePlayerLocationNotify.newBuilder()
.setSceneId(player.getSceneId()); .setSceneId(scene.getId());
for (GenshinPlayer p : player.getWorld().getPlayers()) { for (GenshinPlayer p : scene.getPlayers()) {
proto.addPlayerLocList(p.getPlayerLocationInfo()); proto.addPlayerLocList(p.getPlayerLocationInfo());
} }

View File

@ -13,23 +13,22 @@ public class PacketSceneTransToPointRsp extends GenshinPacket {
public PacketSceneTransToPointRsp(GenshinPlayer player, int pointId, int sceneId) { public PacketSceneTransToPointRsp(GenshinPlayer player, int pointId, int sceneId) {
super(PacketOpcodes.SceneTransToPointRsp); super(PacketOpcodes.SceneTransToPointRsp);
String code = sceneId + "_" + pointId;
ScenePointEntry scenePointEntry = GenshinData.getScenePointEntries().get(code);
float x = scenePointEntry.getPointData().getTranPos().getX();
float y = scenePointEntry.getPointData().getTranPos().getY();
float z = scenePointEntry.getPointData().getTranPos().getZ();
player.getPos().set(new Position(x, y, z));
player.getWorld().forceTransferPlayerToScene(player, sceneId, player.getPos());
SceneTransToPointRsp proto = SceneTransToPointRsp.newBuilder() SceneTransToPointRsp proto = SceneTransToPointRsp.newBuilder()
.setRetcode(0) .setRetcode(0)
.setPointId(pointId) .setPointId(pointId)
.setSceneId(sceneId) .setSceneId(sceneId)
.build(); .build();
this.setData(proto);
}
public PacketSceneTransToPointRsp() {
super(PacketOpcodes.SceneTransToPointRsp);
SceneTransToPointRsp proto = SceneTransToPointRsp.newBuilder()
.setRetcode(1) // Internal server error
.build();
this.setData(proto); this.setData(proto);
} }
} }

View File

@ -13,7 +13,7 @@ public class PacketSceneUnlockInfoNotify extends GenshinPacket {
SceneUnlockInfoNotify proto = SceneUnlockInfoNotify.newBuilder() SceneUnlockInfoNotify proto = SceneUnlockInfoNotify.newBuilder()
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(1)) .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(1))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(3)) .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(3))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(4)) .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(4).addSceneTagIdList(106).addSceneTagIdList(109))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(5)) .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(5))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(6)) .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(6))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(7)) .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(7))

View File

@ -14,7 +14,7 @@ public class PacketWorldPlayerLocationNotify extends GenshinPacket {
WorldPlayerLocationNotify.Builder proto = WorldPlayerLocationNotify.newBuilder(); WorldPlayerLocationNotify.Builder proto = WorldPlayerLocationNotify.newBuilder();
for (GenshinPlayer p : world.getPlayers()) { for (GenshinPlayer p : world.getPlayers()) {
proto.addPlayerLocList(p.getPlayerLocationInfo()); proto.addPlayerLocList(p.getWorldPlayerLocationInfo());
} }
this.setData(proto); this.setData(proto);