From 7049cfdb58a141cead96bfad245c798fa33340f2 Mon Sep 17 00:00:00 2001 From: hamusuke Date: Wed, 30 Aug 2023 12:23:46 +0900 Subject: [PATCH] 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> --- .../net/proto/FriendBriefOuterClass.java | 146 +++++++++--------- .../grasscutter/game/friends/Friendship.java | 59 +++---- .../game/friends/PlayerProfile.java | 56 ++----- .../emu/grasscutter/game/player/Player.java | 2 - 4 files changed, 119 insertions(+), 144 deletions(-) diff --git a/src/generated/main/java/emu/grasscutter/net/proto/FriendBriefOuterClass.java b/src/generated/main/java/emu/grasscutter/net/proto/FriendBriefOuterClass.java index 7dde37122..0e1e0e2f3 100644 --- a/src/generated/main/java/emu/grasscutter/net/proto/FriendBriefOuterClass.java +++ b/src/generated/main/java/emu/grasscutter/net/proto/FriendBriefOuterClass.java @@ -217,16 +217,16 @@ public final class FriendBriefOuterClass { emu.grasscutter.net.proto.PlatformTypeOuterClass.PlatformType getPlatformType(); /** - * bool IEAHDCLDOEJ = 28; - * @return The iEAHDCLDOEJ. + * bool is_in_duel = 28; + * @return The isInDuel. */ - boolean getIEAHDCLDOEJ(); + boolean getIsInDuel(); /** - * bool BJFJJMGENCH = 29; - * @return The bJFJJMGENCH. + * bool is_duel_observable = 29; + * @return The isDuelObservable. */ - boolean getBJFJJMGENCH(); + boolean getIsDuelObservable(); } /** *
@@ -417,12 +417,12 @@ public final class FriendBriefOuterClass {
             }
             case 224: {
 
-              iEAHDCLDOEJ_ = input.readBool();
+              isInDuel_ = input.readBool();
               break;
             }
             case 232: {
 
-              bJFJJMGENCH_ = input.readBool();
+              isDuelObservable_ = input.readBool();
               break;
             }
             default: {
@@ -878,26 +878,26 @@ public final class FriendBriefOuterClass {
       return result == null ? emu.grasscutter.net.proto.PlatformTypeOuterClass.PlatformType.UNRECOGNIZED : result;
     }
 
-    public static final int IEAHDCLDOEJ_FIELD_NUMBER = 28;
-    private boolean iEAHDCLDOEJ_;
+    public static final int IS_IN_DUEL_FIELD_NUMBER = 28;
+    private boolean isInDuel_;
     /**
-     * bool IEAHDCLDOEJ = 28;
-     * @return The iEAHDCLDOEJ.
+     * bool is_in_duel = 28;
+     * @return The isInDuel.
      */
     @java.lang.Override
