Grasscutter/src/main/java/emu/grasscutter/game/GenshinPlayer.java

880 lines
24 KiB
Java
Raw Normal View History

2022-04-17 05:43:07 -07:00
package emu.grasscutter.game;
2022-04-25 14:30:56 +08:00
import java.time.Instant;
import java.util.*;
2022-04-17 05:43:07 -07:00
import dev.morphia.annotations.*;
import emu.grasscutter.GenshinConstants;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.def.PlayerLevelData;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.avatar.AvatarProfileData;
import emu.grasscutter.game.avatar.AvatarStorage;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.entity.EntityItem;
import emu.grasscutter.game.entity.GenshinEntity;
import emu.grasscutter.game.friends.FriendsList;
import emu.grasscutter.game.friends.PlayerProfile;
import emu.grasscutter.game.gacha.PlayerGachaInfo;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.Inventory;
2022-04-23 03:22:32 +02:00
import emu.grasscutter.game.player.PlayerBirthday;
2022-04-17 05:43:07 -07:00
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry;
import emu.grasscutter.net.proto.HeadImageOuterClass.HeadImage;
import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
import emu.grasscutter.net.proto.MpSettingTypeOuterClass.MpSettingType;
import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason;
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
2022-04-20 18:44:02 -07:00
import emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo;
2022-04-17 05:43:07 -07:00
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketAbilityInvocationsNotify;
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;
2022-04-17 05:43:07 -07:00
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;
2022-04-20 18:44:02 -07:00
import emu.grasscutter.server.packet.send.PacketScenePlayerLocationNotify;
import emu.grasscutter.server.packet.send.PacketPlayerLevelRewardUpdateNotify;
2022-04-17 05:43:07 -07:00
import emu.grasscutter.server.packet.send.PacketSetNameCardRsp;
import emu.grasscutter.server.packet.send.PacketStoreWeightLimitNotify;
import emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify;
2022-04-20 18:44:02 -07:00
import emu.grasscutter.server.packet.send.PacketWorldPlayerLocationNotify;
2022-04-17 05:43:07 -07:00
import emu.grasscutter.server.packet.send.PacketWorldPlayerRTTNotify;
import emu.grasscutter.server.packet.send.PacketMailChangeNotify;
2022-04-17 05:43:07 -07:00
import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
2022-04-25 14:51:34 +08:00
import java.util.*;
2022-04-20 21:11:57 -04:00
@Entity(value = "players", useDiscriminator = false)
2022-04-17 05:43:07 -07:00
public class GenshinPlayer {
@Id private int id;
@Indexed(options = @IndexOptions(unique = true)) private String accountId;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
@Transient private Account account;
private String nickname;
private String signature;
private int headImage;
private int nameCardId = 210001;
private Position pos;
private Position rotation;
2022-04-23 03:22:32 +02:00
private PlayerBirthday birthday;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
private Map<Integer, Integer> properties;
private Set<Integer> nameCardList;
private Set<Integer> flyCloakList;
private Set<Integer> costumeList;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
@Transient private long nextGuid = 0;
@Transient private int peerId;
@Transient private World world;
@Transient private GenshinScene scene;
2022-04-17 05:43:07 -07:00
@Transient private GameSession session;
@Transient private AvatarStorage avatars;
@Transient private Inventory inventory;
@Transient private FriendsList friendsList;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
private TeamManager teamManager;
private PlayerGachaInfo gachaInfo;
private PlayerProfile playerProfile;
private MpSettingType mpSetting = MpSettingType.MpSettingEnterAfterApply;
private boolean showAvatar;
private ArrayList<AvatarProfileData> shownAvatars;
private Set<Integer> rewardedLevels;
private ArrayList<Mail> mail;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
private int sceneId;
private int regionId;
private int mainCharacterId;
private boolean godmode;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
@Transient private boolean paused;
@Transient private int enterSceneToken;
@Transient private SceneLoadState sceneState;
@Transient private boolean hasSentAvatarDataNotify;
2022-04-20 18:44:02 -07:00
@Transient private long nextSendPlayerLocTime = 0;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
@Transient private final Int2ObjectMap<CoopRequest> coopRequests;
@Transient private final InvokeHandler<CombatInvokeEntry> combatInvokeHandler;
@Transient private final InvokeHandler<AbilityInvokeEntry> abilityInvokeHandler;
@Transient private final InvokeHandler<AbilityInvokeEntry> clientAbilityInitFinishHandler;
2022-04-25 14:51:34 +08:00
@Deprecated
@SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only!
public GenshinPlayer() {
2022-04-17 05:43:07 -07:00
this.inventory = new Inventory(this);
this.avatars = new AvatarStorage(this);
this.friendsList = new FriendsList(this);
this.pos = new Position();
this.rotation = new Position();
this.properties = new HashMap<>();
for (PlayerProperty prop : PlayerProperty.values()) {
if (prop.getId() < 10000) {
continue;
}
this.properties.put(prop.getId(), 0);
}
2022-04-25 14:51:34 +08:00
this.gachaInfo = new PlayerGachaInfo();
this.nameCardList = new HashSet<>();
this.flyCloakList = new HashSet<>();
this.costumeList = new HashSet<>();
2022-04-25 14:51:34 +08:00
this.mail = new ArrayList<>();
2022-04-17 05:43:07 -07:00
this.setSceneId(3);
this.setRegionId(1);
this.sceneState = SceneLoadState.NONE;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
this.coopRequests = new Int2ObjectOpenHashMap<>();
this.combatInvokeHandler = new InvokeHandler(PacketCombatInvocationsNotify.class);
this.abilityInvokeHandler = new InvokeHandler(PacketAbilityInvocationsNotify.class);
this.clientAbilityInitFinishHandler = new InvokeHandler(PacketClientAbilityInitFinishNotify.class);
2022-04-23 03:22:32 +02:00
this.birthday = new PlayerBirthday();
this.rewardedLevels = new HashSet<>();
2022-04-17 05:43:07 -07:00
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// On player creation
public GenshinPlayer(GameSession session) {
this();
this.account = session.getAccount();
this.accountId = this.getAccount().getId();
this.session = session;
this.nickname = "Traveler";
this.signature = "";
this.teamManager = new TeamManager(this);
2022-04-23 03:22:32 +02:00
this.birthday = new PlayerBirthday();
2022-04-17 05:43:07 -07:00
this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, 1);
this.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, 1);
this.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, 50);
this.setProperty(PlayerProperty.PROP_IS_FLYABLE, 1);
this.setProperty(PlayerProperty.PROP_IS_TRANSFERABLE, 1);
this.setProperty(PlayerProperty.PROP_MAX_STAMINA, 24000);
this.setProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA, 24000);
this.setProperty(PlayerProperty.PROP_PLAYER_RESIN, 160);
this.getFlyCloakList().add(140001);
this.getNameCardList().add(210001);
this.getPos().set(GenshinConstants.START_POSITION);
this.getRotation().set(0, 307, 0);
}
public int getUid() {
2022-04-17 05:43:07 -07:00
return id;
}
public void setUid(int id) {
2022-04-17 05:43:07 -07:00
this.id = id;
}
2022-04-25 14:51:34 +08:00
public long getNextGenshinGuid() {
2022-04-17 05:43:07 -07:00
long nextId = ++this.nextGuid;
return ((long) this.getUid() << 32) + nextId;
2022-04-17 05:43:07 -07:00
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
this.account.setPlayerId(getUid());
2022-04-17 05:43:07 -07:00
}
public GameSession getSession() {
return session;
}
public void setSession(GameSession session) {
this.session = session;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public boolean isOnline() {
return this.getSession() != null && this.getSession().isActive();
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public GameServer getServer() {
return this.getSession().getServer();
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public synchronized World getWorld() {
return this.world;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public synchronized void setWorld(World world) {
this.world = world;
}
2022-04-25 14:51:34 +08:00
public GenshinScene getScene() {
return scene;
}
public void setScene(GenshinScene scene) {
this.scene = scene;
}
2022-04-17 05:43:07 -07:00
public int getGmLevel() {
return 1;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickName) {
this.nickname = nickName;
this.updateProfile();
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public int getHeadImage() {
return headImage;
}
public void setHeadImage(int picture) {
this.headImage = picture;
this.updateProfile();
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
this.updateProfile();
}
public Position getPos() {
return pos;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public Position getRotation() {
return rotation;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public int getLevel() {
return this.getProperty(PlayerProperty.PROP_PLAYER_LEVEL);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public int getExp() {
return this.getProperty(PlayerProperty.PROP_PLAYER_EXP);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public int getWorldLevel() {
return this.getProperty(PlayerProperty.PROP_PLAYER_WORLD_LEVEL);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public int getPrimogems() {
return this.getProperty(PlayerProperty.PROP_PLAYER_HCOIN);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void setPrimogems(int primogem) {
this.setProperty(PlayerProperty.PROP_PLAYER_HCOIN, primogem);
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_HCOIN));
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public int getMora() {
return this.getProperty(PlayerProperty.PROP_PLAYER_SCOIN);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void setMora(int mora) {
this.setProperty(PlayerProperty.PROP_PLAYER_SCOIN, mora);
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_SCOIN));
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
private int getExpRequired(int level) {
PlayerLevelData levelData = GenshinData.getPlayerLevelDataMap().get(level);
2022-04-25 14:51:34 +08:00
return levelData != null ? levelData.getExp() : 0;
2022-04-17 05:43:07 -07:00
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
private float getExpModifier() {
return Grasscutter.getConfig().getGameServerOptions().getGameRates().ADVENTURE_EXP_RATE;
2022-04-17 05:43:07 -07:00
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Affected by exp rate
public void earnExp(int exp) {
addExpDirectly((int) (exp * getExpModifier()));
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Directly give player exp
public void addExpDirectly(int gain) {
boolean hasLeveledUp = false;
int level = getLevel();
int exp = getExp();
int reqExp = getExpRequired(level);
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
exp += gain;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
while (exp >= reqExp && reqExp > 0) {
exp -= reqExp;
level += 1;
reqExp = getExpRequired(level);
hasLeveledUp = true;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
if (hasLeveledUp) {
// Set level property
this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, level);
// Update social status
this.updateProfile();
// Update player with packet
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_LEVEL));
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Set exp
this.setProperty(PlayerProperty.PROP_PLAYER_EXP, exp);
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Update player with packet
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_EXP));
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
private void updateProfile() {
getProfile().syncWithCharacter(this);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public boolean isFirstLoginEnterScene() {
return !this.hasSentAvatarDataNotify;
}
public TeamManager getTeamManager() {
return this.teamManager;
}
public PlayerGachaInfo getGachaInfo() {
return gachaInfo;
}
public PlayerProfile getProfile() {
if (this.playerProfile == null) {
this.playerProfile = new PlayerProfile(this);
}
return playerProfile;
}
public Map<Integer, Integer> getProperties() {
return properties;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void setProperty(PlayerProperty prop, int value) {
getProperties().put(prop.getId(), value);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public int getProperty(PlayerProperty prop) {
return getProperties().get(prop.getId());
}
public Set<Integer> getFlyCloakList() {
return flyCloakList;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public Set<Integer> getCostumeList() {
return costumeList;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public Set<Integer> getNameCardList() {
return this.nameCardList;
}
public MpSettingType getMpSetting() {
return mpSetting;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public synchronized Int2ObjectMap<CoopRequest> getCoopRequests() {
return coopRequests;
}
public InvokeHandler<CombatInvokeEntry> getCombatInvokeHandler() {
return this.combatInvokeHandler;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public InvokeHandler<AbilityInvokeEntry> getAbilityInvokeHandler() {
return this.abilityInvokeHandler;
}
public InvokeHandler<AbilityInvokeEntry> getClientAbilityInitFinishHandler() {
return clientAbilityInitFinishHandler;
}
2022-04-17 05:43:07 -07:00
public void setMpSetting(MpSettingType mpSetting) {
this.mpSetting = mpSetting;
}
public AvatarStorage getAvatars() {
return avatars;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public Inventory getInventory() {
return inventory;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public FriendsList getFriendsList() {
return this.friendsList;
}
public int getEnterSceneToken() {
return enterSceneToken;
}
public void setEnterSceneToken(int enterSceneToken) {
this.enterSceneToken = enterSceneToken;
}
public int getNameCardId() {
return nameCardId;
}
public void setNameCardId(int nameCardId) {
this.nameCardId = nameCardId;
this.updateProfile();
}
public int getMainCharacterId() {
return mainCharacterId;
}
public void setMainCharacterId(int mainCharacterId) {
this.mainCharacterId = mainCharacterId;
}
public int getPeerId() {
return peerId;
}
public void setPeerId(int peerId) {
this.peerId = peerId;
}
public int getClientTime() {
return session.getClientTime();
}
public long getLastPingTime() {
return session.getLastPingTime();
}
public boolean isPaused() {
return paused;
}
public void setPaused(boolean newPauseState) {
boolean oldPauseState = this.paused;
this.paused = newPauseState;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
if (newPauseState && !oldPauseState) {
this.onPause();
} else if (oldPauseState && !newPauseState) {
this.onUnpause();
}
}
public SceneLoadState getSceneLoadState() {
return sceneState;
}
public void setSceneLoadState(SceneLoadState sceneState) {
this.sceneState = sceneState;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public boolean isInMultiplayer() {
return this.getWorld() != null && this.getWorld().isMultiplayer();
}
public int getSceneId() {
return sceneId;
}
public void setSceneId(int sceneId) {
this.sceneId = sceneId;
}
public int getRegionId() {
return regionId;
}
public void setRegionId(int regionId) {
this.regionId = regionId;
}
2022-04-25 14:51:34 +08:00
2022-04-18 22:10:41 -04:00
public boolean inGodmode() {
2022-04-17 05:43:07 -07:00
return godmode;
}
public void setGodmode(boolean godmode) {
this.godmode = godmode;
}
public boolean hasSentAvatarDataNotify() {
return hasSentAvatarDataNotify;
}
public void setHasSentAvatarDataNotify(boolean hasSentAvatarDataNotify) {
this.hasSentAvatarDataNotify = hasSentAvatarDataNotify;
}
public void addAvatar(GenshinAvatar avatar) {
boolean result = getAvatars().addAvatar(avatar);
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
if (result) {
// Add starting weapon
getAvatars().addStartingWeapon(avatar);
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Try adding to team if possible
//List<EntityAvatar> currentTeam = this.getTeamManager().getCurrentTeam();
boolean addedToTeam = false;
/*
if (currentTeam.size() <= GenshinConstants.MAX_AVATARS_IN_TEAM) {
addedToTeam = currentTeam
}
*/
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Done
if (hasSentAvatarDataNotify()) {
// Recalc stats
avatar.recalcStats();
// Packet
sendPacket(new PacketAvatarAddNotify(avatar, addedToTeam));
}
} else {
// Failed adding avatar
}
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void addFlycloak(int flycloakId) {
this.getFlyCloakList().add(flycloakId);
this.sendPacket(new PacketAvatarGainFlycloakNotify(flycloakId));
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void addCostume(int costumeId) {
this.getCostumeList().add(costumeId);
this.sendPacket(new PacketAvatarGainCostumeNotify(costumeId));
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void addNameCard(int nameCardId) {
this.getNameCardList().add(nameCardId);
this.sendPacket(new PacketUnlockNameCardNotify(nameCardId));
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void setNameCard(int nameCardId) {
if (!this.getNameCardList().contains(nameCardId)) {
return;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
this.setNameCardId(nameCardId);
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
this.sendPacket(new PacketSetNameCardRsp(nameCardId));
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void dropMessage(Object message) {
this.sendPacket(new PacketPrivateChatNotify(GenshinConstants.SERVER_CONSOLE_UID, getUid(), message.toString()));
2022-04-17 05:43:07 -07:00
}
2022-04-18 21:35:01 -07:00
/**
* Sends a message to another player.
2022-04-25 14:51:34 +08:00
*
* @param sender The sender of the message.
2022-04-18 21:35:01 -07:00
* @param message The message to send.
*/
public void sendMessage(GenshinPlayer sender, Object message) {
this.sendPacket(new PacketPrivateChatNotify(sender.getUid(), this.getUid(), message.toString()));
2022-04-17 05:43:07 -07:00
}
2022-04-25 14:51:34 +08:00
2022-04-25 13:51:19 +08:00
// ---------------------MAIL------------------------
2022-04-25 13:51:19 +08:00
public List<Mail> getAllMail() { return this.mail; }
2022-04-25 13:51:19 +08:00
public void sendMail(Mail message) {
this.mail.add(message);
message._id = this.mail.size() + 1;
this.save();
this.sendPacket(new PacketMailChangeNotify(this, message));
}
2022-04-25 13:51:19 +08:00
public boolean deleteMail(int mailId) {
Mail message = getMailById(mailId);
if(message != null) {
2022-04-25 14:30:56 +08:00
int index = getMailIndex(message);
message.expireTime = (int) Instant.now().getEpochSecond(); // Just set the mail as expired for now. I don't want to implement a counter specifically for an account...
this.replaceMailByIndex(index, message);
2022-04-25 13:51:19 +08:00
return true;
}
return false;
}
public Mail getMailById(int mailId) {
return this.mail.stream().filter(message -> message._id == mailId).findFirst().orElse(null);
}
public int getMailIndex(Mail message) {
return this.mail.indexOf(message);
}
2022-04-25 14:30:56 +08:00
public boolean replaceMailByIndex(int index, Mail message) {
if(getMailById(index) != null) {
this.mail.set(index, message);
this.save();
2022-04-25 13:51:19 +08:00
return true;
} else {
return false;
}
}
2022-04-17 05:43:07 -07:00
public void interactWith(int gadgetEntityId) {
GenshinEntity entity = getScene().getEntityById(gadgetEntityId);
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
if (entity == null) {
return;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Delete
entity.getScene().removeEntity(entity);
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Handle
if (entity instanceof EntityItem) {
// Pick item
EntityItem drop = (EntityItem) entity;
GenshinItem item = new GenshinItem(drop.getItemData(), drop.getCount());
// Add to inventory
boolean success = getInventory().addItem(item);
if (success) {
this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.InteractPickItem));
this.sendPacket(new PacketItemAddHintNotify(item, ActionReason.SubfieldDrop));
}
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
return;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void onPause() {
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void onUnpause() {
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void sendPacket(GenshinPacket packet) {
if (this.hasSentAvatarDataNotify) {
this.getSession().send(packet);
}
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public OnlinePlayerInfo getOnlinePlayerInfo() {
OnlinePlayerInfo.Builder onlineInfo = OnlinePlayerInfo.newBuilder()
2022-04-25 15:16:18 +08:00
.setUid(this.getUid())
.setNickname(this.getNickname())
.setPlayerLevel(this.getLevel())
.setMpSettingType(this.getMpSetting())
.setNameCardId(this.getNameCardId())
.setSignature(this.getSignature())
.setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage()));
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
if (this.getWorld() != null) {
onlineInfo.setCurPlayerNumInWorld(this.getWorld().getPlayers().indexOf(this) + 1);
} else {
onlineInfo.setCurPlayerNumInWorld(1);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
return onlineInfo.build();
}
2022-04-25 14:51:34 +08:00
public PlayerBirthday getBirthday() {
2022-04-23 03:22:32 +02:00
return this.birthday;
}
public void setBirthday(int d, int m) {
this.birthday = new PlayerBirthday(d, m);
this.updateProfile();
}
2022-04-25 14:51:34 +08:00
public boolean hasBirthday() {
return this.birthday.getDay() > 0;
}
public Set<Integer> getRewardedLevels() {
return rewardedLevels;
}
public void setRewardedLevels(Set<Integer> rewardedLevels) {
this.rewardedLevels = rewardedLevels;
}
2022-04-17 05:43:07 -07:00
public SocialDetail.Builder getSocialDetail() {
2022-04-25 15:16:18 +08:00
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);
2022-04-17 05:43:07 -07:00
return social;
}
2022-04-25 14:51:34 +08:00
2022-04-20 18:44:02 -07:00
public WorldPlayerLocationInfo getWorldPlayerLocationInfo() {
2022-04-25 15:16:18 +08:00
return WorldPlayerLocationInfo.newBuilder()
.setSceneId(this.getSceneId())
.setPlayerLoc(this.getPlayerLocationInfo())
.build();
2022-04-20 18:44:02 -07:00
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public PlayerLocationInfo getPlayerLocationInfo() {
2022-04-25 15:16:18 +08:00
return PlayerLocationInfo.newBuilder()
.setUid(this.getUid())
.setPos(this.getPos().toProto())
.setRot(this.getRotation().toProto())
.build();
2022-04-17 05:43:07 -07:00
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public synchronized void onTick() {
// Check ping
if (this.getLastPingTime() > System.currentTimeMillis() + 60000) {
this.getSession().close();
return;
}
// Check co-op requests
Iterator<CoopRequest> it = this.getCoopRequests().values().iterator();
while (it.hasNext()) {
CoopRequest req = it.next();
if (req.isExpired()) {
req.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(this, false, PlayerApplyEnterMpReason.SystemJudge));
it.remove();
}
}
// Ping
if (this.getWorld() != null) {
2022-04-20 18:44:02 -07:00
// RTT notify - very important to send this often
this.sendPacket(new PacketWorldPlayerRTTNotify(this.getWorld()));
2022-04-25 14:51:34 +08:00
2022-04-20 18:44:02 -07:00
// 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();
}
2022-04-17 05:43:07 -07:00
}
}
2022-04-25 14:51:34 +08:00
2022-04-20 18:44:02 -07:00
public void resetSendPlayerLocTime() {
this.nextSendPlayerLocTime = System.currentTimeMillis() + 5000;
}
2022-04-17 05:43:07 -07:00
@PostLoad
private void onLoad() {
this.getTeamManager().setPlayer(this);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void save() {
DatabaseHelper.savePlayer(this);
}
public void onLogin() {
// Make sure these exist
if (this.getTeamManager() == null) {
this.teamManager = new TeamManager(this);
2022-04-25 14:51:34 +08:00
}
if (this.getProfile().getUid() == 0) {
this.getProfile().syncWithCharacter(this);
2022-04-17 05:43:07 -07:00
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Check if player object exists in server
// TODO - optimize
GenshinPlayer exists = this.getServer().getPlayerByUid(getUid());
2022-04-17 05:43:07 -07:00
if (exists != null) {
exists.getSession().close();
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Load from db
this.getAvatars().loadFromDatabase();
this.getInventory().loadFromDatabase();
this.getAvatars().postLoad();
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
this.getFriendsList().loadFromDatabase();
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Create world
World world = new World(this);
world.addPlayer(this);
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Add to gameserver
if (getSession().isActive()) {
getServer().registerPlayer(this);
getProfile().setPlayer(this); // Set online
}
2022-04-25 14:51:34 +08:00
// Multiplayer setting
2022-04-17 05:43:07 -07:00
this.setProperty(PlayerProperty.PROP_PLAYER_MP_SETTING_TYPE, this.getMpSetting().getNumber());
this.setProperty(PlayerProperty.PROP_IS_MP_MODE_AVAILABLE, 1);
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Packets
session.send(new PacketPlayerDataNotify(this)); // Player data
session.send(new PacketStoreWeightLimitNotify());
session.send(new PacketPlayerStoreNotify(this));
session.send(new PacketAvatarDataNotify(this));
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
session.send(new PacketPlayerEnterSceneNotify(this)); // Enter game world
session.send(new PacketPlayerLevelRewardUpdateNotify(rewardedLevels));
2022-04-17 05:43:07 -07:00
session.send(new PacketOpenStateUpdateNotify());
// First notify packets sent
this.setHasSentAvatarDataNotify(true);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public void onLogout() {
// Leave world
if (this.getWorld() != null) {
this.getWorld().removePlayer(this);
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Status stuff
this.getProfile().syncWithCharacter(this);
this.getProfile().setPlayer(null); // Set offline
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
this.getCoopRequests().clear();
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
// Save to db
this.save();
this.getTeamManager().saveAvatars();
this.getFriendsList().save();
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public enum SceneLoadState {
2022-04-25 14:51:34 +08:00
NONE(0), LOADING(1), INIT(2), LOADED(3);
2022-04-17 05:43:07 -07:00
private final int value;
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
private SceneLoadState(int value) {
this.value = value;
}
2022-04-25 14:51:34 +08:00
2022-04-17 05:43:07 -07:00
public int getValue() {
return this.value;
}
}
}