fix: player profile changes are not reflected cuz Java is object-oriented (#2322)

* fix: player profile changes are not reflected.
fix: deob FriendBrief.proto

* fix: tentatively sync profile when log out

* fix: allow offline player

* Update src/main/java/emu/grasscutter/game/friends/PlayerProfile.java

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* Update src/main/java/emu/grasscutter/game/player/Player.java

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* Update src/main/java/emu/grasscutter/game/player/Player.java

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>

* fix: server friend

---------

Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
This commit is contained in:
hamusuke 2023-08-30 12:23:46 +09:00 committed by GitHub
parent 8e4e3dd89e
commit 7049cfdb58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 119 additions and 144 deletions

View File

@ -217,16 +217,16 @@ public final class FriendBriefOuterClass {
emu.grasscutter.net.proto.PlatformTypeOuterClass.PlatformType getPlatformType(); emu.grasscutter.net.proto.PlatformTypeOuterClass.PlatformType getPlatformType();
/** /**
* <code>bool IEAHDCLDOEJ = 28;</code> * <code>bool is_in_duel = 28;</code>
* @return The iEAHDCLDOEJ. * @return The isInDuel.
*/ */
boolean getIEAHDCLDOEJ(); boolean getIsInDuel();
/** /**
* <code>bool BJFJJMGENCH = 29;</code> * <code>bool is_duel_observable = 29;</code>
* @return The bJFJJMGENCH. * @return The isDuelObservable.
*/ */
boolean getBJFJJMGENCH(); boolean getIsDuelObservable();
} }
/** /**
* <pre> * <pre>
@ -417,12 +417,12 @@ public final class FriendBriefOuterClass {
} }
case 224: { case 224: {
iEAHDCLDOEJ_ = input.readBool(); isInDuel_ = input.readBool();
break; break;
} }
case 232: { case 232: {
bJFJJMGENCH_ = input.readBool(); isDuelObservable_ = input.readBool();
break; break;
} }
default: { default: {
@ -878,26 +878,26 @@ public final class FriendBriefOuterClass {
return result == null ? emu.grasscutter.net.proto.PlatformTypeOuterClass.PlatformType.UNRECOGNIZED : result; return result == null ? emu.grasscutter.net.proto.PlatformTypeOuterClass.PlatformType.UNRECOGNIZED : result;
} }
public static final int IEAHDCLDOEJ_FIELD_NUMBER = 28; public static final int IS_IN_DUEL_FIELD_NUMBER = 28;
private boolean iEAHDCLDOEJ_; private boolean isInDuel_;
/** /**
* <code>bool IEAHDCLDOEJ = 28;</code> * <code>bool is_in_duel = 28;</code>
* @return The iEAHDCLDOEJ. * @return The isInDuel.
*/ */
@java.lang.Override @java.lang.Override
public boolean getIEAHDCLDOEJ() { public boolean getIsInDuel() {
return iEAHDCLDOEJ_; return isInDuel_;
} }
public static final int BJFJJMGENCH_FIELD_NUMBER = 29; public static final int IS_DUEL_OBSERVABLE_FIELD_NUMBER = 29;
private boolean bJFJJMGENCH_; private boolean isDuelObservable_;
/** /**
* <code>bool BJFJJMGENCH = 29;</code> * <code>bool is_duel_observable = 29;</code>
* @return The bJFJJMGENCH. * @return The isDuelObservable.
*/ */
@java.lang.Override @java.lang.Override
public boolean getBJFJJMGENCH() { public boolean getIsDuelObservable() {
return bJFJJMGENCH_; return isDuelObservable_;
} }
private byte memoizedIsInitialized = -1; private byte memoizedIsInitialized = -1;
@ -980,11 +980,11 @@ public final class FriendBriefOuterClass {
if (platformType_ != emu.grasscutter.net.proto.PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_EDITOR.getNumber()) { if (platformType_ != emu.grasscutter.net.proto.PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_EDITOR.getNumber()) {
output.writeEnum(27, platformType_); output.writeEnum(27, platformType_);
} }
if (iEAHDCLDOEJ_ != false) { if (isInDuel_ != false) {
output.writeBool(28, iEAHDCLDOEJ_); output.writeBool(28, isInDuel_);
} }
if (bJFJJMGENCH_ != false) { if (isDuelObservable_ != false) {
output.writeBool(29, bJFJJMGENCH_); output.writeBool(29, isDuelObservable_);
} }
unknownFields.writeTo(output); unknownFields.writeTo(output);
} }
@ -1079,13 +1079,13 @@ public final class FriendBriefOuterClass {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeEnumSize(27, platformType_); .computeEnumSize(27, platformType_);
} }
if (iEAHDCLDOEJ_ != false) { if (isInDuel_ != false) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBoolSize(28, iEAHDCLDOEJ_); .computeBoolSize(28, isInDuel_);
} }
if (bJFJJMGENCH_ != false) { if (isDuelObservable_ != false) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBoolSize(29, bJFJJMGENCH_); .computeBoolSize(29, isDuelObservable_);
} }
size += unknownFields.getSerializedSize(); size += unknownFields.getSerializedSize();
memoizedSize = size; memoizedSize = size;
@ -1146,10 +1146,10 @@ public final class FriendBriefOuterClass {
if (getIsPsnSource() if (getIsPsnSource()
!= other.getIsPsnSource()) return false; != other.getIsPsnSource()) return false;
if (platformType_ != other.platformType_) return false; if (platformType_ != other.platformType_) return false;
if (getIEAHDCLDOEJ() if (getIsInDuel()
!= other.getIEAHDCLDOEJ()) return false; != other.getIsInDuel()) return false;
if (getBJFJJMGENCH() if (getIsDuelObservable()
!= other.getBJFJJMGENCH()) return false; != other.getIsDuelObservable()) return false;
if (!unknownFields.equals(other.unknownFields)) return false; if (!unknownFields.equals(other.unknownFields)) return false;
return true; return true;
} }
@ -1213,12 +1213,12 @@ public final class FriendBriefOuterClass {
getIsPsnSource()); getIsPsnSource());
hash = (37 * hash) + PLATFORM_TYPE_FIELD_NUMBER; hash = (37 * hash) + PLATFORM_TYPE_FIELD_NUMBER;
hash = (53 * hash) + platformType_; hash = (53 * hash) + platformType_;
hash = (37 * hash) + IEAHDCLDOEJ_FIELD_NUMBER; hash = (37 * hash) + IS_IN_DUEL_FIELD_NUMBER;
hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
getIEAHDCLDOEJ()); getIsInDuel());
hash = (37 * hash) + BJFJJMGENCH_FIELD_NUMBER; hash = (37 * hash) + IS_DUEL_OBSERVABLE_FIELD_NUMBER;
hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
getBJFJJMGENCH()); getIsDuelObservable());
hash = (29 * hash) + unknownFields.hashCode(); hash = (29 * hash) + unknownFields.hashCode();
memoizedHashCode = hash; memoizedHashCode = hash;
return hash; return hash;
@ -1409,9 +1409,9 @@ public final class FriendBriefOuterClass {
platformType_ = 0; platformType_ = 0;
iEAHDCLDOEJ_ = false; isInDuel_ = false;
bJFJJMGENCH_ = false; isDuelObservable_ = false;
return this; return this;
} }
@ -1474,8 +1474,8 @@ public final class FriendBriefOuterClass {
result.isGameSource_ = isGameSource_; result.isGameSource_ = isGameSource_;
result.isPsnSource_ = isPsnSource_; result.isPsnSource_ = isPsnSource_;
result.platformType_ = platformType_; result.platformType_ = platformType_;
result.iEAHDCLDOEJ_ = iEAHDCLDOEJ_; result.isInDuel_ = isInDuel_;
result.bJFJJMGENCH_ = bJFJJMGENCH_; result.isDuelObservable_ = isDuelObservable_;
onBuilt(); onBuilt();
return result; return result;
} }
@ -1617,11 +1617,11 @@ public final class FriendBriefOuterClass {
if (other.platformType_ != 0) { if (other.platformType_ != 0) {
setPlatformTypeValue(other.getPlatformTypeValue()); setPlatformTypeValue(other.getPlatformTypeValue());
} }
if (other.getIEAHDCLDOEJ() != false) { if (other.getIsInDuel() != false) {
setIEAHDCLDOEJ(other.getIEAHDCLDOEJ()); setIsInDuel(other.getIsInDuel());
} }
if (other.getBJFJJMGENCH() != false) { if (other.getIsDuelObservable() != false) {
setBJFJJMGENCH(other.getBJFJJMGENCH()); setIsDuelObservable(other.getIsDuelObservable());
} }
this.mergeUnknownFields(other.unknownFields); this.mergeUnknownFields(other.unknownFields);
onChanged(); onChanged();
@ -2881,64 +2881,64 @@ public final class FriendBriefOuterClass {
return this; return this;
} }
private boolean iEAHDCLDOEJ_ ; private boolean isInDuel_ ;
/** /**
* <code>bool IEAHDCLDOEJ = 28;</code> * <code>bool is_in_duel = 28;</code>
* @return The iEAHDCLDOEJ. * @return The isInDuel.
*/ */
@java.lang.Override @java.lang.Override
public boolean getIEAHDCLDOEJ() { public boolean getIsInDuel() {
return iEAHDCLDOEJ_; return isInDuel_;
} }
/** /**
* <code>bool IEAHDCLDOEJ = 28;</code> * <code>bool is_in_duel = 28;</code>
* @param value The iEAHDCLDOEJ to set. * @param value The isInDuel to set.
* @return This builder for chaining. * @return This builder for chaining.
*/ */
public Builder setIEAHDCLDOEJ(boolean value) { public Builder setIsInDuel(boolean value) {
iEAHDCLDOEJ_ = value; isInDuel_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /**
* <code>bool IEAHDCLDOEJ = 28;</code> * <code>bool is_in_duel = 28;</code>
* @return This builder for chaining. * @return This builder for chaining.
*/ */
public Builder clearIEAHDCLDOEJ() { public Builder clearIsInDuel() {
iEAHDCLDOEJ_ = false; isInDuel_ = false;
onChanged(); onChanged();
return this; return this;
} }
private boolean bJFJJMGENCH_ ; private boolean isDuelObservable_ ;
/** /**
* <code>bool BJFJJMGENCH = 29;</code> * <code>bool is_duel_observable = 29;</code>
* @return The bJFJJMGENCH. * @return The isDuelObservable.
*/ */
@java.lang.Override @java.lang.Override
public boolean getBJFJJMGENCH() { public boolean getIsDuelObservable() {
return bJFJJMGENCH_; return isDuelObservable_;
} }
/** /**
* <code>bool BJFJJMGENCH = 29;</code> * <code>bool is_duel_observable = 29;</code>
* @param value The bJFJJMGENCH to set. * @param value The isDuelObservable to set.
* @return This builder for chaining. * @return This builder for chaining.
*/ */
public Builder setBJFJJMGENCH(boolean value) { public Builder setIsDuelObservable(boolean value) {
bJFJJMGENCH_ = value; isDuelObservable_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /**
* <code>bool BJFJJMGENCH = 29;</code> * <code>bool is_duel_observable = 29;</code>
* @return This builder for chaining. * @return This builder for chaining.
*/ */
public Builder clearBJFJJMGENCH() { public Builder clearIsDuelObservable() {
bJFJJMGENCH_ = false; isDuelObservable_ = false;
onChanged(); onChanged();
return this; return this;
} }
@ -3012,7 +3012,7 @@ public final class FriendBriefOuterClass {
"\n\021FriendBrief.proto\032\027FriendOnlineState.p" + "\n\021FriendBrief.proto\032\027FriendOnlineState.p" +
"roto\032\032SocialShowAvatarInfo.proto\032\033Friend" + "roto\032\032SocialShowAvatarInfo.proto\032\033Friend" +
"EnterHomeOption.proto\032\024ProfilePicture.pr" + "EnterHomeOption.proto\032\024ProfilePicture.pr" +
"oto\032\022PlatformType.proto\"\210\005\n\013FriendBrief\022" + "oto\032\022PlatformType.proto\"\216\005\n\013FriendBrief\022" +
"\013\n\003uid\030\001 \001(\r\022\020\n\010nickname\030\002 \001(\t\022\r\n\005level\030" + "\013\n\003uid\030\001 \001(\r\022\020\n\010nickname\030\002 \001(\t\022\r\n\005level\030" +
"\003 \001(\r\022\021\n\tavatar_id\030\004 \001(\r\022\023\n\013world_level\030" + "\003 \001(\r\022\021\n\tavatar_id\030\004 \001(\r\022\023\n\013world_level\030" +
"\005 \001(\r\022\021\n\tsignature\030\006 \001(\t\022(\n\014online_state" + "\005 \001(\r\022\021\n\tsignature\030\006 \001(\t\022(\n\014online_state" +
@ -3027,9 +3027,9 @@ public final class FriendBriefOuterClass {
"\0162\026.FriendEnterHomeOption\022(\n\017profile_pic" + "\0162\026.FriendEnterHomeOption\022(\n\017profile_pic" +
"ture\030\030 \001(\0132\017.ProfilePicture\022\026\n\016is_game_s" + "ture\030\030 \001(\0132\017.ProfilePicture\022\026\n\016is_game_s" +
"ource\030\031 \001(\010\022\025\n\ris_psn_source\030\032 \001(\010\022$\n\rpl" + "ource\030\031 \001(\010\022\025\n\ris_psn_source\030\032 \001(\010\022$\n\rpl" +
"atform_type\030\033 \001(\0162\r.PlatformType\022\023\n\013IEAH" + "atform_type\030\033 \001(\0162\r.PlatformType\022\022\n\nis_i" +
"DCLDOEJ\030\034 \001(\010\022\023\n\013BJFJJMGENCH\030\035 \001(\010B\033\n\031em" + "n_duel\030\034 \001(\010\022\032\n\022is_duel_observable\030\035 \001(\010" +
"u.grasscutter.net.protob\006proto3" "B\033\n\031emu.grasscutter.net.protob\006proto3"
}; };
descriptor = com.google.protobuf.Descriptors.FileDescriptor descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData, .internalBuildGeneratedFileFrom(descriptorData,
@ -3045,7 +3045,7 @@ public final class FriendBriefOuterClass {
internal_static_FriendBrief_fieldAccessorTable = new internal_static_FriendBrief_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_FriendBrief_descriptor, internal_static_FriendBrief_descriptor,
new java.lang.String[] { "Uid", "Nickname", "Level", "AvatarId", "WorldLevel", "Signature", "OnlineState", "Param", "IsMpModeAvailable", "OnlineId", "LastActiveTime", "NameCardId", "MpPlayerNum", "IsChatNoDisturb", "ChatSequence", "RemarkName", "ShowAvatarInfoList", "FriendEnterHomeOption", "ProfilePicture", "IsGameSource", "IsPsnSource", "PlatformType", "IEAHDCLDOEJ", "BJFJJMGENCH", }); new java.lang.String[] { "Uid", "Nickname", "Level", "AvatarId", "WorldLevel", "Signature", "OnlineState", "Param", "IsMpModeAvailable", "OnlineId", "LastActiveTime", "NameCardId", "MpPlayerNum", "IsChatNoDisturb", "ChatSequence", "RemarkName", "ShowAvatarInfoList", "FriendEnterHomeOption", "ProfilePicture", "IsGameSource", "IsPsnSource", "PlatformType", "IsInDuel", "IsDuelObservable", });
emu.grasscutter.net.proto.FriendOnlineStateOuterClass.getDescriptor(); emu.grasscutter.net.proto.FriendOnlineStateOuterClass.getDescriptor();
emu.grasscutter.net.proto.SocialShowAvatarInfoOuterClass.getDescriptor(); emu.grasscutter.net.proto.SocialShowAvatarInfoOuterClass.getDescriptor();
emu.grasscutter.net.proto.FriendEnterHomeOptionOuterClass.getDescriptor(); emu.grasscutter.net.proto.FriendEnterHomeOptionOuterClass.getDescriptor();

View File

@ -14,19 +14,24 @@ import org.bson.types.ObjectId;
@Entity(value = "friendships", useDiscriminator = false) @Entity(value = "friendships", useDiscriminator = false)
public class Friendship { public class Friendship {
@Id private ObjectId id; @Id
private ObjectId id;
@Transient private Player owner; @Transient
private Player owner;
@Indexed private int ownerId; @Indexed
@Indexed private int friendId; private int ownerId;
@Indexed
private int friendId;
private boolean isFriend; private boolean isFriend;
private int askerId; private int askerId;
private PlayerProfile profile; private PlayerProfile profile;
@Deprecated // Morphia use only @Deprecated // Morphia use only
public Friendship() {} public Friendship() {
}
public Friendship(Player owner, Player friend, Player asker) { public Friendship(Player owner, Player friend, Player asker) {
this.setOwner(owner); this.setOwner(owner);
@ -90,28 +95,28 @@ public class Friendship {
} }
public FriendBrief toProto() { public FriendBrief toProto() {
FriendBrief proto = var player = this.getFriendProfile().getPlayer(); // get latest player and sync.
FriendBrief.newBuilder()
.setUid(getFriendProfile().getUid())
.setNickname(getFriendProfile().getName())
.setLevel(getFriendProfile().getPlayerLevel())
.setProfilePicture(
ProfilePicture.newBuilder().setAvatarId(getFriendProfile().getAvatarId()))
.setWorldLevel(getFriendProfile().getWorldLevel())
.setSignature(getFriendProfile().getSignature())
.setOnlineState(
getFriendProfile().isOnline()
? FriendOnlineState.FRIEND_ONLINE_STATE_ONLINE
: FriendOnlineState.FRIEND_ONLINE_STATE_DISCONNECT)
.setIsMpModeAvailable(true)
.setLastActiveTime(getFriendProfile().getLastActiveTime())
.setNameCardId(getFriendProfile().getNameCard())
.setParam(getFriendProfile().getDaysSinceLogin())
.setIsGameSource(true)
.setPlatformType(PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_PC)
.setFriendEnterHomeOptionValue(getFriendProfile().getEnterHomeOption())
.build();
return proto; return FriendBrief.newBuilder()
.setUid(getFriendProfile().getUid())
.setNickname(getFriendProfile().getName())
.setLevel(getFriendProfile().getPlayerLevel())
.setProfilePicture(
ProfilePicture.newBuilder().setAvatarId(getFriendProfile().getAvatarId()))
.setWorldLevel(getFriendProfile().getWorldLevel())
.setSignature(getFriendProfile().getSignature())
.setOnlineState(
player != null && player.isOnline()
? FriendOnlineState.FRIEND_ONLINE_STATE_ONLINE
: FriendOnlineState.FRIEND_ONLINE_STATE_DISCONNECT)
.setIsMpModeAvailable(true)
.setLastActiveTime(getFriendProfile().getLastActiveTime())
.setNameCardId(getFriendProfile().getNameCard())
.setParam(getFriendProfile().getDaysSinceLogin())
.setIsGameSource(true)
.setPlatformType(PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_PC)
.setIsInDuel(getFriendProfile().isInDuel())
.setIsDuelObservable(getFriendProfile().isDuelObservable())
.build();
} }
} }

View File

@ -2,17 +2,21 @@ package emu.grasscutter.game.friends;
import dev.morphia.annotations.AlsoLoad; import dev.morphia.annotations.AlsoLoad;
import dev.morphia.annotations.Entity; import dev.morphia.annotations.Entity;
import emu.grasscutter.Grasscutter;
import dev.morphia.annotations.Transient; import dev.morphia.annotations.Transient;
import emu.grasscutter.game.home.GameHome; import emu.grasscutter.game.home.GameHome;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.proto.FriendEnterHomeOptionOuterClass; import emu.grasscutter.net.proto.FriendEnterHomeOptionOuterClass;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.Nullable;
@Entity @Entity
@Getter
public class PlayerProfile { public class PlayerProfile {
@Transient private Player player;
@AlsoLoad("id") @AlsoLoad("id")
private int uid; private int uid;
@ -24,9 +28,14 @@ public class PlayerProfile {
private int playerLevel; private int playerLevel;
private int worldLevel; private int worldLevel;
private int lastActiveTime; private int lastActiveTime;
private boolean isInDuel = false; // TODO: Implement duels. (TCG)
private boolean isDuelObservable = false; // TODO: Implement duels. (TCG)
@Getter @Getter
private int enterHomeOption; private int enterHomeOption;
@Deprecated // Morphia only @Deprecated // Morphia only
public PlayerProfile() {} public PlayerProfile() {}
@ -35,46 +44,13 @@ public class PlayerProfile {
this.syncWithCharacter(player); this.syncWithCharacter(player);
} }
public int getUid() { @Nullable
return uid;
}
public Player getPlayer() { public Player getPlayer() {
var player = Grasscutter.getGameServer().getPlayerByUid(this.getUid(), true);
this.syncWithCharacter(player);
return player; return player;
} }
public synchronized void setPlayer(Player player) {
this.player = player;
}
public String getName() {
return name;
}
public int getNameCard() {
return nameCard;
}
public int getAvatarId() {
return avatarId;
}
public String getSignature() {
return signature;
}
public int getPlayerLevel() {
return playerLevel;
}
public int getWorldLevel() {
return worldLevel;
}
public int getLastActiveTime() {
return lastActiveTime;
}
public void updateLastActiveTime() { public void updateLastActiveTime() {
this.lastActiveTime = Utils.getCurrentSeconds(); this.lastActiveTime = Utils.getCurrentSeconds();
} }
@ -83,10 +59,6 @@ public class PlayerProfile {
return (int) Math.floor((Utils.getCurrentSeconds() - getLastActiveTime()) / 86400.0); return (int) Math.floor((Utils.getCurrentSeconds() - getLastActiveTime()) / 86400.0);
} }
public boolean isOnline() {
return this.getPlayer() != null;
}
public void syncWithCharacter(Player player) { public void syncWithCharacter(Player player) {
if (player == null) { if (player == null) {
return; return;

View File

@ -1488,7 +1488,6 @@ public class Player implements PlayerHook, FieldFetch {
// register // register
getServer().registerPlayer(this); getServer().registerPlayer(this);
getProfile().setPlayer(this); // Set online
} }
public void onLogout() { public void onLogout() {
@ -1509,7 +1508,6 @@ public class Player implements PlayerHook, FieldFetch {
// Status stuff // Status stuff
this.getProfile().syncWithCharacter(this); this.getProfile().syncWithCharacter(this);
this.getProfile().setPlayer(null); // Set offline
this.getCoopRequests().clear(); this.getCoopRequests().clear();
this.getEnterHomeRequests().values().forEach(req -> this.expireEnterHomeRequest(req, true)); this.getEnterHomeRequests().values().forEach(req -> this.expireEnterHomeRequest(req, true));