sanity check

This commit is contained in:
Asnxthaony 2022-04-25 14:51:34 +08:00 committed by Melledy
parent 122568ad27
commit 4e5d72a99a
3 changed files with 189 additions and 179 deletions

View File

@ -1,7 +1,5 @@
package emu.grasscutter.game; package emu.grasscutter.game;
import java.util.*;
import dev.morphia.annotations.*; import dev.morphia.annotations.*;
import emu.grasscutter.GenshinConstants; import emu.grasscutter.GenshinConstants;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
@ -23,7 +21,6 @@ import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
import emu.grasscutter.net.proto.BirthdayOuterClass.Birthday;
import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry;
import emu.grasscutter.net.proto.HeadImageOuterClass.HeadImage; import emu.grasscutter.net.proto.HeadImageOuterClass.HeadImage;
import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
@ -35,39 +32,18 @@ import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo; 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.*;
import emu.grasscutter.server.packet.send.PacketAvatarAddNotify;
import emu.grasscutter.server.packet.send.PacketAvatarDataNotify;
import emu.grasscutter.server.packet.send.PacketAvatarGainCostumeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarGainFlycloakNotify;
import emu.grasscutter.server.packet.send.PacketClientAbilityInitFinishNotify;
import emu.grasscutter.server.packet.send.PacketCombatInvocationsNotify;
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
import emu.grasscutter.server.packet.send.PacketOpenStateUpdateNotify;
import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpResultNotify;
import emu.grasscutter.server.packet.send.PacketPlayerDataNotify;
import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify;
import emu.grasscutter.server.packet.send.PacketPlayerPropNotify;
import emu.grasscutter.server.packet.send.PacketPlayerStoreNotify;
import emu.grasscutter.server.packet.send.PacketPrivateChatNotify;
import emu.grasscutter.server.packet.send.PacketScenePlayerLocationNotify;
import emu.grasscutter.server.packet.send.PacketPlayerLevelRewardUpdateNotify;
import emu.grasscutter.server.packet.send.PacketSetNameCardRsp;
import emu.grasscutter.server.packet.send.PacketStoreWeightLimitNotify;
import emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify;
import emu.grasscutter.server.packet.send.PacketWorldPlayerLocationNotify;
import emu.grasscutter.server.packet.send.PacketWorldPlayerRTTNotify;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
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 java.util.*;
@Entity(value = "players", useDiscriminator = false) @Entity(value = "players", useDiscriminator = false)
public class GenshinPlayer { public class GenshinPlayer {
@Id private int id; @Id private int id;
@Indexed(options = @IndexOptions(unique = true)) private String accountId; @Indexed(options = @IndexOptions(unique = true)) private String accountId;
@Transient private Account account; @Transient private Account account;
private String nickname; private String nickname;
private String signature; private String signature;
@ -76,12 +52,12 @@ public class GenshinPlayer {
private Position pos; private Position pos;
private Position rotation; private Position rotation;
private PlayerBirthday birthday; private PlayerBirthday birthday;
private Map<Integer, Integer> properties; private Map<Integer, Integer> properties;
private Set<Integer> nameCardList; private Set<Integer> nameCardList;
private Set<Integer> flyCloakList; private Set<Integer> flyCloakList;
private Set<Integer> costumeList; private Set<Integer> costumeList;
@Transient private long nextGuid = 0; @Transient private long nextGuid = 0;
@Transient private int peerId; @Transient private int peerId;
@Transient private World world; @Transient private World world;
@ -90,7 +66,7 @@ public class GenshinPlayer {
@Transient private AvatarStorage avatars; @Transient private AvatarStorage avatars;
@Transient private Inventory inventory; @Transient private Inventory inventory;
@Transient private FriendsList friendsList; @Transient private FriendsList friendsList;
private TeamManager teamManager; private TeamManager teamManager;
private PlayerGachaInfo gachaInfo; private PlayerGachaInfo gachaInfo;
private PlayerProfile playerProfile; private PlayerProfile playerProfile;
@ -98,25 +74,26 @@ public class GenshinPlayer {
private boolean showAvatar; private boolean showAvatar;
private ArrayList<AvatarProfileData> shownAvatars; private ArrayList<AvatarProfileData> shownAvatars;
private Set<Integer> rewardedLevels; private Set<Integer> rewardedLevels;
private int sceneId; private int sceneId;
private int regionId; private int regionId;
private int mainCharacterId; private int mainCharacterId;
private boolean godmode; private boolean godmode;
@Transient private boolean paused; @Transient private boolean paused;
@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 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;
@Transient private final InvokeHandler<AbilityInvokeEntry> abilityInvokeHandler; @Transient private final InvokeHandler<AbilityInvokeEntry> abilityInvokeHandler;
@Transient private final InvokeHandler<AbilityInvokeEntry> clientAbilityInitFinishHandler; @Transient private final InvokeHandler<AbilityInvokeEntry> clientAbilityInitFinishHandler;
@Deprecated @SuppressWarnings({ "rawtypes", "unchecked" }) // Morphia only! @Deprecated
public GenshinPlayer() { @SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only!
public GenshinPlayer() {
this.inventory = new Inventory(this); this.inventory = new Inventory(this);
this.avatars = new AvatarStorage(this); this.avatars = new AvatarStorage(this);
this.friendsList = new FriendsList(this); this.friendsList = new FriendsList(this);
@ -129,16 +106,16 @@ public class GenshinPlayer {
} }
this.properties.put(prop.getId(), 0); this.properties.put(prop.getId(), 0);
} }
this.gachaInfo = new PlayerGachaInfo(); this.gachaInfo = new PlayerGachaInfo();
this.nameCardList = new HashSet<>(); this.nameCardList = new HashSet<>();
this.flyCloakList = new HashSet<>(); this.flyCloakList = new HashSet<>();
this.costumeList = 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;
this.coopRequests = new Int2ObjectOpenHashMap<>(); this.coopRequests = new Int2ObjectOpenHashMap<>();
this.combatInvokeHandler = new InvokeHandler(PacketCombatInvocationsNotify.class); this.combatInvokeHandler = new InvokeHandler(PacketCombatInvocationsNotify.class);
this.abilityInvokeHandler = new InvokeHandler(PacketAbilityInvocationsNotify.class); this.abilityInvokeHandler = new InvokeHandler(PacketAbilityInvocationsNotify.class);
@ -147,7 +124,7 @@ public class GenshinPlayer {
this.birthday = new PlayerBirthday(); this.birthday = new PlayerBirthday();
this.rewardedLevels = new HashSet<>(); this.rewardedLevels = new HashSet<>();
} }
// On player creation // On player creation
public GenshinPlayer(GameSession session) { public GenshinPlayer(GameSession session) {
this(); this();
@ -179,7 +156,7 @@ public class GenshinPlayer {
public void setUid(int id) { public void setUid(int id) {
this.id = id; this.id = id;
} }
public long getNextGenshinGuid() { public long getNextGenshinGuid() {
long nextId = ++this.nextGuid; long nextId = ++this.nextGuid;
return ((long) this.getUid() << 32) + nextId; return ((long) this.getUid() << 32) + nextId;
@ -201,23 +178,23 @@ public class GenshinPlayer {
public void setSession(GameSession session) { public void setSession(GameSession session) {
this.session = session; this.session = session;
} }
public boolean isOnline() { public boolean isOnline() {
return this.getSession() != null && this.getSession().isActive(); return this.getSession() != null && this.getSession().isActive();
} }
public GameServer getServer() { public GameServer getServer() {
return this.getSession().getServer(); return this.getSession().getServer();
} }
public synchronized World getWorld() { public synchronized World getWorld() {
return this.world; return this.world;
} }
public synchronized void setWorld(World world) { public synchronized void setWorld(World world) {
this.world = world; this.world = world;
} }
public GenshinScene getScene() { public GenshinScene getScene() {
return scene; return scene;
} }
@ -238,7 +215,7 @@ public class GenshinPlayer {
this.nickname = nickName; this.nickname = nickName;
this.updateProfile(); this.updateProfile();
} }
public int getHeadImage() { public int getHeadImage() {
return headImage; return headImage;
} }
@ -260,71 +237,71 @@ public class GenshinPlayer {
public Position getPos() { public Position getPos() {
return pos; return pos;
} }
public Position getRotation() { public Position getRotation() {
return rotation; return rotation;
} }
public int getLevel() { public int getLevel() {
return this.getProperty(PlayerProperty.PROP_PLAYER_LEVEL); return this.getProperty(PlayerProperty.PROP_PLAYER_LEVEL);
} }
public int getExp() { public int getExp() {
return this.getProperty(PlayerProperty.PROP_PLAYER_EXP); return this.getProperty(PlayerProperty.PROP_PLAYER_EXP);
} }
public int getWorldLevel() { public int getWorldLevel() {
return this.getProperty(PlayerProperty.PROP_PLAYER_WORLD_LEVEL); return this.getProperty(PlayerProperty.PROP_PLAYER_WORLD_LEVEL);
} }
public int getPrimogems() { public int getPrimogems() {
return this.getProperty(PlayerProperty.PROP_PLAYER_HCOIN); return this.getProperty(PlayerProperty.PROP_PLAYER_HCOIN);
} }
public void setPrimogems(int primogem) { public void setPrimogems(int primogem) {
this.setProperty(PlayerProperty.PROP_PLAYER_HCOIN, primogem); this.setProperty(PlayerProperty.PROP_PLAYER_HCOIN, primogem);
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_HCOIN)); this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_HCOIN));
} }
public int getMora() { public int getMora() {
return this.getProperty(PlayerProperty.PROP_PLAYER_SCOIN); return this.getProperty(PlayerProperty.PROP_PLAYER_SCOIN);
} }
public void setMora(int mora) { public void setMora(int mora) {
this.setProperty(PlayerProperty.PROP_PLAYER_SCOIN, mora); this.setProperty(PlayerProperty.PROP_PLAYER_SCOIN, mora);
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_SCOIN)); this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_SCOIN));
} }
private int getExpRequired(int level) { private int getExpRequired(int level) {
PlayerLevelData levelData = GenshinData.getPlayerLevelDataMap().get(level); PlayerLevelData levelData = GenshinData.getPlayerLevelDataMap().get(level);
return levelData != null ? levelData.getExp() : 0; return levelData != null ? levelData.getExp() : 0;
} }
private float getExpModifier() { private float getExpModifier() {
return Grasscutter.getConfig().getGameServerOptions().getGameRates().ADVENTURE_EXP_RATE; return Grasscutter.getConfig().getGameServerOptions().getGameRates().ADVENTURE_EXP_RATE;
} }
// Affected by exp rate // Affected by exp rate
public void earnExp(int exp) { public void earnExp(int exp) {
addExpDirectly((int) (exp * getExpModifier())); addExpDirectly((int) (exp * getExpModifier()));
} }
// Directly give player exp // Directly give player exp
public void addExpDirectly(int gain) { public void addExpDirectly(int gain) {
boolean hasLeveledUp = false; boolean hasLeveledUp = false;
int level = getLevel(); int level = getLevel();
int exp = getExp(); int exp = getExp();
int reqExp = getExpRequired(level); int reqExp = getExpRequired(level);
exp += gain; exp += gain;
while (exp >= reqExp && reqExp > 0) { while (exp >= reqExp && reqExp > 0) {
exp -= reqExp; exp -= reqExp;
level += 1; level += 1;
reqExp = getExpRequired(level); reqExp = getExpRequired(level);
hasLeveledUp = true; hasLeveledUp = true;
} }
if (hasLeveledUp) { if (hasLeveledUp) {
// Set level property // Set level property
this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, level); this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, level);
@ -333,18 +310,18 @@ public class GenshinPlayer {
// Update player with packet // Update player with packet
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_LEVEL)); this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_LEVEL));
} }
// Set exp // Set exp
this.setProperty(PlayerProperty.PROP_PLAYER_EXP, exp); this.setProperty(PlayerProperty.PROP_PLAYER_EXP, exp);
// Update player with packet // Update player with packet
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_EXP)); this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_EXP));
} }
private void updateProfile() { private void updateProfile() {
getProfile().syncWithCharacter(this); getProfile().syncWithCharacter(this);
} }
public boolean isFirstLoginEnterScene() { public boolean isFirstLoginEnterScene() {
return !this.hasSentAvatarDataNotify; return !this.hasSentAvatarDataNotify;
} }
@ -367,11 +344,11 @@ public class GenshinPlayer {
public Map<Integer, Integer> getProperties() { public Map<Integer, Integer> getProperties() {
return properties; return properties;
} }
public void setProperty(PlayerProperty prop, int value) { public void setProperty(PlayerProperty prop, int value) {
getProperties().put(prop.getId(), value); getProperties().put(prop.getId(), value);
} }
public int getProperty(PlayerProperty prop) { public int getProperty(PlayerProperty prop) {
return getProperties().get(prop.getId()); return getProperties().get(prop.getId());
} }
@ -379,11 +356,11 @@ public class GenshinPlayer {
public Set<Integer> getFlyCloakList() { public Set<Integer> getFlyCloakList() {
return flyCloakList; return flyCloakList;
} }
public Set<Integer> getCostumeList() { public Set<Integer> getCostumeList() {
return costumeList; return costumeList;
} }
public Set<Integer> getNameCardList() { public Set<Integer> getNameCardList() {
return this.nameCardList; return this.nameCardList;
} }
@ -391,7 +368,7 @@ public class GenshinPlayer {
public MpSettingType getMpSetting() { public MpSettingType getMpSetting() {
return mpSetting; return mpSetting;
} }
public synchronized Int2ObjectMap<CoopRequest> getCoopRequests() { public synchronized Int2ObjectMap<CoopRequest> getCoopRequests() {
return coopRequests; return coopRequests;
} }
@ -399,7 +376,7 @@ public class GenshinPlayer {
public InvokeHandler<CombatInvokeEntry> getCombatInvokeHandler() { public InvokeHandler<CombatInvokeEntry> getCombatInvokeHandler() {
return this.combatInvokeHandler; return this.combatInvokeHandler;
} }
public InvokeHandler<AbilityInvokeEntry> getAbilityInvokeHandler() { public InvokeHandler<AbilityInvokeEntry> getAbilityInvokeHandler() {
return this.abilityInvokeHandler; return this.abilityInvokeHandler;
} }
@ -415,11 +392,11 @@ public class GenshinPlayer {
public AvatarStorage getAvatars() { public AvatarStorage getAvatars() {
return avatars; return avatars;
} }
public Inventory getInventory() { public Inventory getInventory() {
return inventory; return inventory;
} }
public FriendsList getFriendsList() { public FriendsList getFriendsList() {
return this.friendsList; return this.friendsList;
} }
@ -472,7 +449,7 @@ public class GenshinPlayer {
public void setPaused(boolean newPauseState) { public void setPaused(boolean newPauseState) {
boolean oldPauseState = this.paused; boolean oldPauseState = this.paused;
this.paused = newPauseState; this.paused = newPauseState;
if (newPauseState && !oldPauseState) { if (newPauseState && !oldPauseState) {
this.onPause(); this.onPause();
} else if (oldPauseState && !newPauseState) { } else if (oldPauseState && !newPauseState) {
@ -487,7 +464,7 @@ public class GenshinPlayer {
public void setSceneLoadState(SceneLoadState sceneState) { public void setSceneLoadState(SceneLoadState sceneState) {
this.sceneState = sceneState; this.sceneState = sceneState;
} }
public boolean isInMultiplayer() { public boolean isInMultiplayer() {
return this.getWorld() != null && this.getWorld().isMultiplayer(); return this.getWorld() != null && this.getWorld().isMultiplayer();
} }
@ -507,7 +484,7 @@ public class GenshinPlayer {
public void setRegionId(int regionId) { public void setRegionId(int regionId) {
this.regionId = regionId; this.regionId = regionId;
} }
public boolean inGodmode() { public boolean inGodmode() {
return godmode; return godmode;
} }
@ -526,11 +503,11 @@ public class GenshinPlayer {
public void addAvatar(GenshinAvatar avatar) { public void addAvatar(GenshinAvatar avatar) {
boolean result = getAvatars().addAvatar(avatar); boolean result = getAvatars().addAvatar(avatar);
if (result) { if (result) {
// Add starting weapon // Add starting weapon
getAvatars().addStartingWeapon(avatar); getAvatars().addStartingWeapon(avatar);
// Try adding to team if possible // Try adding to team if possible
//List<EntityAvatar> currentTeam = this.getTeamManager().getCurrentTeam(); //List<EntityAvatar> currentTeam = this.getTeamManager().getCurrentTeam();
boolean addedToTeam = false; boolean addedToTeam = false;
@ -540,7 +517,7 @@ public class GenshinPlayer {
addedToTeam = currentTeam addedToTeam = currentTeam
} }
*/ */
// Done // Done
if (hasSentAvatarDataNotify()) { if (hasSentAvatarDataNotify()) {
// Recalc stats // Recalc stats
@ -552,55 +529,56 @@ public class GenshinPlayer {
// Failed adding avatar // Failed adding avatar
} }
} }
public void addFlycloak(int flycloakId) { public void addFlycloak(int flycloakId) {
this.getFlyCloakList().add(flycloakId); this.getFlyCloakList().add(flycloakId);
this.sendPacket(new PacketAvatarGainFlycloakNotify(flycloakId)); this.sendPacket(new PacketAvatarGainFlycloakNotify(flycloakId));
} }
public void addCostume(int costumeId) { public void addCostume(int costumeId) {
this.getCostumeList().add(costumeId); this.getCostumeList().add(costumeId);
this.sendPacket(new PacketAvatarGainCostumeNotify(costumeId)); this.sendPacket(new PacketAvatarGainCostumeNotify(costumeId));
} }
public void addNameCard(int nameCardId) { public void addNameCard(int nameCardId) {
this.getNameCardList().add(nameCardId); this.getNameCardList().add(nameCardId);
this.sendPacket(new PacketUnlockNameCardNotify(nameCardId)); this.sendPacket(new PacketUnlockNameCardNotify(nameCardId));
} }
public void setNameCard(int nameCardId) { public void setNameCard(int nameCardId) {
if (!this.getNameCardList().contains(nameCardId)) { if (!this.getNameCardList().contains(nameCardId)) {
return; return;
} }
this.setNameCardId(nameCardId); this.setNameCardId(nameCardId);
this.sendPacket(new PacketSetNameCardRsp(nameCardId)); this.sendPacket(new PacketSetNameCardRsp(nameCardId));
} }
public void dropMessage(Object message) { public void dropMessage(Object message) {
this.sendPacket(new PacketPrivateChatNotify(GenshinConstants.SERVER_CONSOLE_UID, getUid(), message.toString())); this.sendPacket(new PacketPrivateChatNotify(GenshinConstants.SERVER_CONSOLE_UID, getUid(), message.toString()));
} }
/** /**
* Sends a message to another player. * Sends a message to another player.
* @param sender The sender of the message. *
* @param sender The sender of the message.
* @param message The message to send. * @param message The message to send.
*/ */
public void sendMessage(GenshinPlayer sender, Object message) { public void sendMessage(GenshinPlayer sender, Object message) {
this.sendPacket(new PacketPrivateChatNotify(sender.getUid(), this.getUid(), message.toString())); this.sendPacket(new PacketPrivateChatNotify(sender.getUid(), this.getUid(), message.toString()));
} }
public void interactWith(int gadgetEntityId) { public void interactWith(int gadgetEntityId) {
GenshinEntity entity = getScene().getEntityById(gadgetEntityId); GenshinEntity entity = getScene().getEntityById(gadgetEntityId);
if (entity == null) { if (entity == null) {
return; return;
} }
// Delete // Delete
entity.getScene().removeEntity(entity); entity.getScene().removeEntity(entity);
// Handle // Handle
if (entity instanceof EntityItem) { if (entity instanceof EntityItem) {
// Pick item // Pick item
@ -613,44 +591,44 @@ public class GenshinPlayer {
this.sendPacket(new PacketItemAddHintNotify(item, ActionReason.SubfieldDrop)); this.sendPacket(new PacketItemAddHintNotify(item, ActionReason.SubfieldDrop));
} }
} }
return; return;
} }
public void onPause() { public void onPause() {
} }
public void onUnpause() { public void onUnpause() {
} }
public void sendPacket(GenshinPacket packet) { public void sendPacket(GenshinPacket packet) {
if (this.hasSentAvatarDataNotify) { if (this.hasSentAvatarDataNotify) {
this.getSession().send(packet); this.getSession().send(packet);
} }
} }
public OnlinePlayerInfo getOnlinePlayerInfo() { public OnlinePlayerInfo getOnlinePlayerInfo() {
OnlinePlayerInfo.Builder onlineInfo = OnlinePlayerInfo.newBuilder() OnlinePlayerInfo.Builder onlineInfo = OnlinePlayerInfo.newBuilder()
.setUid(this.getUid()) .setUid(this.getUid())
.setNickname(this.getNickname()) .setNickname(this.getNickname())
.setPlayerLevel(this.getLevel()) .setPlayerLevel(this.getLevel())
.setMpSettingType(this.getMpSetting()) .setMpSettingType(this.getMpSetting())
.setNameCardId(this.getNameCardId()) .setNameCardId(this.getNameCardId())
.setSignature(this.getSignature()) .setSignature(this.getSignature())
.setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage())); .setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage()));
if (this.getWorld() != null) { if (this.getWorld() != null) {
onlineInfo.setCurPlayerNumInWorld(this.getWorld().getPlayers().indexOf(this) + 1); onlineInfo.setCurPlayerNumInWorld(this.getWorld().getPlayers().indexOf(this) + 1);
} else { } else {
onlineInfo.setCurPlayerNumInWorld(1); onlineInfo.setCurPlayerNumInWorld(1);
} }
return onlineInfo.build(); return onlineInfo.build();
} }
public PlayerBirthday getBirthday(){ public PlayerBirthday getBirthday() {
return this.birthday; return this.birthday;
} }
@ -659,6 +637,10 @@ public class GenshinPlayer {
this.updateProfile(); this.updateProfile();
} }
public boolean hasBirthday() {
return this.birthday.getDay() > 0;
}
public Set<Integer> getRewardedLevels() { public Set<Integer> getRewardedLevels() {
return rewardedLevels; return rewardedLevels;
} }
@ -668,36 +650,18 @@ public class GenshinPlayer {
} }
public SocialDetail.Builder getSocialDetail() { public SocialDetail.Builder getSocialDetail() {
SocialDetail.Builder social = SocialDetail.newBuilder() SocialDetail.Builder social = SocialDetail.newBuilder().setUid(this.getUid()).setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage())).setNickname(this.getNickname()).setSignature(this.getSignature()).setLevel(this.getLevel()).setBirthday(this.getBirthday().getFilledProtoWhenNotEmpty()).setWorldLevel(this.getWorldLevel()).setUnk1(1).setUnk3(1).setNameCardId(this.getNameCardId()).setFinishAchievementNum(0);
.setUid(this.getUid())
.setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage()))
.setNickname(this.getNickname())
.setSignature(this.getSignature())
.setLevel(this.getLevel())
.setBirthday(this.getBirthday().getFilledProtoWhenNotEmpty())
.setWorldLevel(this.getWorldLevel())
.setUnk1(1)
.setUnk3(1)
.setNameCardId(this.getNameCardId())
.setFinishAchievementNum(0);
return social; return social;
} }
public WorldPlayerLocationInfo getWorldPlayerLocationInfo() { public WorldPlayerLocationInfo getWorldPlayerLocationInfo() {
return WorldPlayerLocationInfo.newBuilder() return WorldPlayerLocationInfo.newBuilder().setSceneId(this.getSceneId()).setPlayerLoc(this.getPlayerLocationInfo()).build();
.setSceneId(this.getSceneId())
.setPlayerLoc(this.getPlayerLocationInfo())
.build();
} }
public PlayerLocationInfo getPlayerLocationInfo() { public PlayerLocationInfo getPlayerLocationInfo() {
return PlayerLocationInfo.newBuilder() return PlayerLocationInfo.newBuilder().setUid(this.getUid()).setPos(this.getPos().toProto()).setRot(this.getRotation().toProto()).build();
.setUid(this.getUid())
.setPos(this.getPos().toProto())
.setRot(this.getRotation().toProto())
.build();
} }
public synchronized void onTick() { public synchronized void onTick() {
// Check ping // Check ping
if (this.getLastPingTime() > System.currentTimeMillis() + 60000) { if (this.getLastPingTime() > System.currentTimeMillis() + 60000) {
@ -717,7 +681,7 @@ public class GenshinPlayer {
if (this.getWorld() != null) { if (this.getWorld() != null) {
// RTT notify - very important to send this often // RTT notify - very important to send this often
this.sendPacket(new PacketWorldPlayerRTTNotify(this.getWorld())); this.sendPacket(new PacketWorldPlayerRTTNotify(this.getWorld()));
// Update player locations if in multiplayer every 5 seconds // Update player locations if in multiplayer every 5 seconds
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
if (this.getWorld().isMultiplayer() && this.getScene() != null && time > nextSendPlayerLocTime) { if (this.getWorld().isMultiplayer() && this.getScene() != null && time > nextSendPlayerLocTime) {
@ -727,7 +691,7 @@ public class GenshinPlayer {
} }
} }
} }
public void resetSendPlayerLocTime() { public void resetSendPlayerLocTime() {
this.nextSendPlayerLocTime = System.currentTimeMillis() + 5000; this.nextSendPlayerLocTime = System.currentTimeMillis() + 5000;
} }
@ -736,7 +700,7 @@ public class GenshinPlayer {
private void onLoad() { private void onLoad() {
this.getTeamManager().setPlayer(this); this.getTeamManager().setPlayer(this);
} }
public void save() { public void save() {
DatabaseHelper.savePlayer(this); DatabaseHelper.savePlayer(this);
} }
@ -745,44 +709,45 @@ 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.getProfile().getUid() == 0) { }
if (this.getProfile().getUid() == 0) {
this.getProfile().syncWithCharacter(this); this.getProfile().syncWithCharacter(this);
} }
// Check if player object exists in server // Check if player object exists in server
// TODO - optimize // TODO - optimize
GenshinPlayer exists = this.getServer().getPlayerByUid(getUid()); GenshinPlayer exists = this.getServer().getPlayerByUid(getUid());
if (exists != null) { if (exists != null) {
exists.getSession().close(); exists.getSession().close();
} }
// Load from db // Load from db
this.getAvatars().loadFromDatabase(); this.getAvatars().loadFromDatabase();
this.getInventory().loadFromDatabase(); this.getInventory().loadFromDatabase();
this.getAvatars().postLoad(); this.getAvatars().postLoad();
this.getFriendsList().loadFromDatabase(); this.getFriendsList().loadFromDatabase();
// Create world // Create world
World world = new World(this); World world = new World(this);
world.addPlayer(this); world.addPlayer(this);
// Add to gameserver // Add to gameserver
if (getSession().isActive()) { if (getSession().isActive()) {
getServer().registerPlayer(this); getServer().registerPlayer(this);
getProfile().setPlayer(this); // Set online getProfile().setPlayer(this); // Set online
} }
// Multiplayer setting // Multiplayer setting
this.setProperty(PlayerProperty.PROP_PLAYER_MP_SETTING_TYPE, this.getMpSetting().getNumber()); this.setProperty(PlayerProperty.PROP_PLAYER_MP_SETTING_TYPE, this.getMpSetting().getNumber());
this.setProperty(PlayerProperty.PROP_IS_MP_MODE_AVAILABLE, 1); this.setProperty(PlayerProperty.PROP_IS_MP_MODE_AVAILABLE, 1);
// Packets // Packets
session.send(new PacketPlayerDataNotify(this)); // Player data session.send(new PacketPlayerDataNotify(this)); // Player data
session.send(new PacketStoreWeightLimitNotify()); session.send(new PacketStoreWeightLimitNotify());
session.send(new PacketPlayerStoreNotify(this)); session.send(new PacketPlayerStoreNotify(this));
session.send(new PacketAvatarDataNotify(this)); session.send(new PacketAvatarDataNotify(this));
session.send(new PacketPlayerEnterSceneNotify(this)); // Enter game world session.send(new PacketPlayerEnterSceneNotify(this)); // Enter game world
session.send(new PacketPlayerLevelRewardUpdateNotify(rewardedLevels)); session.send(new PacketPlayerLevelRewardUpdateNotify(rewardedLevels));
session.send(new PacketOpenStateUpdateNotify()); session.send(new PacketOpenStateUpdateNotify());
@ -790,34 +755,34 @@ public class GenshinPlayer {
// First notify packets sent // First notify packets sent
this.setHasSentAvatarDataNotify(true); this.setHasSentAvatarDataNotify(true);
} }
public void onLogout() { public void onLogout() {
// Leave world // Leave world
if (this.getWorld() != null) { if (this.getWorld() != null) {
this.getWorld().removePlayer(this); this.getWorld().removePlayer(this);
} }
// Status stuff // Status stuff
this.getProfile().syncWithCharacter(this); this.getProfile().syncWithCharacter(this);
this.getProfile().setPlayer(null); // Set offline this.getProfile().setPlayer(null); // Set offline
this.getCoopRequests().clear(); this.getCoopRequests().clear();
// Save to db // Save to db
this.save(); this.save();
this.getTeamManager().saveAvatars(); this.getTeamManager().saveAvatars();
this.getFriendsList().save(); this.getFriendsList().save();
} }
public enum SceneLoadState { public enum SceneLoadState {
NONE (0), LOADING (1), INIT (2), LOADED (3); NONE(0), LOADING(1), INIT(2), LOADED(3);
private final int value; private final int value;
private SceneLoadState(int value) { private SceneLoadState(int value) {
this.value = value; this.value = value;
} }
public int getValue() { public int getValue() {
return this.value; return this.value;
} }

View File

@ -11,23 +11,57 @@ import emu.grasscutter.server.packet.send.PacketSetPlayerBirthdayRsp;
@Opcodes(PacketOpcodes.SetPlayerBirthdayReq) @Opcodes(PacketOpcodes.SetPlayerBirthdayReq)
public class HandlerSetPlayerBirthdayReq extends PacketHandler { public class HandlerSetPlayerBirthdayReq 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 {
SetPlayerBirthdayReq req = SetPlayerBirthdayReq.parseFrom(payload); SetPlayerBirthdayReq req = SetPlayerBirthdayReq.parseFrom(payload);
if (req.getBirthday().getDay() > 0 && req.getBirthday().getMonth() > 0) { // RET_BIRTHDAY_CANNOT_BE_SET_TWICE = 7009
int day = req.getBirthday().getDay(); if (session.getPlayer().hasBirthday()) {
int month = req.getBirthday().getMonth(); session.send(new PacketSetPlayerBirthdayRsp(7009));
return;
}
// Update birthday value int month = req.getBirthday().getMonth();
session.getPlayer().setBirthday(day, month); int day = req.getBirthday().getDay();
// Save birthday month and day // RET_BIRTHDAY_FORMAT_ERROR = 7022
session.getPlayer().save(); if (!isValidBirthday(month, day)) {
SocialDetail.Builder detail = session.getPlayer().getSocialDetail(); session.send(new PacketSetPlayerBirthdayRsp(7022));
return;
}
// Update birthday value
session.getPlayer().setBirthday(day, month);
// Save birthday month and day
session.getPlayer().save();
SocialDetail.Builder detail = session.getPlayer().getSocialDetail();
session.send(new PacketSetPlayerBirthdayRsp(session.getPlayer()));
session.send(new PacketGetPlayerSocialDetailRsp(detail));
}
private boolean isValidBirthday(int month, int day) {
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return day > 0 & day <= 31;
case 4:
case 6:
case 9:
case 11:
return day > 0 && day <= 30;
case 2:
return day > 0 & day <= 29;
}
return false;
}
session.send(new PacketSetPlayerBirthdayRsp(session.getPlayer()));
session.send(new PacketGetPlayerSocialDetailRsp(detail));
}
}
} }

View File

@ -6,13 +6,24 @@ import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.SetPlayerBirthdayRspOuterClass.SetPlayerBirthdayRsp; import emu.grasscutter.net.proto.SetPlayerBirthdayRspOuterClass.SetPlayerBirthdayRsp;
public class PacketSetPlayerBirthdayRsp extends GenshinPacket { public class PacketSetPlayerBirthdayRsp extends GenshinPacket {
public PacketSetPlayerBirthdayRsp(GenshinPlayer player) {
super(PacketOpcodes.SetPlayerBirthdayRsp);
SetPlayerBirthdayRsp proto = SetPlayerBirthdayRsp.newBuilder() public PacketSetPlayerBirthdayRsp(int retCode) {
.setBirthday(player.getBirthday().toProto()) super(PacketOpcodes.SetPlayerBirthdayRsp);
.build();
this.setData(proto); SetPlayerBirthdayRsp proto = SetPlayerBirthdayRsp.newBuilder()
} .setRetcode(retCode)
.build();
this.setData(proto);
}
public PacketSetPlayerBirthdayRsp(GenshinPlayer player) {
super(PacketOpcodes.SetPlayerBirthdayRsp);
SetPlayerBirthdayRsp proto = SetPlayerBirthdayRsp.newBuilder()
.setBirthday(player.getBirthday().toProto())
.build();
this.setData(proto);
}
} }