From d20e9d1f72e28d2cabc48d0bcf35582938c9b50f Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Mon, 18 Jul 2022 20:42:22 -0700
Subject: [PATCH] Refactor player managers

---
 .../game/ability/AbilityManager.java          |   9 +-
 .../game/activity/ActivityManager.java        |   6 +-
 .../game/avatar/AvatarProfileData.java        |  26 --
 .../game/avatar/AvatarStorage.java            |  10 +-
 .../game/battlepass/BattlePassManager.java    |   7 +-
 .../grasscutter/game/friends/FriendsList.java |  11 +-
 .../grasscutter/game/inventory/Inventory.java |  12 +-
 .../grasscutter/game/mail/MailHandler.java    |  12 +-
 .../game/managers/CookingManager.java         |   7 +-
 .../game/managers/FurnitureManager.java       |   8 +-
 .../game/managers/InsectCaptureManager.java   |   8 +-
 .../game/managers/ResinManager.java           |   6 +-
 .../game/managers/SotSManager.java            |   6 +-
 .../collection/CollectionManager.java         |  74 -----
 .../deforestation/DeforestationManager.java   |  12 +-
 .../game/managers/energy/EnergyManager.java   |  10 +-
 .../game/managers/forging/ForgingManager.java |   6 +-
 .../managers/mapmark/MapMarksManager.java     |  31 +-
 .../game/managers/stamina/StaminaManager.java |   6 +-
 .../game/player/BasePlayerDataManager.java    |  23 ++
 .../game/player/BasePlayerManager.java        |  15 +
 .../emu/grasscutter/game/player/Player.java   | 314 +++++-------------
 .../game/player/PlayerOpenStateManager.java   |  10 +-
 .../grasscutter/game/player/TeamManager.java  |  17 +-
 .../grasscutter/game/quest/QuestManager.java  |  10 +-
 .../grasscutter/game/tower/TowerManager.java  |  54 +--
 .../HandlerEnterTransPointRegionNotify.java   |   2 +-
 .../HandlerExitTransPointRegionNotify.java    |   2 +-
 .../send/PacketHomeBasicInfoNotify.java       |   2 +-
 .../server/packet/send/PacketMarkMapRsp.java  |   2 +-
 30 files changed, 232 insertions(+), 486 deletions(-)
 delete mode 100644 src/main/java/emu/grasscutter/game/avatar/AvatarProfileData.java
 delete mode 100644 src/main/java/emu/grasscutter/game/managers/collection/CollectionManager.java
 create mode 100644 src/main/java/emu/grasscutter/game/player/BasePlayerDataManager.java
 create mode 100644 src/main/java/emu/grasscutter/game/player/BasePlayerManager.java

diff --git a/src/main/java/emu/grasscutter/game/ability/AbilityManager.java b/src/main/java/emu/grasscutter/game/ability/AbilityManager.java
index 394313ef..1464e571 100644
--- a/src/main/java/emu/grasscutter/game/ability/AbilityManager.java
+++ b/src/main/java/emu/grasscutter/game/ability/AbilityManager.java
@@ -21,6 +21,7 @@ import emu.grasscutter.game.entity.EntityItem;
 import emu.grasscutter.game.entity.GameEntity;
 import emu.grasscutter.game.entity.gadget.GadgetGatherObject;
 import emu.grasscutter.game.entity.gadget.GadgetGatherPoint;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.ElementType;
 import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall;
@@ -35,18 +36,14 @@ import emu.grasscutter.utils.Position;
 import emu.grasscutter.utils.Utils;
 import emu.grasscutter.game.props.FightProperty;
 
