From 02deeb285268f4fe48a17a21e57126ca610cefd5 Mon Sep 17 00:00:00 2001
From: AnimeGitB <AnimeGitB@bigblueball.in>
Date: Thu, 11 Aug 2022 13:11:33 +0930
Subject: [PATCH] Remove erroneous references to excel skilldata instead of
 avatar skilldata Refactor team resonances and correct login behaviour and
 less-than-full-party behaviour

---
 .../emu/grasscutter/game/avatar/Avatar.java   | 232 +++---------------
 .../emu/grasscutter/game/player/Player.java   |   1 +
 .../grasscutter/game/player/TeamManager.java  | 113 +++------
 3 files changed, 79 insertions(+), 267 deletions(-)

diff --git a/src/main/java/emu/grasscutter/game/avatar/Avatar.java b/src/main/java/emu/grasscutter/game/avatar/Avatar.java
index 37f696f4..f1d36025 100644
--- a/src/main/java/emu/grasscutter/game/avatar/Avatar.java
+++ b/src/main/java/emu/grasscutter/game/avatar/Avatar.java
@@ -8,6 +8,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.stream.Stream;
 import java.util.Set;
 
 import org.bson.types.ObjectId;
@@ -64,50 +65,51 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
 import lombok.Getter;
+import lombok.Setter;
 
 @Entity(value = "avatars", useDiscriminator = false)
 public class Avatar {
     @Id private ObjectId id;
-    @Indexed private int ownerId;	// Id of player that this avatar belongs to
+    @Indexed @Getter private int ownerId;	// Id of player that this avatar belongs to
 
     @Transient private Player owner;
-    @Transient private AvatarData data;
-    @Transient private AvatarSkillDepotData skillDepot;
-    @Transient private long guid;	// Player unique id
-    private int avatarId;			// Id of avatar
-
-    private int level = 1;
-    private int exp;
-    private int promoteLevel;
-    private int satiation; // ?
-    private int satiationPenalty; // ?
-    private float currentHp;
+    @Transient @Getter private AvatarData data;
+    @Transient @Getter private AvatarSkillDepotData skillDepot;
+    @Transient @Getter private long guid;	// Player unique id
+    @Getter private int avatarId;			// Id of avatar
+
+    @Getter @Setter private int level = 1;
+    @Getter @Setter private int exp;
+    @Getter @Setter private int promoteLevel;
+    @Getter @Setter private int satiation; // ?
+    @Getter @Setter private int satiationPenalty; // ?
+    @Getter @Setter private float currentHp;
     private float currentEnergy;
 
-    @Transient private final Int2ObjectMap<GameItem> equips;
+    @Transient @Getter private final Int2ObjectMap<GameItem> equips;
     @Transient private final Int2FloatOpenHashMap fightProp;
     @Transient @Getter private final Int2FloatOpenHashMap fightPropOverrides;
-    @Transient private Set<String> extraAbilityEmbryos;
+    @Transient @Getter private Set<String> extraAbilityEmbryos;
 
     private List<Integer> fetters;
 
-    private Map<Integer, Integer> skillLevelMap; // Talent levels
+    @Getter private Map<Integer, Integer> skillLevelMap; // Talent levels
     private Map<Integer, Integer> skillExtraChargeMap; // Charges
-    private Map<Integer, Integer> proudSkillBonusMap; // Talent bonus levels (from const)
-    private int skillDepotId;
-    private int coreProudSkillLevel; // Constellation level
-    private Set<Integer> talentIdList; // Constellation id list
-    private Set<Integer> proudSkillList; // Character passives
+    @Getter private Map<Integer, Integer> proudSkillBonusMap; // Talent bonus levels (from const)
+    @Getter private int skillDepotId;
+    @Getter @Setter private int coreProudSkillLevel; // Constellation level
+    @Getter private Set<Integer> talentIdList; // Constellation id list
+    @Getter private Set<Integer> proudSkillList; // Character passives
 
-    private int flyCloak;
-    private int costume;
-    private int bornTime;
+    @Getter @Setter private int flyCloak;
+    @Getter @Setter private int costume;
+    @Getter private int bornTime;
 
-    private int fetterLevel = 1;
-    private int fetterExp;
+    @Getter @Setter private int fetterLevel = 1;
+    @Getter @Setter private int fetterExp;
 
-    private int nameCardRewardId;
-    private int nameCardId;
+    @Getter @Setter private int nameCardRewardId;
+    @Getter @Setter private int nameCardId;
 
     @Deprecated // Do not use. Morhpia only!
     public Avatar() {
@@ -139,15 +141,13 @@ public class Avatar {
         this.proudSkillList = new HashSet<>();
 
         // Combat properties
-        for (FightProperty prop : FightProperty.values()) {
-            if (prop.getId() <= 0 || prop.getId() >= 3000) {
-                continue;
-            }
-            this.setFightProperty(prop, 0f);
-        }
+        Stream.of(FightProperty.values())
+            .map(FightProperty::getId)
+            .filter(id -> (id > 0) && (id < 3000))
+            .forEach(id -> this.setFightProperty(id, 0f));
 
         // Skill depot
-        this.setSkillDepotData(getAvatarData().getSkillDepot());
+        this.setSkillDepotData(data.getSkillDepot());
 
         // Set stats
         this.recalcStats();
@@ -175,76 +175,12 @@ public class Avatar {
         this.data = data; // Used while loading this from the database
     }
 
-    public int getOwnerId() {
-        return ownerId;
-    }
-
     public void setOwner(Player player) {
         this.owner = player;
         this.ownerId = player.getUid();
         this.guid = player.getNextGameGuid();
     }
 
-    public int getSatiation() {
-        return satiation;
-    }
-
-    public void setSatiation(int satiation) {
-        this.satiation = satiation;
-    }
-
-    public int getNameCardRewardId() {
-        return nameCardRewardId;
-    }
-
-    public void setNameCardRewardId(int nameCardRewardId) {
-        this.nameCardRewardId = nameCardRewardId;
-    }
-
-    public int getSatiationPenalty() {
-        return satiationPenalty;
-    }
-
-    public void setSatiationPenalty(int satiationPenalty) {
-        this.satiationPenalty = satiationPenalty;
-    }
-
-    public AvatarData getData() {
-        return data;
-    }
-
-    public long getGuid() {
-        return guid;
-    }
-
-    public int getAvatarId() {
-        return avatarId;
-    }
-
-    public int getLevel() {
-        return level;
-    }
-
-    public void setLevel(int level) {
-        this.level = level;
-    }
-
-    public int getExp() {
-        return exp;
-    }
-
-    public void setExp(int exp) {
-        this.exp = exp;
-    }
-
-    public int getPromoteLevel() {
-        return promoteLevel;
-    }
-
-    public void setPromoteLevel(int promoteLevel) {
-        this.promoteLevel = promoteLevel;
-    }
-
     static public int getMinPromoteLevel(int level) {
         if (level > 80) {
             return 6;
@@ -262,10 +198,6 @@ public class Avatar {
         return 0;
     }
 
-    public Int2ObjectMap<GameItem> getEquips() {
-        return equips;
-    }
-
     public GameItem getEquipBySlot(EquipType slot) {
         return this.getEquips().get(slot.getValue());
     }
@@ -278,14 +210,6 @@ public class Avatar {
         return this.getEquipBySlot(EquipType.EQUIP_WEAPON);
     }
 
-    public int getSkillDepotId() {
-        return skillDepotId;
-    }
-
-    public AvatarSkillDepotData getSkillDepot() {
-        return skillDepot;
-    }
-
     protected void setSkillDepot(AvatarSkillDepotData skillDepot) {
         if (this.skillDepot != null) return;
         this.skillDepot = skillDepot; // Used while loading this from the database
@@ -320,10 +244,6 @@ public class Avatar {
         }
     }
 
-    public Map<Integer, Integer> getSkillLevelMap() {
-        return skillLevelMap;
-    }
-
     public Map<Integer, Integer> getSkillExtraChargeMap() {
         if (skillExtraChargeMap == null) {
             skillExtraChargeMap = new HashMap<>();
@@ -331,14 +251,6 @@ public class Avatar {
         return skillExtraChargeMap;
     }
 
-    public Map<Integer, Integer> getProudSkillBonusMap() {
-        return proudSkillBonusMap;
-    }
-
-    public Set<String> getExtraAbilityEmbryos() {
-        return extraAbilityEmbryos;
-    }
-
     public void setFetterList(List<Integer> fetterList) {
         this.fetters = fetterList;
     }
@@ -347,38 +259,6 @@ public class Avatar {
         return fetters;
     }
 
-    public int getFetterLevel() {
-        return fetterLevel;
-    }
-
-    public void setFetterLevel(int fetterLevel) {
-        this.fetterLevel = fetterLevel;
-    }
-
-    public int getFetterExp() {
-        return fetterExp;
-    }
-
-    public void setFetterExp(int fetterExp) {
-        this.fetterExp = fetterExp;
-    }
-
-    public int getNameCardId() {
-        return nameCardId;
-    }
-
-    public void setNameCardId(int nameCardId) {
-        this.nameCardId = nameCardId;
-    }
-
-    public float getCurrentHp() {
-        return currentHp;
-    }
-
-    public void setCurrentHp(float currentHp) {
-        this.currentHp = currentHp;
-    }
-
     public void setCurrentEnergy() {
         if (GAME_OPTIONS.energyUsage) {
             this.setCurrentEnergy(this.currentEnergy);
@@ -427,42 +307,6 @@ public class Avatar {
         return getFightProperties().getOrDefault(prop.getId(), 0f);
     }
 
-    public Set<Integer> getTalentIdList() {
-        return talentIdList;
-    }
-
-    public int getCoreProudSkillLevel() {
-        return coreProudSkillLevel;
-    }
-
-    public void setCoreProudSkillLevel(int constLevel) {
-        this.coreProudSkillLevel = constLevel;
-    }
-
-    public Set<Integer> getProudSkillList() {
-        return proudSkillList;
-    }
-
-    public int getFlyCloak() {
-        return flyCloak;
-    }
-
-    public void setFlyCloak(int flyCloak) {
-        this.flyCloak = flyCloak;
-    }
-
-    public int getCostume() {
-        return costume;
-    }
-
-    public void setCostume(int costume) {
-        this.costume = costume;
-    }
-
-    public int getBornTime() {
-        return bornTime;
-    }
-
     public boolean equipItem(GameItem item, boolean shouldRecalc) {
         // Sanity check equip type
         EquipType itemEquipType = item.getItemData().getEquipType();
@@ -776,7 +620,7 @@ public class Avatar {
         this.getSkillExtraChargeMap().clear();
 
         // Sanity checks
-        if (getData() == null || getData().getSkillDepot() == null) {
+        if (getData() == null || this.skillDepot == null) {
             return;
         }
 
@@ -811,12 +655,12 @@ public class Avatar {
                 // Check if a skill can be boosted by +3 levels
                 int skillId = 0;
 
-                if (entry.getExtraTalentIndex() == 2 && this.getData().getSkillDepot().getSkills().size() >= 2) {
+                if (entry.getExtraTalentIndex() == 2 && this.skillDepot.getSkills().size() >= 2) {
                     // E skill
-                    skillId = this.getData().getSkillDepot().getSkills().get(1);
+                    skillId = this.skillDepot.getSkills().get(1);
                 } else if (entry.getExtraTalentIndex() == 9) {
                     // Ult skill
-                    skillId = this.getData().getSkillDepot().getEnergySkill();
+                    skillId = this.skillDepot.getEnergySkill();
                 }
 
                 // Sanity check
diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java
index 6fcad527..03d5abb7 100644
--- a/src/main/java/emu/grasscutter/game/player/Player.java
+++ b/src/main/java/emu/grasscutter/game/player/Player.java
@@ -1174,6 +1174,7 @@ public class Player {
         this.forgingManager.sendForgeDataNotify();
         this.resinManager.onPlayerLogin();
         this.cookingManager.sendCookDataNofity();
+        this.teamManager.onPlayerLogin();
 
         getTodayMoonCard(); // The timer works at 0:0, some users log in after that, use this method to check if they have received a reward today or not. If not, send the reward.
 
diff --git a/src/main/java/emu/grasscutter/game/player/TeamManager.java b/src/main/java/emu/grasscutter/game/player/TeamManager.java
index 8421b4ec..c6f118ad 100644
--- a/src/main/java/emu/grasscutter/game/player/TeamManager.java
+++ b/src/main/java/emu/grasscutter/game/player/TeamManager.java
@@ -34,25 +34,26 @@ import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify;
 import emu.grasscutter.server.packet.send.PacketSceneTeamUpdateNotify;
 import emu.grasscutter.server.packet.send.PacketSetUpAvatarTeamRsp;
 import emu.grasscutter.server.packet.send.PacketWorldPlayerDieNotify;
-import it.unimi.dsi.fastutil.ints.Int2IntMap;
-import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
 import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
 import it.unimi.dsi.fastutil.ints.IntSet;
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
+import lombok.Getter;
+import lombok.Setter;
 
 @Entity
 public class TeamManager extends BasePlayerDataManager {
-    private Map<Integer, TeamInfo> teams;
+    @Getter private Map<Integer, TeamInfo> teams;
     private int currentTeamIndex;
-    private int currentCharacterIndex;
+    @Getter @Setter private int currentCharacterIndex;
 
-    @Transient private TeamInfo mpTeam;
-    @Transient private int entityId;
+    @Transient @Getter @Setter private TeamInfo mpTeam;
+    @Transient @Getter @Setter private int entityId;
     @Transient private final List<EntityAvatar> avatars;
-    @Transient private final Set<EntityBaseGadget> gadgets;
-    @Transient private final IntSet teamResonances;
-    @Transient private final IntSet teamResonancesConfig;
+    @Transient @Getter private final Set<EntityBaseGadget> gadgets;
+    @Transient @Getter private final IntSet teamResonances;
+    @Transient @Getter private final IntSet teamResonancesConfig;
 
     @Transient private int useTemporarilyTeamIndex = -1;
     @Transient private List<TeamInfo> temporaryTeam; // Temporary Team for tower
@@ -80,18 +81,6 @@ public class TeamManager extends BasePlayerDataManager {
         return this.getPlayer().getWorld();
     }
 
-    public Map<Integer, TeamInfo> getTeams() {
-        return this.teams;
-    }
-
-    public TeamInfo getMpTeam() {
-        return mpTeam;
-    }
-
-    public void setMpTeam(TeamInfo mpTeam) {
-        this.mpTeam = mpTeam;
-    }
-
     /**
      * Search through all teams and if the team matches, return that index.
      * Otherwise, return -1.
@@ -115,14 +104,6 @@ public class TeamManager extends BasePlayerDataManager {
         this.currentTeamIndex = currentTeamIndex;
     }
 
-    public int getCurrentCharacterIndex() {
-        return currentCharacterIndex;
-    }
-
-    public void setCurrentCharacterIndex(int currentCharacterIndex) {
-        this.currentCharacterIndex = currentCharacterIndex;
-    }
-
     public long getCurrentCharacterGuid() {
         return this.getCurrentAvatarEntity().getAvatar().getGuid();
     }
@@ -142,26 +123,6 @@ public class TeamManager extends BasePlayerDataManager {
         return this.getTeams().get(this.currentTeamIndex);
     }
 
-    public int getEntityId() {
-        return entityId;
-    }
-
-    public void setEntityId(int entityId) {
-        this.entityId = entityId;
-    }
-
-    public Set<EntityBaseGadget> getGadgets() {
-        return gadgets;
-    }
-
-    public IntSet getTeamResonances() {
-        return teamResonances;
-    }
-
-    public IntSet getTeamResonancesConfig() {
-        return teamResonancesConfig;
-    }
-
     public List<EntityAvatar> getActiveTeam() {
         return avatars;
     }
@@ -290,32 +251,34 @@ public class TeamManager extends BasePlayerDataManager {
     }
 
     private void updateTeamResonances() {
-        Int2IntOpenHashMap map = new Int2IntOpenHashMap();
-
         this.getTeamResonances().clear();
         this.getTeamResonancesConfig().clear();
-
-        for (EntityAvatar entity : this.getActiveTeam()) {
-            AvatarSkillDepotData skillData = entity.getAvatar().getAvatarData().getSkillDepot();
-            if (skillData != null) {
-                map.addTo(skillData.getElementType().getValue(), 1);
-            }
-        }
-
-        for (Int2IntMap.Entry e : map.int2IntEntrySet()) {
-            if (e.getIntValue() >= 2) {
-                ElementType element = ElementType.getTypeByValue(e.getIntKey());
-                if (element.getTeamResonanceId() != 0) {
-                    this.getTeamResonances().add(element.getTeamResonanceId());
-                    this.getTeamResonancesConfig().add(element.getConfigHash());
-                }
-            }
-        }
-
-        // No resonances
-        if (this.getTeamResonances().size() == 0) {
-            this.getTeamResonances().add(ElementType.Default.getTeamResonanceId());
-            this.getTeamResonancesConfig().add(ElementType.Default.getTeamResonanceId());
+        // Official resonances require a full party
+        if (this.avatars.size() < 4) return;
+
+        // TODO: make this actually read from TeamResonanceExcelConfigData.json for the real resonances and conditions
+        // Currently we just hardcode these conditions, but this won't work for modded resources or future changes
+        var elementCounts = new Object2IntOpenHashMap<ElementType>();
+        this.getActiveTeam().stream()
+            .map(EntityAvatar::getAvatar).filter(Objects::nonNull)
+            .map(Avatar::getSkillDepot).filter(Objects::nonNull)
+            .map(AvatarSkillDepotData::getElementType).filter(Objects::nonNull)
+            .forEach(elementType -> elementCounts.addTo(elementType, 1));
+
+        // Dual element resonances
+        elementCounts.object2IntEntrySet().stream()
+            .filter(e -> e.getIntValue() >= 2)
+            .map(e -> e.getKey())
+            .filter(elementType -> elementType.getTeamResonanceId() != 0)
+            .forEach(elementType -> {
+                    this.teamResonances.add(elementType.getTeamResonanceId());
+                    this.teamResonancesConfig.add(elementType.getConfigHash());
+            });
+
+        // Four element resonance
+        if (elementCounts.size() >= 4) {
+            this.teamResonances.add(ElementType.Default.getTeamResonanceId());
+            this.teamResonancesConfig.add(ElementType.Default.getConfigHash());
         }
     }
 
@@ -677,4 +640,8 @@ public class TeamManager extends BasePlayerDataManager {
             entity.getAvatar().save();
         }
     }
+
+    public void onPlayerLogin() {  // Hack for now to fix resonances on login
+        this.updateTeamResonances();
+    }
 }
-- 
GitLab