-    public boolean getIEAHDCLDOEJ() {
-      return iEAHDCLDOEJ_;
+    public boolean getIsInDuel() {
+      return isInDuel_;
     }
 
-    public static final int BJFJJMGENCH_FIELD_NUMBER = 29;
-    private boolean bJFJJMGENCH_;
+    public static final int IS_DUEL_OBSERVABLE_FIELD_NUMBER = 29;
+    private boolean isDuelObservable_;
     /**
-     * bool BJFJJMGENCH = 29;
-     * @return The bJFJJMGENCH.
+     * bool is_duel_observable = 29;
+     * @return The isDuelObservable.
      */
     @java.lang.Override
-    public boolean getBJFJJMGENCH() {
-      return bJFJJMGENCH_;
+    public boolean getIsDuelObservable() {
+      return isDuelObservable_;
     }
 
     private byte memoizedIsInitialized = -1;
@@ -980,11 +980,11 @@ public final class FriendBriefOuterClass {
       if (platformType_ != emu.grasscutter.net.proto.PlatformTypeOuterClass.PlatformType.PLATFORM_TYPE_EDITOR.getNumber()) {
         output.writeEnum(27, platformType_);
       }
-      if (iEAHDCLDOEJ_ != false) {
-        output.writeBool(28, iEAHDCLDOEJ_);
+      if (isInDuel_ != false) {
+        output.writeBool(28, isInDuel_);
       }
-      if (bJFJJMGENCH_ != false) {
-        output.writeBool(29, bJFJJMGENCH_);
+      if (isDuelObservable_ != false) {
+        output.writeBool(29, isDuelObservable_);
       }
       unknownFields.writeTo(output);
     }
@@ -1079,13 +1079,13 @@ public final class FriendBriefOuterClass {
         size += com.google.protobuf.CodedOutputStream
           .computeEnumSize(27, platformType_);
       }
-      if (iEAHDCLDOEJ_ != false) {
+      if (isInDuel_ != false) {
         size += com.google.protobuf.CodedOutputStream
-          .computeBoolSize(28, iEAHDCLDOEJ_);
+          .computeBoolSize(28, isInDuel_);
       }
-      if (bJFJJMGENCH_ != false) {
+      if (isDuelObservable_ != false) {
         size += com.google.protobuf.CodedOutputStream
-          .computeBoolSize(29, bJFJJMGENCH_);
+          .computeBoolSize(29, isDuelObservable_);
       }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
@@ -1146,10 +1146,10 @@ public final class FriendBriefOuterClass {
       if (getIsPsnSource()
           != other.getIsPsnSource()) return false;
       if (platformType_ != other.platformType_) return false;
-      if (getIEAHDCLDOEJ()
-          != other.getIEAHDCLDOEJ()) return false;
-      if (getBJFJJMGENCH()
-          != other.getBJFJJMGENCH()) return false;
+      if (getIsInDuel()
+          != other.getIsInDuel()) return false;
+      if (getIsDuelObservable()
+          != other.getIsDuelObservable()) return false;
       if (!unknownFields.equals(other.unknownFields)) return false;
       return true;
     }
@@ -1213,12 +1213,12 @@ public final class FriendBriefOuterClass {
           getIsPsnSource());
       hash = (37 * hash) + PLATFORM_TYPE_FIELD_NUMBER;
       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(
-          getIEAHDCLDOEJ());
-      hash = (37 * hash) + BJFJJMGENCH_FIELD_NUMBER;
+          getIsInDuel());
+      hash = (37 * hash) + IS_DUEL_OBSERVABLE_FIELD_NUMBER;
       hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
-          getBJFJJMGENCH());
+          getIsDuelObservable());
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
@@ -1409,9 +1409,9 @@ public final class FriendBriefOuterClass {
 
         platformType_ = 0;
 
-        iEAHDCLDOEJ_ = false;
+        isInDuel_ = false;
 
-        bJFJJMGENCH_ = false;
+        isDuelObservable_ = false;
 
         return this;
       }
@@ -1474,8 +1474,8 @@ public final class FriendBriefOuterClass {
         result.isGameSource_ = isGameSource_;
         result.isPsnSource_ = isPsnSource_;
         result.platformType_ = platformType_;
-        result.iEAHDCLDOEJ_ = iEAHDCLDOEJ_;
-        result.bJFJJMGENCH_ = bJFJJMGENCH_;
+        result.isInDuel_ = isInDuel_;
+        result.isDuelObservable_ = isDuelObservable_;
         onBuilt();
         return result;
       }
@@ -1617,11 +1617,11 @@ public final class FriendBriefOuterClass {
         if (other.platformType_ != 0) {
           setPlatformTypeValue(other.getPlatformTypeValue());
         }
-        if (other.getIEAHDCLDOEJ() != false) {
-          setIEAHDCLDOEJ(other.getIEAHDCLDOEJ());
+        if (other.getIsInDuel() != false) {
+          setIsInDuel(other.getIsInDuel());
         }
-        if (other.getBJFJJMGENCH() != false) {
-          setBJFJJMGENCH(other.getBJFJJMGENCH());
+        if (other.getIsDuelObservable() != false) {
+          setIsDuelObservable(other.getIsDuelObservable());
         }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
@@ -2881,64 +2881,64 @@ public final class FriendBriefOuterClass {
         return this;
       }
 
-      private boolean iEAHDCLDOEJ_ ;
+      private boolean isInDuel_ ;
       /**
-       * bool IEAHDCLDOEJ = 28;
-       * @return The iEAHDCLDOEJ.
+       * bool is_in_duel = 28;
+       * @return The isInDuel.
        */
       @java.lang.Override
-      public boolean getIEAHDCLDOEJ() {
-        return iEAHDCLDOEJ_;
+      public boolean getIsInDuel() {
+        return isInDuel_;
       }
       /**
-       * bool IEAHDCLDOEJ = 28;
-       * @param value The iEAHDCLDOEJ to set.
+       * bool is_in_duel = 28;
+       * @param value The isInDuel to set.
        * @return This builder for chaining.
        */
-      public Builder setIEAHDCLDOEJ(boolean value) {
+      public Builder setIsInDuel(boolean value) {
         
-        iEAHDCLDOEJ_ = value;
+        isInDuel_ = value;
         onChanged();
         return this;
       }
       /**
-       * bool IEAHDCLDOEJ = 28;
+       * bool is_in_duel = 28;
        * @return This builder for chaining.
        */
-      public Builder clearIEAHDCLDOEJ() {
+      public Builder clearIsInDuel() {
         
-        iEAHDCLDOEJ_ = false;
+        isInDuel_ = false;
         onChanged();
         return this;
       }
 
-      private boolean bJFJJMGENCH_ ;
+      private boolean isDuelObservable_ ;
       /**
-       * bool BJFJJMGENCH = 29;
-       * @return The bJFJJMGENCH.
+       * bool is_duel_observable = 29;
+       * @return The isDuelObservable.
        */
       @java.lang.Override
-      public boolean getBJFJJMGENCH() {
-        return bJFJJMGENCH_;
+      public boolean getIsDuelObservable() {
+        return isDuelObservable_;
       }
       /**
-       * bool BJFJJMGENCH = 29;
-       * @param value The bJFJJMGENCH to set.
+       * bool is_duel_observable = 29;
+       * @param value The isDuelObservable to set.
        * @return This builder for chaining.
        */
-      public Builder setBJFJJMGENCH(boolean value) {
+      public Builder setIsDuelObservable(boolean value) {
         
-        bJFJJMGENCH_ = value;
+        isDuelObservable_ = value;
         onChanged();
         return this;
       }
       /**
-       * bool BJFJJMGENCH = 29;
+       * bool is_duel_observable = 29;
        * @return This builder for chaining.
        */
-      public Builder clearBJFJJMGENCH() {
+      public Builder clearIsDuelObservable() {
         
-        bJFJJMGENCH_ = false;
+        isDuelObservable_ = false;
         onChanged();
         return this;
       }
@@ -3012,7 +3012,7 @@ public final class FriendBriefOuterClass {
       "\n\021FriendBrief.proto\032\027FriendOnlineState.p" +
       "roto\032\032SocialShowAvatarInfo.proto\032\033Friend" +
       "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" +
       "\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" +
@@ -3027,9 +3027,9 @@ public final class FriendBriefOuterClass {
       "\0162\026.FriendEnterHomeOption\022(\n\017profile_pic" +
       "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" +
-      "atform_type\030\033 \001(\0162\r.PlatformType\022\023\n\013IEAH" +
-      "DCLDOEJ\030\034 \001(\010\022\023\n\013BJFJJMGENCH\030\035 \001(\010B\033\n\031em" +
-      "u.grasscutter.net.protob\006proto3"
+      "atform_type\030\033 \001(\0162\r.PlatformType\022\022\n\nis_i" +
+      "n_duel\030\034 \001(\010\022\032\n\022is_duel_observable\030\035 \001(\010" +
+      "B\033\n\031emu.grasscutter.net.protob\006proto3"
     };
     descriptor = com.google.protobuf.Descriptors.FileDescriptor
       .internalBuildGeneratedFileFrom(descriptorData,
@@ -3045,7 +3045,7 @@ public final class FriendBriefOuterClass {
     internal_static_FriendBrief_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         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.SocialShowAvatarInfoOuterClass.getDescriptor();
     emu.grasscutter.net.proto.FriendEnterHomeOptionOuterClass.getDescriptor();
diff --git a/src/main/java/emu/grasscutter/game/friends/Friendship.java b/src/main/java/emu/grasscutter/game/friends/Friendship.java
index 3e28e9aa6..2282b7857 100644
--- a/src/main/java/emu/grasscutter/game/friends/Friendship.java
+++ b/src/main/java/emu/grasscutter/game/friends/Friendship.java
@@ -14,19 +14,24 @@ import org.bson.types.ObjectId;
 
 @Entity(value = "friendships", useDiscriminator = false)
 public class Friendship {
-    @Id private ObjectId id;
+    @Id
+    private ObjectId id;
 
-    @Transient private Player owner;
+    @Transient
+    private Player owner;
 
-    @Indexed private int ownerId;
-    @Indexed private int friendId;
+    @Indexed
+    private int ownerId;
+    @Indexed
+    private int friendId;
     private boolean isFriend;
     private int askerId;
 
     private PlayerProfile profile;
 
     @Deprecated // Morphia use only
-    public Friendship() {}
+    public Friendship() {
+    }
 
     public Friendship(Player owner, Player friend, Player asker) {
         this.setOwner(owner);
@@ -90,28 +95,28 @@ public class Friendship {
     }
 
     public FriendBrief toProto() {
-        FriendBrief proto =
-                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();
+        var player = this.getFriendProfile().getPlayer(); // get latest player and sync.
 
-        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();
     }
 }
diff --git a/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java b/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java
index b6676e9d7..d8106a7f8 100644
--- a/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java
+++ b/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java
@@ -2,17 +2,21 @@ package emu.grasscutter.game.friends;
 
 import dev.morphia.annotations.AlsoLoad;
 import dev.morphia.annotations.Entity;
+
+import emu.grasscutter.Grasscutter;
+
 import dev.morphia.annotations.Transient;
 import emu.grasscutter.game.home.GameHome;
+
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.net.proto.FriendEnterHomeOptionOuterClass;
 import emu.grasscutter.utils.Utils;
 import lombok.Getter;
+import org.jetbrains.annotations.Nullable;
 
 @Entity
+@Getter
 public class PlayerProfile {
-    @Transient private Player player;
-
     @AlsoLoad("id")
     private int uid;
 
@@ -24,9 +28,14 @@ public class PlayerProfile {
     private int playerLevel;
     private int worldLevel;
     private int lastActiveTime;
+
+    private boolean isInDuel = false; // TODO: Implement duels. (TCG)
+    private boolean isDuelObservable = false; // TODO: Implement duels. (TCG)
+
     @Getter
     private int enterHomeOption;
 
+
     @Deprecated // Morphia only
     public PlayerProfile() {}
 
@@ -35,46 +44,13 @@ public class PlayerProfile {
         this.syncWithCharacter(player);
     }
 
-    public int getUid() {
-        return uid;
-    }
-
+    @Nullable
     public Player getPlayer() {
+        var player = Grasscutter.getGameServer().getPlayerByUid(this.getUid(), true);
+        this.syncWithCharacter(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() {
         this.lastActiveTime = Utils.getCurrentSeconds();
     }
@@ -83,10 +59,6 @@ public class PlayerProfile {
         return (int) Math.floor((Utils.getCurrentSeconds() - getLastActiveTime()) / 86400.0);
     }
 
-    public boolean isOnline() {
-        return this.getPlayer() != null;
-    }
-
     public void syncWithCharacter(Player player) {
         if (player == null) {
             return;
diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java
index e84e433f4..c067739b2 100644
--- a/src/main/java/emu/grasscutter/game/player/Player.java
+++ b/src/main/java/emu/grasscutter/game/player/Player.java
@@ -1488,7 +1488,6 @@ public class Player implements PlayerHook, FieldFetch {
 
         // register
         getServer().registerPlayer(this);
-        getProfile().setPlayer(this); // Set online
     }
 
     public void onLogout() {
@@ -1509,7 +1508,6 @@ public class Player implements PlayerHook, FieldFetch {
 
             // Status stuff
             this.getProfile().syncWithCharacter(this);
-            this.getProfile().setPlayer(null); // Set offline
 
             this.getCoopRequests().clear();
             this.getEnterHomeRequests().values().forEach(req -> this.expireEnterHomeRequest(req, true));