-public class AbilityManager {
+public class AbilityManager extends BasePlayerManager {
 	private Player player;
     HealAbilityManager healAbilityManager;
 	
 	public AbilityManager(Player player) {
-		this.player = player;
+		super(player);
         this.healAbilityManager = new HealAbilityManager(player);
 	}
-	
-	public Player getPlayer() {
-		return this.player;
-	}
 
 	public void onAbilityInvoke(AbilityInvokeEntry invoke) throws Exception {
         healAbilityManager.healHandler(invoke);
diff --git a/src/main/java/emu/grasscutter/game/activity/ActivityManager.java b/src/main/java/emu/grasscutter/game/activity/ActivityManager.java
index b511a262..b3cdb024 100644
--- a/src/main/java/emu/grasscutter/game/activity/ActivityManager.java
+++ b/src/main/java/emu/grasscutter/game/activity/ActivityManager.java
@@ -5,6 +5,7 @@ import com.google.gson.reflect.TypeToken;
 import emu.grasscutter.Grasscutter;
 import emu.grasscutter.data.DataLoader;
 import emu.grasscutter.data.GameData;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.ActivityType;
 import emu.grasscutter.game.props.WatcherTriggerType;
@@ -19,9 +20,8 @@ import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 
 @Getter
-public class ActivityManager {
+public class ActivityManager extends BasePlayerManager {
     private static final Map<Integer, ActivityConfigItem> activityConfigItemMap;
-    private final Player player;
     private final Map<Integer, PlayerActivityData> playerActivityDataMap;
 
     static {
@@ -79,7 +79,7 @@ public class ActivityManager {
     }
 
     public ActivityManager(Player player){
-        this.player = player;
+        super(player);
 
         playerActivityDataMap = new ConcurrentHashMap<>();
         // load data for player
diff --git a/src/main/java/emu/grasscutter/game/avatar/AvatarProfileData.java b/src/main/java/emu/grasscutter/game/avatar/AvatarProfileData.java
deleted file mode 100644
index b38855b8..00000000
--- a/src/main/java/emu/grasscutter/game/avatar/AvatarProfileData.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package emu.grasscutter.game.avatar;
-
-import dev.morphia.annotations.Entity;
-
-@Entity
-public class AvatarProfileData {
-	private int avatarId;
-	private int level;
-	
-	public AvatarProfileData(Avatar avatar) {
-		this.update(avatar);
-	}
-
-	public int getAvatarId() {
-		return avatarId;
-	}
-
-	public int getLevel() {
-		return level;
-	}
-
-	public void update(Avatar avatar) {
-		this.avatarId = avatar.getAvatarId();
-		this.level = avatar.getLevel();
-	}
-}
diff --git a/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java b/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java
index 8feae29c..3c359627 100644
--- a/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java
+++ b/src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java
@@ -9,6 +9,7 @@ import emu.grasscutter.data.excels.AvatarSkillDepotData;
 import emu.grasscutter.database.DatabaseHelper;
 import emu.grasscutter.game.entity.EntityAvatar;
 import emu.grasscutter.game.inventory.GameItem;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.server.packet.send.PacketAvatarChangeCostumeNotify;
 import emu.grasscutter.server.packet.send.PacketAvatarFlycloakChangeNotify;
@@ -17,20 +18,15 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
 import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
 import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
 
-public class AvatarStorage implements Iterable<Avatar> {
-	private final Player player;
+public class AvatarStorage extends BasePlayerManager implements Iterable<Avatar> {
 	private final Int2ObjectMap<Avatar> avatars;
 	private final Long2ObjectMap<Avatar> avatarsGuid;
 	
 	public AvatarStorage(Player player) {
-		this.player = player;
+		super(player);
 		this.avatars = new Int2ObjectOpenHashMap<>();
 		this.avatarsGuid = new Long2ObjectOpenHashMap<>();
 	}
-	
-	public Player getPlayer() {
-		return player;
-	}
 
 	public Int2ObjectMap<Avatar> getAvatars() {
 		return avatars;
diff --git a/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java b/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java
index 028312d9..2f74819f 100644
--- a/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java
+++ b/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java
@@ -15,7 +15,6 @@ import org.bson.types.ObjectId;
 import dev.morphia.annotations.Entity;
 import dev.morphia.annotations.Id;
 import dev.morphia.annotations.Indexed;
-import dev.morphia.annotations.Transient;
 import emu.grasscutter.GameConstants;
 import emu.grasscutter.Grasscutter;
 import emu.grasscutter.data.GameData;
@@ -26,6 +25,7 @@ import emu.grasscutter.data.excels.RewardData;
 import emu.grasscutter.database.DatabaseHelper;
 import emu.grasscutter.game.inventory.GameItem;
 import emu.grasscutter.game.inventory.MaterialType;
+import emu.grasscutter.game.player.BasePlayerDataManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.BattlePassMissionRefreshType;
 import emu.grasscutter.game.props.BattlePassMissionStatus;
@@ -41,9 +41,8 @@ import emu.grasscutter.server.packet.send.PacketTakeBattlePassRewardRsp;
 import lombok.Getter;
 
 @Entity(value = "battlepass", useDiscriminator = false)
-public class BattlePassManager {
+public class BattlePassManager extends BasePlayerDataManager {
 	@Id @Getter private ObjectId id;
-	@Transient @Getter private Player player;
 	
 	@Indexed private int ownerUid;
     @Getter private int point;
@@ -60,7 +59,7 @@ public class BattlePassManager {
     public BattlePassManager() {}
 
     public BattlePassManager(Player player) {
-        this.setPlayer(player);
+        super(player);
     }
     
     public void setPlayer(Player player) {
diff --git a/src/main/java/emu/grasscutter/game/friends/FriendsList.java b/src/main/java/emu/grasscutter/game/friends/FriendsList.java
index 70eace5c..39940629 100644
--- a/src/main/java/emu/grasscutter/game/friends/FriendsList.java
+++ b/src/main/java/emu/grasscutter/game/friends/FriendsList.java
@@ -3,6 +3,7 @@ package emu.grasscutter.game.friends;
 import java.util.List;
 
 import emu.grasscutter.database.DatabaseHelper;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.net.proto.DealAddFriendResultTypeOuterClass.DealAddFriendResultType;
 import emu.grasscutter.server.packet.send.PacketAskAddFriendNotify;
@@ -13,24 +14,18 @@ import emu.grasscutter.server.packet.send.PacketDeleteFriendRsp;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
 
-public class FriendsList {
-	private final Player player;
-	
+public class FriendsList extends BasePlayerManager {
 	private final Int2ObjectMap<Friendship> friends;
 	private final Int2ObjectMap<Friendship> pendingFriends;
 	
 	private boolean loaded = false;
 	
 	public FriendsList(Player player) {
-		this.player = player;
+		super(player);
 		this.friends = new Int2ObjectOpenHashMap<Friendship>();
 		this.pendingFriends = new Int2ObjectOpenHashMap<Friendship>();
 	}
 	
-	public Player getPlayer() {
-		return player;
-	}
-	
 	public boolean hasLoaded() {
 		return loaded;
 	}
diff --git a/src/main/java/emu/grasscutter/game/inventory/Inventory.java b/src/main/java/emu/grasscutter/game/inventory/Inventory.java
index a40a6ac5..f5660a95 100644
--- a/src/main/java/emu/grasscutter/game/inventory/Inventory.java
+++ b/src/main/java/emu/grasscutter/game/inventory/Inventory.java
@@ -15,6 +15,7 @@ import emu.grasscutter.data.excels.ItemData;
 import emu.grasscutter.database.DatabaseHelper;
 import emu.grasscutter.game.avatar.AvatarStorage;
 import emu.grasscutter.game.avatar.Avatar;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.ActionReason;
 import emu.grasscutter.game.props.PlayerProperty;
@@ -31,14 +32,13 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
 
 import static emu.grasscutter.Configuration.*;
 
-public class Inventory implements Iterable<GameItem> {
-	private final Player player;
-	
+public class Inventory extends BasePlayerManager implements Iterable<GameItem> {
 	private final Long2ObjectMap<GameItem> store;
 	private final Int2ObjectMap<InventoryTab> inventoryTypes;
 	
 	public Inventory(Player player) {
-		this.player = player;
+		super(player);
+		
 		this.store = new Long2ObjectOpenHashMap<>();
 		this.inventoryTypes = new Int2ObjectOpenHashMap<>();
 		
@@ -48,10 +48,6 @@ public class Inventory implements Iterable<GameItem> {
 		this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(INVENTORY_LIMITS.furniture));
 	}
 
-	public Player getPlayer() {
-		return player;
-	}
-	
 	public AvatarStorage getAvatarStorage() {
 		return this.getPlayer().getAvatars();
 	}
diff --git a/src/main/java/emu/grasscutter/game/mail/MailHandler.java b/src/main/java/emu/grasscutter/game/mail/MailHandler.java
index ad2f8469..12e74181 100644
--- a/src/main/java/emu/grasscutter/game/mail/MailHandler.java
+++ b/src/main/java/emu/grasscutter/game/mail/MailHandler.java
@@ -1,30 +1,26 @@
 package emu.grasscutter.game.mail;
 
-import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 import emu.grasscutter.Grasscutter;
 import emu.grasscutter.database.DatabaseHelper;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.server.event.player.PlayerReceiveMailEvent;
 import emu.grasscutter.server.packet.send.PacketDelMailRsp;
 import emu.grasscutter.server.packet.send.PacketMailChangeNotify;
 
-public class MailHandler {
-	private final Player player;
+public class MailHandler extends BasePlayerManager {
 	private final List<Mail> mail;
 	
 	public MailHandler(Player player) {
-		this.player = player;
+		super(player);
+		
 		this.mail = new ArrayList<>();
 	}
 
-	public Player getPlayer() {
-		return player;
-	}
-
 	public List<Mail> getMail() {
 		return mail;
 	}
diff --git a/src/main/java/emu/grasscutter/game/managers/CookingManager.java b/src/main/java/emu/grasscutter/game/managers/CookingManager.java
index 855fd56e..5964d4f1 100644
--- a/src/main/java/emu/grasscutter/game/managers/CookingManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/CookingManager.java
@@ -10,6 +10,7 @@ import emu.grasscutter.data.GameData;
 import emu.grasscutter.data.common.ItemParamData;
 import emu.grasscutter.data.excels.ItemData;
 import emu.grasscutter.game.inventory.GameItem;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.ActionReason;
 import emu.grasscutter.net.proto.CookRecipeDataOuterClass;
@@ -22,14 +23,12 @@ import emu.grasscutter.server.packet.send.PacketPlayerCookArgsRsp;
 import emu.grasscutter.server.packet.send.PacketPlayerCookRsp;
 import io.netty.util.internal.ThreadLocalRandom;
 
-public class CookingManager {
+public class CookingManager extends BasePlayerManager {
     private static final int MANUAL_PERFECT_COOK_QUALITY = 3;
-
     private static Set<Integer> defaultUnlockedRecipies;
-    private final Player player;
 
     public CookingManager(Player player) {
-        this.player = player;
+        super(player);
     }
 
     public static void initialize() {
diff --git a/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java b/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java
index 33d771df..d1811940 100644
--- a/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/FurnitureManager.java
@@ -4,6 +4,7 @@ import emu.grasscutter.data.GameData;
 import emu.grasscutter.data.common.ItemParamData;
 import emu.grasscutter.game.home.FurnitureMakeSlotItem;
 import emu.grasscutter.game.inventory.GameItem;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.net.proto.ItemParamOuterClass;
 import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
@@ -13,11 +14,10 @@ import emu.grasscutter.utils.Utils;
 import java.util.ArrayList;
 import java.util.List;
 
-public class FurnitureManager {
-    private final Player player;
-
+public class FurnitureManager extends BasePlayerManager {
+    
     public FurnitureManager(Player player) {
-        this.player = player;
+        super(player);
     }
 
     public void onLogin(){
diff --git a/src/main/java/emu/grasscutter/game/managers/InsectCaptureManager.java b/src/main/java/emu/grasscutter/game/managers/InsectCaptureManager.java
index 9fe5623b..42a21bbb 100644
--- a/src/main/java/emu/grasscutter/game/managers/InsectCaptureManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/InsectCaptureManager.java
@@ -8,11 +8,17 @@ import emu.grasscutter.game.entity.EntityMonster;
 import emu.grasscutter.game.entity.EntityVehicle;
 import emu.grasscutter.game.entity.GameEntity;
 import emu.grasscutter.game.inventory.GameItem;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.ActionReason;
 import emu.grasscutter.net.proto.VisionTypeOuterClass;
 
-public record InsectCaptureManager(Player player) {
+public class InsectCaptureManager extends BasePlayerManager {
+    
+    public InsectCaptureManager(Player player) {
+        super(player);
+    }
+
     public void arrestSmallCreature(GameEntity entity) {
         //System.out.println("arrestSmallCreature!");
         EnvAnimalGatherConfigData gather;
diff --git a/src/main/java/emu/grasscutter/game/managers/ResinManager.java b/src/main/java/emu/grasscutter/game/managers/ResinManager.java
index 76393c7f..2fefe88e 100644
--- a/src/main/java/emu/grasscutter/game/managers/ResinManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/ResinManager.java
@@ -1,5 +1,6 @@
 package emu.grasscutter.game.managers;
 
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.PlayerProperty;
 import emu.grasscutter.game.props.WatcherTriggerType;
@@ -9,11 +10,10 @@ import emu.grasscutter.utils.Utils;
 
 import static emu.grasscutter.Configuration.GAME_OPTIONS;
 
-public class ResinManager {
-    private final Player player;
+public class ResinManager extends BasePlayerManager {
 
     public ResinManager(Player player) {
-        this.player = player;
+        super(player);
     }
 
     /********************
diff --git a/src/main/java/emu/grasscutter/game/managers/SotSManager.java b/src/main/java/emu/grasscutter/game/managers/SotSManager.java
index c1d1326a..8002fafa 100644
--- a/src/main/java/emu/grasscutter/game/managers/SotSManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/SotSManager.java
@@ -3,6 +3,7 @@ package emu.grasscutter.game.managers;
 import ch.qos.logback.classic.Logger;
 import emu.grasscutter.Grasscutter;
 import emu.grasscutter.game.entity.EntityAvatar;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.FightProperty;
 import emu.grasscutter.game.props.PlayerProperty;
@@ -16,11 +17,10 @@ import java.util.Timer;
 import java.util.TimerTask;
 
 // Statue of the Seven Manager
-public class SotSManager {
+public class SotSManager extends BasePlayerManager {
 
     // NOTE: Spring volume balance *1  = fight prop HP *100
 
-    private final Player player;
     private final Logger logger = Grasscutter.getLogger();
     private Timer autoRecoverTimer;
     private final boolean enablePriorityHealing = false;
@@ -28,7 +28,7 @@ public class SotSManager {
     public final static int GlobalMaximumSpringVolume = PlayerProperty.PROP_MAX_SPRING_VOLUME.getMax();
 
     public SotSManager(Player player) {
-        this.player = player;
+        super(player);
     }
 
     public boolean getIsAutoRecoveryEnabled() {
diff --git a/src/main/java/emu/grasscutter/game/managers/collection/CollectionManager.java b/src/main/java/emu/grasscutter/game/managers/collection/CollectionManager.java
deleted file mode 100644
index 47f21b45..00000000
--- a/src/main/java/emu/grasscutter/game/managers/collection/CollectionManager.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package emu.grasscutter.game.managers.collection;
-
-import java.util.HashMap;
-import java.util.List;
-
-import emu.grasscutter.game.entity.EntityGadget;
-import emu.grasscutter.game.player.Player;
-
-public class CollectionManager {
-    private static final long SECOND = 1000; //1 Second
-    private static final long MINUTE = SECOND*60; //1 Minute
-    private static final long HOUR = MINUTE*60; //1 Hour
-    private static final long DAY = HOUR*24; //1 Day
-    private static final HashMap<Integer,Long> DEFINE_REFRESH_TIME = new HashMap<>();// <GadgetId,Waiting Millisecond>
-    private static final long DEFAULT_REFRESH_TIME = HOUR*6; // default 6 Hours
-
-    static {
-        DEFINE_REFRESH_TIME.put(70590027,3*DAY);//鏄熼摱鐭跨煶 3 Days
-        DEFINE_REFRESH_TIME.put(70590036,3*DAY);//绱櫠鍧� 3 Days
-        DEFINE_REFRESH_TIME.put(70520003,3*DAY);//姘存櫠 3 Days
-
-        DEFINE_REFRESH_TIME.put(70590013,2*DAY);//鍢熷槦鑾� 2 Days
-        DEFINE_REFRESH_TIME.put(70540029,2*DAY);//娓呭績 2 Days
-        DEFINE_REFRESH_TIME.put(70540028,2*DAY);//鏄熻灪 2 Days
-        DEFINE_REFRESH_TIME.put(70540027,2*DAY);//椹熬 2 Days
-        DEFINE_REFRESH_TIME.put(70540026,2*DAY);//鐞夌拑琚� 2 Days
-        DEFINE_REFRESH_TIME.put(70540022,2*DAY);//钀借惤鑾� 2 Days
-        DEFINE_REFRESH_TIME.put(70540020,2*DAY);//鎱曢铇戣弴 2 Days
-        DEFINE_REFRESH_TIME.put(70540019,2*DAY);//椋庤溅鑿� 2 Days
-        DEFINE_REFRESH_TIME.put(70540018,2*DAY);//濉炶タ鑾変簹鑺� 2 Days
-        DEFINE_REFRESH_TIME.put(70540015,2*DAY);//闇撹3鑺� 2 Days
-        DEFINE_REFRESH_TIME.put(70540014,2*DAY);//鑾茶摤 2 Days 
-        DEFINE_REFRESH_TIME.put(70540013,2*DAY);//閽╅挬鏋� 2 Days
-        DEFINE_REFRESH_TIME.put(70540012,2*DAY);//鐞夌拑鐧惧悎 2 Days
-        DEFINE_REFRESH_TIME.put(70540008,2*DAY);//缁濅簯妞掓 2 Days
-        DEFINE_REFRESH_TIME.put(70520018,2*DAY);//澶滄硦鐭� 2 Days
-        DEFINE_REFRESH_TIME.put(70520002,2*DAY);//鐧介搧鐭� 2 Days
-        DEFINE_REFRESH_TIME.put(70510012,2*DAY);//鐭崇弨 2 Days
-        DEFINE_REFRESH_TIME.put(70510009,2*DAY);//钂插叕鑻� 2 Days
-        DEFINE_REFRESH_TIME.put(70510007,2*DAY);//鍐伴浘鑺� 2 Days
-        DEFINE_REFRESH_TIME.put(70510006,2*DAY);//鐑堢劙鑺� 2 Days
-        DEFINE_REFRESH_TIME.put(70510005,2*DAY);//鐢垫皵姘存櫠 2 Days
-        DEFINE_REFRESH_TIME.put(70510004,2*DAY);//灏忕伅鑽� 2 Days
-
-
-        DEFINE_REFRESH_TIME.put(70540021,DAY);//鏃ヨ惤鏋� 1 Day
-        DEFINE_REFRESH_TIME.put(70540005,DAY);//鏉炬灉 1 Day
-        DEFINE_REFRESH_TIME.put(70540003,DAY);//鑻规灉 1 Day
-        DEFINE_REFRESH_TIME.put(70540001,DAY);//鏍戣帗 1 Day
-        DEFINE_REFRESH_TIME.put(70520019,DAY);//榄旀櫠鍧� 1 Days
-        DEFINE_REFRESH_TIME.put(70520008,DAY);//閲戦奔鑽� 1 Days
-        DEFINE_REFRESH_TIME.put(70520007,DAY);//鐧借悵鍗� 1 Days
-        DEFINE_REFRESH_TIME.put(70520006,DAY);//鑳¤悵鍗� 1 Days
-        DEFINE_REFRESH_TIME.put(70520004,DAY);//铇戣弴 1 Day
-        DEFINE_REFRESH_TIME.put(70520001,DAY);//閾佺熆 1 Day
-
-        DEFINE_REFRESH_TIME.put(70520009,12*HOUR);//钖勮嵎 12 Hours
-        DEFINE_REFRESH_TIME.put(70520005,12*HOUR);//鐢滅敎鑺� 12 Hours
-    }
-    
-    private final static HashMap<Integer, List<CollectionData>> CollectionResourcesData = new HashMap<>();
-    private final HashMap<CollectionData,EntityGadget> spawnedEntities = new HashMap<>();
-    private CollectionRecordStore collectionRecordStore;
-    Player player;
-    
-    private static long getGadgetRefreshTime(int gadgetId){
-        return DEFINE_REFRESH_TIME.getOrDefault(gadgetId,DEFAULT_REFRESH_TIME);
-    }
-    
-    public synchronized void setPlayer(Player player) {
-        this.player = player;
-        this.collectionRecordStore = player.getCollectionRecordStore();
-    }
-}
diff --git a/src/main/java/emu/grasscutter/game/managers/deforestation/DeforestationManager.java b/src/main/java/emu/grasscutter/game/managers/deforestation/DeforestationManager.java
index 3650bdb3..a0fb4658 100644
--- a/src/main/java/emu/grasscutter/game/managers/deforestation/DeforestationManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/deforestation/DeforestationManager.java
@@ -7,20 +7,21 @@ import dev.morphia.annotations.Transient;
 import emu.grasscutter.Grasscutter;
 import emu.grasscutter.data.GameData;
 import emu.grasscutter.game.entity.EntityItem;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.world.Scene;
 import emu.grasscutter.net.proto.HitTreeNotifyOuterClass;
 import emu.grasscutter.net.proto.VectorOuterClass;
 import emu.grasscutter.utils.Position;
 
-public class DeforestationManager {
+public class DeforestationManager extends BasePlayerManager {
     final static int RECORD_EXPIRED_SECONDS = 60*5; // 5 min
     final static int RECORD_MAX_TIMES = 3; // max number of wood
     final static int RECORD_MAX_TIMES_OTHER_HIT_TREE = 10; // if hit 10 times other trees, reset wood
 
-    @Transient private final Player player;
-    @Transient private final ArrayList<HitTreeRecord> currentRecord;
-    @Transient private final static HashMap<Integer, Integer> ColliderTypeToWoodItemID = new HashMap<>();
+    private final ArrayList<HitTreeRecord> currentRecord;
+    private final static HashMap<Integer, Integer> ColliderTypeToWoodItemID = new HashMap<>();
+    
     static {
         /* define wood types which reflected to item id*/
         ColliderTypeToWoodItemID.put(1,101301);
@@ -36,8 +37,9 @@ public class DeforestationManager {
         ColliderTypeToWoodItemID.put(11,101311);
         ColliderTypeToWoodItemID.put(12,101312);
     }
+    
     public DeforestationManager(Player player){
-        this.player = player;
+        super(player);
         this.currentRecord = new ArrayList<>();
     }
     public void resetWood(){
diff --git a/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java b/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java
index 0ba5a5df..e688267d 100644
--- a/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java
@@ -13,6 +13,7 @@ import emu.grasscutter.game.entity.EntityItem;
 import emu.grasscutter.game.entity.EntityMonster;
 import emu.grasscutter.game.entity.GameEntity;
 import emu.grasscutter.game.inventory.GameItem;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.ElementType;
 import emu.grasscutter.game.props.FightProperty;
@@ -46,8 +47,7 @@ import static java.util.Map.entry;
 import com.google.gson.reflect.TypeToken;
 import com.google.protobuf.InvalidProtocolBufferException;
 
-public class EnergyManager {
-    private final Player player;
+public class EnergyManager extends BasePlayerManager {
     private final Map<EntityAvatar, Integer> avatarNormalProbabilities;
 //    energyUsage for each player
     private Boolean energyUsage;
@@ -55,15 +55,11 @@ public class EnergyManager {
     private final static Int2ObjectMap<List<SkillParticleGenerationInfo>> skillParticleGenerationData = new Int2ObjectOpenHashMap<>();
 
     public EnergyManager(Player player) {
-        this.player = player;
+        super(player);
         this.avatarNormalProbabilities = new HashMap<>();
         this.energyUsage=GAME_OPTIONS.energyUsage;
     }
 
-    public Player getPlayer() {
-        return this.player;
-    }
-
     public static void initialize() {
         // Read the data we need for monster energy drops.
         try (Reader fileReader = new InputStreamReader(DataLoader.load("EnergyDrop.json"))) {
diff --git a/src/main/java/emu/grasscutter/game/managers/forging/ForgingManager.java b/src/main/java/emu/grasscutter/game/managers/forging/ForgingManager.java
index 54ad374e..9cd3dc63 100644
--- a/src/main/java/emu/grasscutter/game/managers/forging/ForgingManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/forging/ForgingManager.java
@@ -11,6 +11,7 @@ import emu.grasscutter.data.common.ItemParamData;
 import emu.grasscutter.data.excels.ForgeData;
 import emu.grasscutter.data.excels.ItemData;
 import emu.grasscutter.game.inventory.GameItem;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.ActionReason;
 import emu.grasscutter.game.props.WatcherTriggerType;
@@ -27,11 +28,10 @@ import emu.grasscutter.server.packet.send.PacketForgeQueueManipulateRsp;
 import emu.grasscutter.server.packet.send.PacketForgeStartRsp;
 import emu.grasscutter.utils.Utils;
 
-public class ForgingManager {
-	private final Player player;
+public class ForgingManager extends BasePlayerManager {
 
 	public ForgingManager(Player player) {
-		this.player = player;
+		super(player);
 	}
 
 	/**********
diff --git a/src/main/java/emu/grasscutter/game/managers/mapmark/MapMarksManager.java b/src/main/java/emu/grasscutter/game/managers/mapmark/MapMarksManager.java
index 1fa36ec5..dfde7a0e 100644
--- a/src/main/java/emu/grasscutter/game/managers/mapmark/MapMarksManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/mapmark/MapMarksManager.java
@@ -1,5 +1,6 @@
 package emu.grasscutter.game.managers.mapmark;
 
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.net.proto.MapMarkPointTypeOuterClass.MapMarkPointType;
 import emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq;
@@ -9,16 +10,17 @@ import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify;
 import emu.grasscutter.utils.Position;
 
 import java.util.HashMap;
+import java.util.Map;
 
-public class MapMarksManager {
+public class MapMarksManager extends BasePlayerManager {
     public static final int mapMarkMaxCount = 150;
-    private HashMap<String, MapMark> mapMarks;
-    private final Player player;
 
     public MapMarksManager(Player player) {
-        this.player = player;
-        this.mapMarks = player.getMapMarks();
-        if (this.mapMarks == null) { this.mapMarks = new HashMap<>(); }
+        super(player);
+    }
+    
+    public Map<String, MapMark> getMapMarks() {
+        return getPlayer().getMapMarks();
     }
 
     public void handleMapMarkReq(MarkMapReq req) {
@@ -45,31 +47,26 @@ public class MapMarksManager {
             }
         }
         if (op != Operation.OPERATION_GET) {
-            saveMapMarks();
+            save();
         }
         player.getSession().send(new PacketMarkMapRsp(getMapMarks()));
     }
-
-    public HashMap<String, MapMark> getMapMarks() {
-        return mapMarks;
-    }
-
+    
     public String getMapMarkKey(Position position) {
         return "x" + (int)position.getX()+ "z" + (int)position.getZ();
     }
 
     public void removeMapMark(Position position) {
-        mapMarks.remove(getMapMarkKey(position));
+        getMapMarks().remove(getMapMarkKey(position));
     }
 
     public void addMapMark(MapMark mapMark) {
-        if (mapMarks.size() < mapMarkMaxCount) {
-            mapMarks.put(getMapMarkKey(mapMark.getPosition()), mapMark);
+        if (getMapMarks().size() < mapMarkMaxCount) {
+            getMapMarks().put(getMapMarkKey(mapMark.getPosition()), mapMark);
         }
     }
 
-    private void saveMapMarks() {
-        player.setMapMarks(mapMarks);
+    private void save() {
         player.save();
     }
 
diff --git a/src/main/java/emu/grasscutter/game/managers/stamina/StaminaManager.java b/src/main/java/emu/grasscutter/game/managers/stamina/StaminaManager.java
index 6b9b0302..e72d737e 100644
--- a/src/main/java/emu/grasscutter/game/managers/stamina/StaminaManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/stamina/StaminaManager.java
@@ -5,6 +5,7 @@ import emu.grasscutter.Grasscutter;
 import emu.grasscutter.game.avatar.Avatar;
 import emu.grasscutter.game.entity.EntityAvatar;
 import emu.grasscutter.game.entity.GameEntity;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.props.FightProperty;
 import emu.grasscutter.game.props.LifeState;
@@ -25,10 +26,9 @@ import java.util.*;
 
 import static emu.grasscutter.Configuration.GAME_OPTIONS;
 
-public class StaminaManager {
+public class StaminaManager extends BasePlayerManager {
 
     // TODO: Skiff state detection?
-    private final Player player;
     private static final HashMap<String, HashSet<MotionState>> MotionStatesCategorized = new HashMap<>() {{
         put("CLIMB", new HashSet<>(List.of(
                 MotionState.MOTION_STATE_CLIMB, // sustained, when not moving no cost no recover
@@ -163,7 +163,7 @@ public class StaminaManager {
     }
 
     public StaminaManager(Player player) {
-        this.player = player;
+        super(player);
     }
 
     // Accessors
diff --git a/src/main/java/emu/grasscutter/game/player/BasePlayerDataManager.java b/src/main/java/emu/grasscutter/game/player/BasePlayerDataManager.java
new file mode 100644
index 00000000..68447e89
--- /dev/null
+++ b/src/main/java/emu/grasscutter/game/player/BasePlayerDataManager.java
@@ -0,0 +1,23 @@
+package emu.grasscutter.game.player;
+
+import lombok.NonNull;
+
+public abstract class BasePlayerDataManager {
+    protected transient Player player;
+    
+    public BasePlayerDataManager() {}
+    
+    public BasePlayerDataManager(@NonNull Player player) {
+        this.player = player;
+    }
+    
+    public Player getPlayer() {
+        return this.player;
+    }
+    
+    public void setPlayer(Player player) {
+        if (this.player == null) {
+            this.player = player;
+        }
+    }
+}
diff --git a/src/main/java/emu/grasscutter/game/player/BasePlayerManager.java b/src/main/java/emu/grasscutter/game/player/BasePlayerManager.java
new file mode 100644
index 00000000..24023f72
--- /dev/null
+++ b/src/main/java/emu/grasscutter/game/player/BasePlayerManager.java
@@ -0,0 +1,15 @@
+package emu.grasscutter.game.player;
+
+import lombok.NonNull;
+
+public abstract class BasePlayerManager {
+    protected transient final Player player;
+    
+    public BasePlayerManager(@NonNull Player player) {
+        this.player = player;
+    }
+    
+    public Player getPlayer() {
+        return this.player;
+    }
+}
diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java
index d4be0f3a..e287fcb1 100644
--- a/src/main/java/emu/grasscutter/game/player/Player.java
+++ b/src/main/java/emu/grasscutter/game/player/Player.java
@@ -4,7 +4,6 @@ import dev.morphia.annotations.*;
 import emu.grasscutter.GameConstants;
 import emu.grasscutter.Grasscutter;
 import emu.grasscutter.data.GameData;
-import emu.grasscutter.data.excels.PersonalLineData;
 import emu.grasscutter.data.excels.PlayerLevelData;
 import emu.grasscutter.data.excels.WeatherData;
 import emu.grasscutter.database.DatabaseHelper;
@@ -13,7 +12,6 @@ import emu.grasscutter.game.CoopRequest;
 import emu.grasscutter.game.ability.AbilityManager;
 import emu.grasscutter.game.activity.ActivityManager;
 import emu.grasscutter.game.avatar.Avatar;
-import emu.grasscutter.game.avatar.AvatarProfileData;
 import emu.grasscutter.game.avatar.AvatarStorage;
 import emu.grasscutter.game.battlepass.BattlePassManager;
 import emu.grasscutter.game.entity.EntityMonster;
@@ -34,7 +32,6 @@ import emu.grasscutter.game.managers.CookingManager;
 import emu.grasscutter.game.managers.FurnitureManager;
 import emu.grasscutter.game.managers.InsectCaptureManager;
 import emu.grasscutter.game.managers.ResinManager;
-import emu.grasscutter.game.managers.collection.CollectionManager;
 import emu.grasscutter.game.managers.collection.CollectionRecordStore;
 import emu.grasscutter.game.managers.deforestation.DeforestationManager;
 import emu.grasscutter.game.managers.energy.EnergyManager;
@@ -91,11 +88,11 @@ import static emu.grasscutter.Configuration.*;
 
 @Entity(value = "players", useDiscriminator = false)
 public class Player {
-
 	@Id private int id;
 	@Indexed(options = @IndexOptions(unique = true)) private String accountId;
-
-	@Transient private Account account;
+	private transient Account account;
+	private transient GameSession session;
+	
 	private String nickname;
 	private String signature;
 	private int headImage;
@@ -104,22 +101,29 @@ public class Player {
 	private Position rotation;
 	private PlayerBirthday birthday;
 	private PlayerCodex codex;
-    @Getter private PlayerOpenStateManager openStateManager;
+	private boolean showAvatars;
+	private List<Integer> showAvatarList;
 	private Map<Integer, Integer> properties;
-	private Set<Integer> nameCardList;
-	private Set<Integer> flyCloakList;
-	private Set<Integer> costumeList;
-	private Set<Integer> unlockedForgingBlueprints;
-	private Set<Integer> unlockedCombines;
-	private Set<Integer> unlockedFurniture;
-	private Set<Integer> unlockedFurnitureSuite;
-	private List<ActiveForgeData> activeForges;
-	private Map<Integer, Integer> unlockedRecipies;
-
-	private Integer widgetId;
-
-	private Set<Integer> realmList;
-	private Integer currentRealmId;
+	private int currentRealmId;
+	private int widgetId;
+	private int sceneId;
+    private int regionId;
+    private int mainCharacterId;
+    private boolean godmode;
+    private boolean stamina;
+    
+    @Getter private Set<Integer> nameCardList;
+    @Getter private Set<Integer> flyCloakList;
+    @Getter private Set<Integer> costumeList;
+    @Getter private Set<Integer> rewardedLevels;
+    @Getter private Set<Integer> realmList;
+    @Getter private Set<Integer> unlockedForgingBlueprints;
+    @Getter private Set<Integer> unlockedCombines;
+    @Getter private Set<Integer> unlockedFurniture;
+    @Getter private Set<Integer> unlockedFurnitureSuite;
+    @Getter private Map<Long, ExpeditionInfo> expeditionInfo;
+    @Getter private Map<Integer, Integer> unlockedRecipies;
+    @Getter private List<ActiveForgeData> activeForges;
 
 	@Transient private long nextGuid = 0;
 	@Transient private int peerId;
@@ -127,71 +131,56 @@ public class Player {
 	@Transient private Scene scene;
 	@Transient @Getter private int weatherId = 0;
 	@Transient @Getter private ClimateType climate = ClimateType.CLIMATE_SUNNY;
-	@Transient private GameSession session;
-	@Transient private AvatarStorage avatars;
-	@Transient private Inventory inventory;
-	@Transient private FriendsList friendsList;
-	@Transient private MailHandler mailHandler;
-	@Transient private MessageHandler messageHandler;
-	@Transient private AbilityManager abilityManager;
-	@Transient private QuestManager questManager;
-
-	@Transient private SotSManager sotsManager;
-	@Transient private InsectCaptureManager insectCaptureManager;
-
-	private TeamManager teamManager;
-
-	@Transient private TowerManager towerManager;
+	
+	// Player managers go here
+	@Getter private transient AvatarStorage avatars;
+	@Getter private transient Inventory inventory;
+	@Getter private transient FriendsList friendsList;
+	@Getter private transient MailHandler mailHandler;
+	@Getter private transient MessageHandler messageHandler;
+	@Getter private transient AbilityManager abilityManager;
+	@Getter private transient QuestManager questManager;
+	@Getter private transient TowerManager towerManager;
+	@Getter private transient SotSManager sotsManager;
+	@Getter private transient InsectCaptureManager insectCaptureManager;
+    @Getter private transient MapMarksManager mapMarksManager;
+    @Getter private transient StaminaManager staminaManager;
+    @Getter private transient EnergyManager energyManager;
+    @Getter private transient ResinManager resinManager;
+    @Getter private transient ForgingManager forgingManager;
+    @Getter private transient DeforestationManager deforestationManager;
+    @Getter private transient FurnitureManager furnitureManager;
+    @Getter private transient BattlePassManager battlePassManager;
+    @Getter private transient CookingManager cookingManager;
+    @Getter private transient ActivityManager activityManager;
+
+    // Manager data (Save-able to the database)
+    private PlayerProfile playerProfile;
+    private TeamManager teamManager;
 	private TowerData towerData;
 	private PlayerGachaInfo gachaInfo;
-	private PlayerProfile playerProfile;
-	private boolean showAvatar;
-	private ArrayList<AvatarProfileData> shownAvatars;
-	private Set<Integer> rewardedLevels;
+	private PlayerOpenStateManager openStateManager;
+	private CollectionRecordStore collectionRecordStore;
 	private ArrayList<ShopLimit> shopLimit;
-	private Map<Long, ExpeditionInfo> expeditionInfo;
-
-	private int sceneId;
-	private int regionId;
-	private int mainCharacterId;
-	private boolean godmode;
-	private boolean stamina;
+	
+	@Getter private transient GameHome home;
 
 	private boolean moonCard;
 	private Date moonCardStartTime;
 	private int moonCardDuration;
 	private Set<Date> moonCardGetTimes;
 
-	private List<Integer> showAvatarList;
-	private boolean showAvatars;
-
 	@Transient private boolean paused;
 	@Transient private int enterSceneToken;
 	@Transient private SceneLoadState sceneState;
 	@Transient private boolean hasSentAvatarDataNotify;
 	@Transient private long nextSendPlayerLocTime = 0;
 
-	@Transient private final Int2ObjectMap<CoopRequest> coopRequests;
-	@Transient private final Queue<AttackResult> attackResults;
-	@Transient private final InvokeHandler<CombatInvokeEntry> combatInvokeHandler;
-	@Transient private final InvokeHandler<AbilityInvokeEntry> abilityInvokeHandler;
-	@Transient private final InvokeHandler<AbilityInvokeEntry> clientAbilityInitFinishHandler;
-
-	@Transient private MapMarksManager mapMarksManager;
-	@Transient private StaminaManager staminaManager;
-	@Transient private EnergyManager energyManager;
-	@Transient private ResinManager resinManager;
-	@Transient private ForgingManager forgingManager;
-	@Transient private DeforestationManager deforestationManager;
-	@Transient private GameHome home;
-	@Transient private FurnitureManager furnitureManager;
-	@Transient private BattlePassManager battlePassManager;
-	@Transient private CookingManager cookingManager;
-	// @Transient private
-	@Getter @Transient private ActivityManager activityManager;
-
-	@Transient private CollectionManager collectionManager;
-	private CollectionRecordStore collectionRecordStore;
+	private transient final Int2ObjectMap<CoopRequest> coopRequests;
+	private transient final Queue<AttackResult> attackResults;
+	@Getter private transient final InvokeHandler<CombatInvokeEntry> combatInvokeHandler;
+	@Getter private transient final InvokeHandler<AbilityInvokeEntry> abilityInvokeHandler;
+	@Getter private transient final InvokeHandler<AbilityInvokeEntry> clientAbilityInitFinishHandler;
 
 	private long springLastUsed;
 	private HashMap<String, MapMark> mapMarks;
@@ -209,8 +198,8 @@ public class Player {
 		this.abilityManager = new AbilityManager(this);
 		this.deforestationManager = new DeforestationManager(this);
 		this.insectCaptureManager = new InsectCaptureManager(this);
-
-		this.setQuestManager(new QuestManager(this));
+		this.questManager = new QuestManager(this);
+		
 		this.pos = new Position();
 		this.rotation = new Position();
 		this.properties = new HashMap<>();
@@ -374,10 +363,6 @@ public class Player {
 		this.session.send(new PacketSceneAreaWeatherNotify(this));
 	}
 
-	public int getGmLevel() {
-		return 1;
-	}
-
 	public String getNickname() {
 		return nickname;
 	}
@@ -413,10 +398,6 @@ public class Player {
 		this.widgetId = widgetId;
 	}
 
-	public Set<Integer> getRealmList() {
-		return realmList;
-	}
-
 	public void setRealmList(Set<Integer> realmList) {
 		this.realmList = realmList;
 	}
@@ -430,16 +411,14 @@ public class Player {
 		this.realmList.add(realmId);
 	}
 
-	public Integer getCurrentRealmId() {
+	public int getCurrentRealmId() {
 		return currentRealmId;
 	}
 
-	public void setCurrentRealmId(Integer currentRealmId) {
+	public void setCurrentRealmId(int currentRealmId) {
 		this.currentRealmId = currentRealmId;
 	}
-	public GameHome getHome(){
-		return home;
-	}
+	
 	public Position getPos() {
 		return pos;
 	}
@@ -598,10 +577,6 @@ public class Player {
 		return this.teamManager;
 	}
 
-	public TowerManager getTowerManager() {
-		return towerManager;
-	}
-
 	public TowerData getTowerData() {
 		if (towerData == null) {
 			// because of mistake, null may be saved as storage at some machine, this if can be removed in future
@@ -610,14 +585,6 @@ public class Player {
 		return towerData;
 	}
 
-	public QuestManager getQuestManager() {
-		return questManager;
-	}
-
-	public void setQuestManager(QuestManager questManager) {
-		this.questManager = questManager;
-	}
-
 	public PlayerGachaInfo getGachaInfo() {
 		return gachaInfo;
 	}
@@ -647,42 +614,6 @@ public class Player {
 		return getProperties().get(prop.getId());
 	}
 
-	public Set<Integer> getFlyCloakList() {
-		return flyCloakList;
-	}
-
-	public Set<Integer> getCostumeList() {
-		return costumeList;
-	}
-
-	public Set<Integer> getNameCardList() {
-		return this.nameCardList;
-	}
-
-	public Set<Integer> getUnlockedForgingBlueprints() {
-		return this.unlockedForgingBlueprints;
-	}
-
-	public Set<Integer> getUnlockedCombines() {
-		return this.unlockedCombines;
-	}
-
-	public Set<Integer> getUnlockedFurniture() {
-		return unlockedFurniture;
-	}
-
-	public Set<Integer> getUnlockedFurnitureSuite() {
-		return unlockedFurnitureSuite;
-	}
-
-	public List<ActiveForgeData> getActiveForges() {
-		return this.activeForges;
-	}
-
-	public Map<Integer, Integer> getUnlockedRecipies() {
-		return this.unlockedRecipies;
-	}
-
 	public MpSettingType getMpSetting() {
 		return MpSettingType.MP_SETTING_TYPE_ENTER_AFTER_APPLY; // TEMP
 	}
@@ -695,34 +626,6 @@ public class Player {
 		return coopRequests;
 	}
 
-	public InvokeHandler<CombatInvokeEntry> getCombatInvokeHandler() {
-		return this.combatInvokeHandler;
-	}
-
-	public InvokeHandler<AbilityInvokeEntry> getAbilityInvokeHandler() {
-		return this.abilityInvokeHandler;
-	}
-
-	public InvokeHandler<AbilityInvokeEntry> getClientAbilityInitFinishHandler() {
-		return clientAbilityInitFinishHandler;
-	}
-
-	public AvatarStorage getAvatars() {
-		return avatars;
-	}
-
-	public Inventory getInventory() {
-		return inventory;
-	}
-
-	public FriendsList getFriendsList() {
-		return this.friendsList;
-	}
-
-	public MailHandler getMailHandler() {
-		return mailHandler;
-	}
-
 	public int getEnterSceneToken() {
 		return enterSceneToken;
 	}
@@ -931,10 +834,6 @@ public class Player {
 		session.send(new PacketCardProductRewardNotify(getMoonCardRemainDays()));
 	}
 
-	public Map<Long, ExpeditionInfo> getExpeditionInfo() {
-		return expeditionInfo;
-	}
-
 	public void addExpeditionInfo(long avaterGuid, int expId, int hourTime, int startTime){
 		ExpeditionInfo exp = new ExpeditionInfo();
 		exp.setExpId(expId);
@@ -1188,10 +1087,8 @@ public class Player {
 		return this.birthday.getDay() > 0;
 	}
 
-	public PlayerCodex getCodex(){ return this.codex; }
-
-	public Set<Integer> getRewardedLevels() {
-		return rewardedLevels;
+	public PlayerCodex getCodex() { 
+	    return this.codex; 
 	}
 
 	public void setRewardedLevels(Set<Integer> rewardedLevels) {
@@ -1290,59 +1187,12 @@ public class Player {
 				.build();
 	}
 
-	public MapMarksManager getMapMarksManager() {
-		return mapMarksManager;
-	}
-
-	public StaminaManager getStaminaManager() { return staminaManager; }
-
-	public SotSManager getSotSManager() { return sotsManager; }
-
-	public EnergyManager getEnergyManager() {
-		return this.energyManager;
-	}
-
-	public ResinManager getResinManager() {
-		return this.resinManager;
-	}
-
-	public ForgingManager getForgingManager() {
-		return this.forgingManager;
-	}
-
-	public FurnitureManager getFurnitureManager() {
-		return furnitureManager;
-	}
-
-	public BattlePassManager getBattlePassManager(){
-		return battlePassManager;
-	}
-
-	public CookingManager getCookingManager() {
-		return cookingManager;
-	}
-
 	public void loadBattlePassManager() {
 		if (this.battlePassManager != null) return;
 		this.battlePassManager = DatabaseHelper.loadBattlePass(this);
 		this.battlePassManager.getMissions().values().removeIf(mission -> mission.getData() == null);
 	}
 
-	public AbilityManager getAbilityManager() {
-		return abilityManager;
-	}
-
-	public DeforestationManager getDeforestationManager() {
-		return deforestationManager;
-	}
-
-	public CollectionManager getCollectionManager() {
-		if(this.collectionManager==null){
-			this.collectionManager = new CollectionManager();
-		}
-		return this.collectionManager;
-	}
-
 	public CollectionRecordStore getCollectionRecordStore() {
 		if(this.collectionRecordStore==null){
 			this.collectionRecordStore = new CollectionRecordStore();
@@ -1350,11 +1200,21 @@ public class Player {
 		return collectionRecordStore;
 	}
 
-	public HashMap<String, MapMark> getMapMarks() { return mapMarks; }
+	public Map<String, MapMark> getMapMarks() {
+	    if (this.mapMarks == null) {
+	        this.mapMarks = new HashMap<String, MapMark>();
+	    }
+	    return mapMarks; 
+	}
 
-	public void setMapMarks(HashMap<String, MapMark> newMarks) { mapMarks = newMarks; }
+	public PlayerOpenStateManager getOpenStateManager() {
+	    if (this.openStateManager == null) {
+            this.openStateManager = new PlayerOpenStateManager(this);
+        }
+        return openStateManager;
+    }
 
-	public synchronized void onTick() {
+    public synchronized void onTick() {
 		// Check ping
 		if (this.getLastPingTime() > System.currentTimeMillis() + 60000) {
 			this.getSession().close();
@@ -1453,7 +1313,6 @@ public class Player {
 		this.getCodex().setPlayer(this);
         this.getOpenStateManager().setPlayer(this);
 		this.getTeamManager().setPlayer(this);
-		this.getTowerManager().setPlayer(this);
 	}
 
 	public void save() {
@@ -1463,24 +1322,15 @@ public class Player {
 	// Called from tokenrsp
 	public void loadFromDatabase() {
 		// Make sure these exist
-		if (this.getTowerManager() == null) {
-			this.towerManager = new TowerManager(this);
-		}
 		if (this.getTeamManager() == null) {
 			this.teamManager = new TeamManager(this);
 		}
 		if (this.getCodex() == null) {
 			this.codex = new PlayerCodex(this);
 		}
-        if (this.getOpenStateManager() == null) {
-            this.openStateManager = new PlayerOpenStateManager(this);
-        }
 		if (this.getProfile().getUid() == 0) {
 			this.getProfile().syncWithCharacter(this);
 		}
-		//Make sure towerManager's player is online player
-		this.getTowerManager().setPlayer(this);
-		this.getCollectionManager().setPlayer(this);
 
 		// Load from db
 		this.getAvatars().loadFromDatabase();
@@ -1537,8 +1387,8 @@ public class Player {
 		this.cookingManager.sendCookDataNofity();
 
 		// Unlock in case this is an existing user that reached a level before we implemented unlocking.
-		this.openStateManager.unlockLevelDependentStates();
-        this.openStateManager.onPlayerLogin();
+		this.getOpenStateManager().unlockLevelDependentStates();
+        this.getOpenStateManager().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/PlayerOpenStateManager.java b/src/main/java/emu/grasscutter/game/player/PlayerOpenStateManager.java
index 7d18f059..8effaada 100644
--- a/src/main/java/emu/grasscutter/game/player/PlayerOpenStateManager.java
+++ b/src/main/java/emu/grasscutter/game/player/PlayerOpenStateManager.java
@@ -16,9 +16,7 @@ import java.util.stream.Stream;
 import static emu.grasscutter.game.props.OpenState.*;
 
 @Entity
-public class PlayerOpenStateManager {
-    @Transient private Player player;
-    
+public class PlayerOpenStateManager extends BasePlayerDataManager {
     // Map of all open states that this player has. Do not put default values here.
     private Map<Integer, Integer> map;
     
@@ -37,11 +35,7 @@ public class PlayerOpenStateManager {
         .collect(Collectors.toSet());
 
     public PlayerOpenStateManager(Player player) {
-        this.player = player;
-    }
-
-    public void setPlayer(Player player) {
-        this.player = player;
+        super(player);
     }
 
 	public Map<Integer, Integer> getOpenStateMap() {
diff --git a/src/main/java/emu/grasscutter/game/player/TeamManager.java b/src/main/java/emu/grasscutter/game/player/TeamManager.java
index f969e694..cfb1abec 100644
--- a/src/main/java/emu/grasscutter/game/player/TeamManager.java
+++ b/src/main/java/emu/grasscutter/game/player/TeamManager.java
@@ -41,7 +41,7 @@ import it.unimi.dsi.fastutil.ints.IntSet;
 import static emu.grasscutter.Configuration.*;
 
 @Entity
-public class TeamManager {
+public class TeamManager extends BasePlayerDataManager {
 	@Transient private Player player;
 	
 	private Map<Integer, TeamInfo> teams;
@@ -56,10 +56,7 @@ public class TeamManager {
 	@Transient private final IntSet teamResonancesConfig;
 
 	@Transient private int useTemporarilyTeamIndex = -1;
-	/**
-	 * Temporary Team for tower
-	 */
-	@Transient private List<TeamInfo> temporaryTeam;
+	@Transient private List<TeamInfo> temporaryTeam; // Temporary Team for tower
 
 	public TeamManager() {
 		this.mpTeam = new TeamInfo();
@@ -71,7 +68,7 @@ public class TeamManager {
 	
 	public TeamManager(Player player) {
 		this();
-		this.player = player;
+		this.setPlayer(player);
 		
 		this.teams = new HashMap<>();
 		this.currentTeamIndex = 1;
@@ -80,17 +77,9 @@ public class TeamManager {
 		}
 	}
 	
-	public Player getPlayer() {
-		return player;
-	}
-	
 	public World getWorld() {
 		return player.getWorld();
 	}
-
-	public void setPlayer(Player player) {
-		this.player = player;
-	}
 	
 	public Map<Integer, TeamInfo> getTeams() {
 		return this.teams;
diff --git a/src/main/java/emu/grasscutter/game/quest/QuestManager.java b/src/main/java/emu/grasscutter/game/quest/QuestManager.java
index d9858699..69ae3819 100644
--- a/src/main/java/emu/grasscutter/game/quest/QuestManager.java
+++ b/src/main/java/emu/grasscutter/game/quest/QuestManager.java
@@ -10,6 +10,7 @@ import emu.grasscutter.data.binout.MainQuestData;
 import emu.grasscutter.data.excels.QuestData;
 import emu.grasscutter.data.excels.QuestData.QuestCondition;
 import emu.grasscutter.database.DatabaseHelper;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.game.quest.enums.ParentQuestState;
 import emu.grasscutter.game.quest.enums.QuestTrigger;
@@ -19,19 +20,14 @@ import emu.grasscutter.server.packet.send.*;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
 
-public class QuestManager {
-	private final Player player;
+public class QuestManager extends BasePlayerManager {
 	private final Int2ObjectMap<GameMainQuest> quests;
 
 	public QuestManager(Player player) {
-		this.player = player;
+		super(player);
 		this.quests = new Int2ObjectOpenHashMap<>();
 	}
 
-	public Player getPlayer() {
-		return player;
-	}
-
 	public Int2ObjectMap<GameMainQuest> getQuests() {
 		return quests;
 	}
diff --git a/src/main/java/emu/grasscutter/game/tower/TowerManager.java b/src/main/java/emu/grasscutter/game/tower/TowerManager.java
index 07459f93..a862b158 100644
--- a/src/main/java/emu/grasscutter/game/tower/TowerManager.java
+++ b/src/main/java/emu/grasscutter/game/tower/TowerManager.java
@@ -4,6 +4,7 @@ import emu.grasscutter.data.GameData;
 import emu.grasscutter.data.excels.TowerLevelData;
 import emu.grasscutter.game.dungeons.DungeonSettleListener;
 import emu.grasscutter.game.dungeons.TowerDungeonSettleListener;
+import emu.grasscutter.game.player.BasePlayerManager;
 import emu.grasscutter.game.player.Player;
 import emu.grasscutter.server.packet.send.*;
 
@@ -11,55 +12,54 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-public class TowerManager {
-    private Player player;
-    private TowerData towerData;
+public class TowerManager extends BasePlayerManager {
+    
     public TowerManager(Player player) {
-        setPlayer(player);
+        super(player);
     }
-    public void setPlayer(Player player) {
-        this.player = player;
-        this.towerData = player.getTowerData();
+    
+    public TowerData getTowerData() {
+        return getPlayer().getTowerData();
     }
 
     public int getCurrentFloorId() {
-        return towerData.currentFloorId;
+        return getTowerData().currentFloorId;
     }
 
     public int getCurrentLevelId(){
-        return towerData.currentLevelId + towerData.currentLevel;
+        return getTowerData().currentLevelId + getTowerData().currentLevel;
     }
 
     /**
      * form 1-3
      */
     public int getCurrentLevel(){
-        return towerData.currentLevel + 1;
+        return getTowerData().currentLevel + 1;
     }
     private static final List<DungeonSettleListener> towerDungeonSettleListener = List.of(new TowerDungeonSettleListener());
 	
     public Map<Integer, TowerLevelRecord> getRecordMap() {
-        Map<Integer, TowerLevelRecord> recordMap = towerData.recordMap;
+        Map<Integer, TowerLevelRecord> recordMap = getTowerData().recordMap;
         if(recordMap == null || recordMap.size()==0){
             recordMap = new HashMap<>();
             recordMap.put(1001, new TowerLevelRecord(1001));
-            towerData.recordMap = recordMap;
+            getTowerData().recordMap = recordMap;
         }
         return recordMap;
     }
 
     public void teamSelect(int floor, List<List<Long>> towerTeams) {
         var floorData = GameData.getTowerFloorDataMap().get(floor);
-        towerData.currentFloorId = floorData.getFloorId();
-        towerData.currentLevel = 0;
-        towerData.currentLevelId = GameData.getTowerLevelDataMap().values().stream()
+        getTowerData().currentFloorId = floorData.getFloorId();
+        getTowerData().currentLevel = 0;
+        getTowerData().currentLevelId = GameData.getTowerLevelDataMap().values().stream()
                 .filter(x -> x.getLevelGroupId() == floorData.getLevelGroupId() && x.getLevelIndex() == 1)
                 .findFirst()
                 .map(TowerLevelData::getId)
                 .orElse(0);
 
-        if (towerData.entryScene == 0){
-            towerData.entryScene = player.getSceneId();
+        if (getTowerData().entryScene == 0){
+            getTowerData().entryScene = player.getSceneId();
         }
 
         player.getTeamManager().setupTemporaryTeam(towerTeams);
@@ -78,22 +78,22 @@ public class TowerManager {
                 towerDungeonSettleListener);
 
         // make sure user can exit dungeon correctly
-        player.getScene().setPrevScene(towerData.entryScene);
+        player.getScene().setPrevScene(getTowerData().entryScene);
         player.getScene().setPrevScenePoint(enterPointId);
 
-        player.getSession().send(new PacketTowerEnterLevelRsp(towerData.currentFloorId, getCurrentLevel()));
+        player.getSession().send(new PacketTowerEnterLevelRsp(getTowerData().currentFloorId, getCurrentLevel()));
         // stop using skill
         player.getSession().send(new PacketCanUseSkillNotify(false));
         // notify the cond of stars
-        player.getSession().send(new PacketTowerLevelStarCondNotify(towerData.currentFloorId, getCurrentLevel()));
+        player.getSession().send(new PacketTowerLevelStarCondNotify(getTowerData().currentFloorId, getCurrentLevel()));
     }
 
     public void notifyCurLevelRecordChange(){
-        player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(towerData.currentFloorId, getCurrentLevel()));
+        player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(getTowerData().currentFloorId, getCurrentLevel()));
     }
     public void notifyCurLevelRecordChangeWhenDone(int stars){
         Map<Integer, TowerLevelRecord> recordMap = getRecordMap();
-        int currentFloorId = towerData.currentFloorId;
+        int currentFloorId = getTowerData().currentFloorId;
         if(!recordMap.containsKey(currentFloorId)){
             recordMap.put(currentFloorId,
                     new TowerLevelRecord(currentFloorId).setLevelStars(getCurrentLevelId(),stars));
@@ -102,7 +102,7 @@ public class TowerManager {
                     recordMap.get(currentFloorId).setLevelStars(getCurrentLevelId(),stars));
         }
 
-        towerData.currentLevel++;
+        getTowerData().currentLevel++;
 
         if(!hasNextLevel()){
             // set up the next floor
@@ -113,17 +113,17 @@ public class TowerManager {
         }
     }
     public boolean hasNextLevel(){
-        return towerData.currentLevel < 3;
+        return getTowerData().currentLevel < 3;
     }
     public int getNextFloorId() {
-        return player.getServer().getTowerScheduleManager().getNextFloorId(towerData.currentFloorId);
+        return player.getServer().getTowerScheduleManager().getNextFloorId(getTowerData().currentFloorId);
     }
     public boolean hasNextFloor(){
-        return player.getServer().getTowerScheduleManager().getNextFloorId(towerData.currentFloorId) > 0;
+        return player.getServer().getTowerScheduleManager().getNextFloorId(getTowerData().currentFloorId) > 0;
     }
 
     public void clearEntry() {
-        towerData.entryScene = 0;
+        getTowerData().entryScene = 0;
     }
 
     public boolean canEnterScheduleFloor(){
diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java
index 9a587203..ac162461 100644
--- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java
@@ -11,6 +11,6 @@ import emu.grasscutter.server.game.GameSession;
 public class HandlerEnterTransPointRegionNotify extends PacketHandler {
     @Override
     public void handle(GameSession session, byte[] header, byte[] payload) throws Exception{
-        session.getPlayer().getSotSManager().handleEnterTransPointRegionNotify();
+        session.getPlayer().getSotsManager().handleEnterTransPointRegionNotify();
     }
 }
diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java
index 03fcd4e3..6b4c1f93 100644
--- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java
@@ -12,6 +12,6 @@ import emu.grasscutter.server.game.GameSession;
 public class HandlerExitTransPointRegionNotify extends PacketHandler {
     @Override
     public void handle(GameSession session, byte[] header, byte[] payload) throws Exception{
-        session.getPlayer().getSotSManager().handleExitTransPointRegionNotify();
+        session.getPlayer().getSotsManager().handleExitTransPointRegionNotify();
     }
 }
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeBasicInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeBasicInfoNotify.java
index 846069f5..a55091f3 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketHomeBasicInfoNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketHomeBasicInfoNotify.java
@@ -13,7 +13,7 @@ public class PacketHomeBasicInfoNotify extends BasePacket {
 	public PacketHomeBasicInfoNotify(Player player, boolean editMode) {
 		super(PacketOpcodes.HomeBasicInfoNotify);
 
-		if(player.getCurrentRealmId() == null){
+		if (player.getCurrentRealmId() <= 0) {
 			return;
 		}
 
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java
index 337e28e0..f904e389 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMarkMapRsp.java
@@ -10,7 +10,7 @@ import java.util.*;
 
 public class PacketMarkMapRsp extends BasePacket {
 
-    public PacketMarkMapRsp(HashMap<String, MapMark> mapMarks) {
+    public PacketMarkMapRsp(Map<String, MapMark> mapMarks) {
         super(PacketOpcodes.MarkMapRsp);
 
         MarkMapRspOuterClass.MarkMapRsp.Builder proto = MarkMapRspOuterClass.MarkMapRsp.newBuilder();
-- 
GitLab