From 7d1895023c1a5263f5997979fc583a06f5e7e786 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 04 九月 2024 16:16:46 +0800
Subject: [PATCH] 10249 【越南】【砍树】仙宫(新增仙宫系统;跨服boss历练、跨服仙匣秘境、跨服骑宠养成;跨服古宝养成、跨服排位赛个人排行榜结算支持晋升仙宫;)

---
 ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py                                             |   53 
 ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Championship.py                                  |   54 +
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py                          |   14 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_Xiangong.py |   48 
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameXiangong.py                               |  366 +++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py                          |  104 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                      |  539 ++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py                          |    1 
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py                                               |  104 ++
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py                                           |  539 ++++++++++
 ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py                                                 |    9 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerXiangong.py                |  169 +++
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFuncTeam.py                                     |    4 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py                                    |   27 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                        |   46 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                      |    5 
 PySysDB/PySysDBPY.h                                                                                         |   16 
 ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py                                               |   18 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_TiandaoQiyun.py       |   34 
 ServerPython/CoreServerGroup/GameServer/PyNetPack.ini                                                       |   15 
 ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py                                          |  132 ++
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActXianXiaMJ.py                                 |   10 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py                   |    9 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                          |   18 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActHorsePetTrain.py                             |   12 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActGubao.py                                     |   10 
 ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py                                           |   11 
 ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py                                             |    9 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Xiangong.py                 |   71 +
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py                              |    7 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActBossTrial.py                                 |   10 
 ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Xiangong.py                                      |  117 ++
 ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py                                                |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py            |    3 
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameRecData.py                                |  377 +++++++
 PySysDB/PySysDBG.h                                                                                          |   18 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                             |   10 
 37 files changed, 2,958 insertions(+), 33 deletions(-)

diff --git a/PySysDB/PySysDBG.h b/PySysDB/PySysDBG.h
index b9c09ec..97a40c6 100644
--- a/PySysDB/PySysDBG.h
+++ b/PySysDB/PySysDBG.h
@@ -600,6 +600,7 @@
 	list		MemAwardItemList;	//仙盟榜成员奖励物品信息列表[[物品ID,个数,是否拍品], ...]
 	DWORD		NeedScore;	//上榜所需积分
 	dict		ScoreAwardEx;	//达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...}
+	WORD		XiangongID;	//晋升仙宫ID
 };
 
 //Boss历练跨服活动表
@@ -662,6 +663,7 @@
 	list		AwardItemList;	//奖励物品列表[[物品ID,个数,是否拍品], ...]
 	DWORD		NeedScore;	//上榜所需积分
 	dict		ScoreAwardEx;	//达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...}
+	WORD		XiangongID;	//晋升仙宫ID
 };
 
 //古宝养成活动时间表
@@ -703,6 +705,7 @@
 	list		AwardItemList;	//奖励物品列表[[物品ID,个数,是否拍品], ...]
 	DWORD		NeedScore;	//上榜所需积分
 	dict		ScoreAwardEx;	//达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...}
+	WORD		XiangongID;	//晋升仙宫ID
 };
 
 //仙匣秘境活动时间表
@@ -746,6 +749,7 @@
 	list		AwardItemList;	//奖励物品列表[[物品ID,个数,是否拍品], ...]
 	DWORD		NeedScore;	//上榜所需积分
 	dict		ScoreAwardEx;	//达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...}
+	WORD		XiangongID;	//晋升仙宫ID
 };
 
 //天帝礼包活动时间表
@@ -1046,6 +1050,7 @@
 	BYTE		_Rank;	// 名次
 	list		RankAwardItemList;	//名次奖励物品列表
 	WORD		MainOfficialID;	//主官职ID
+	WORD		XiangongID;	//晋升仙宫ID
 };
 
 //跨服排位官职表
@@ -1420,6 +1425,19 @@
 	list		MoneyRange;	//货币值范围
 };
 
+//仙宫表
+
+struct tagXiangong
+{
+	WORD		_XiangongID;	//仙宫ID
+	BYTE		ShowDays;	//展示天数
+	BYTE		MoneyType;	//点赞货币类型
+	DWORD		MoneyValue;	//货币值
+	DWORD		TitleID;	//称号ID
+	list		AwardItemList;	//晋级仙宫奖励物品列表
+	char		MailKey;	//仙官通知邮件
+};
+
 //缥缈仙域表
 
 struct tagFairyDomain
diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index b8c2185..670b4a3 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -3158,3 +3158,19 @@
 	list		ZLRewardItemList;	//战令奖励物品列表 [[物品ID,个数,是否拍品],...]
 	list		ZLRewardItemListH;	//高级战令奖励物品列表 [[物品ID,个数,是否拍品],...]
 };
+
+//仙宫表
+
+struct tagXiangong
+{
+	WORD		_XiangongID;	//仙宫ID
+};
+
+//仙宫天道树
+
+struct tagTiandaoTree
+{
+	WORD		_AwardIndex;	//奖励索引
+	DWORD		NeedQiyun;	//所需气运值
+	list		AwardItemList;	//奖励物品列表
+};
diff --git a/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini b/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
index 6d9ca8c..512e415 100644
--- a/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
+++ b/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
@@ -580,6 +580,21 @@
 PacketSubCMD_1=0x20
 PacketCallFunc_1=OnWorship
 
+[GameXiangong]
+ScriptName = GameWorldLogic\GameXiangong.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 2
+
+PacketCMD_1=0xA9
+PacketSubCMD_1=0x06
+PacketCallFunc_1=OnQueryXiangongRecPlayers
+
+PacketCMD_2=0xA9
+PacketSubCMD_2=0x07
+PacketCallFunc_2=OnLikeXiangong
+
 [GameWorldMineArea]
 ScriptName = GameWorldLogic\GameWorldMineArea.py
 Writer = hxp
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
index 416480f..4265437 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -1252,6 +1252,58 @@
 
 
 #------------------------------------------------------
+# A9 07 点赞仙宫 #tagCGLikeXiangong
+
+class  tagCGLikeXiangong(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("XiangongID", c_ushort),    # 仙宫ID,为0时代表每日的仙宫点赞
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA9
+        self.SubCmd = 0x07
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA9
+        self.SubCmd = 0x07
+        self.XiangongID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCGLikeXiangong)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A9 07 点赞仙宫 //tagCGLikeXiangong:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                XiangongID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.XiangongID
+                                )
+        return DumpString
+
+
+m_NAtagCGLikeXiangong=tagCGLikeXiangong()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGLikeXiangong.Cmd,m_NAtagCGLikeXiangong.SubCmd))] = m_NAtagCGLikeXiangong
+
+
+#------------------------------------------------------
 # A9 A5 查看竞技场对战玩家最新信息 #tagCGQueryArenaBattlePlayer
 
 class  tagCGQueryArenaBattlePlayer(Structure):
@@ -1572,6 +1624,58 @@
 
 
 #------------------------------------------------------
+# A9 06 查看仙宫仙名录 #tagCGQueryXiangongRecPlayers
+
+class  tagCGQueryXiangongRecPlayers(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("XiangongID", c_ushort),    # 仙宫ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA9
+        self.SubCmd = 0x06
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA9
+        self.SubCmd = 0x06
+        self.XiangongID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCGQueryXiangongRecPlayers)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A9 06 查看仙宫仙名录 //tagCGQueryXiangongRecPlayers:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                XiangongID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.XiangongID
+                                )
+        return DumpString
+
+
+m_NAtagCGQueryXiangongRecPlayers=tagCGQueryXiangongRecPlayers()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGQueryXiangongRecPlayers.Cmd,m_NAtagCGQueryXiangongRecPlayers.SubCmd))] = m_NAtagCGQueryXiangongRecPlayers
+
+
+#------------------------------------------------------
 #A9 A6 设置邮件(补偿)已读状态 #tagCGReadCompensation
 
 class  tagCGReadCompensation(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index 09acf79..716b89d 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -5736,6 +5736,356 @@
 
 
 #------------------------------------------------------
+# A9 27 仙宫新晋玩家信息 #tagGCXiangongNewPlayerInfo
+
+class  tagGCXiangongNewPlayer(Structure):
+    AddTime = 0    #(DWORD AddTime)// 新晋时间戳
+    ServerID = 0    #(DWORD ServerID)
+    PlayerID = 0    #(DWORD PlayerID)
+    NameLen = 0    #(BYTE NameLen)
+    Name = ""    #(String Name)// 玩家名,size = NameLen
+    LV = 0    #(WORD LV)// 玩家等级
+    Job = 0    #(BYTE Job)// 玩家职业
+    RealmLV = 0    #(WORD RealmLV)// 玩家境界
+    EquipShowSwitch = 0    #(DWORD EquipShowSwitch)
+    EquipShowIDCount = 0    #(BYTE EquipShowIDCount)
+    EquipShowID = list()    #(vector<DWORD> EquipShowID)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.AddTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.Name,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
+        self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.EquipShowSwitch,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.EquipShowIDCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.EquipShowIDCount):
+            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+            self.EquipShowID.append(value)
+        return _pos
+
+    def Clear(self):
+        self.AddTime = 0
+        self.ServerID = 0
+        self.PlayerID = 0
+        self.NameLen = 0
+        self.Name = ""
+        self.LV = 0
+        self.Job = 0
+        self.RealmLV = 0
+        self.EquipShowSwitch = 0
+        self.EquipShowIDCount = 0
+        self.EquipShowID = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 4
+        length += 4
+        length += 4
+        length += 1
+        length += len(self.Name)
+        length += 2
+        length += 1
+        length += 2
+        length += 4
+        length += 1
+        length += 4 * self.EquipShowIDCount
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteDWORD(data, self.AddTime)
+        data = CommFunc.WriteDWORD(data, self.ServerID)
+        data = CommFunc.WriteDWORD(data, self.PlayerID)
+        data = CommFunc.WriteBYTE(data, self.NameLen)
+        data = CommFunc.WriteString(data, self.NameLen, self.Name)
+        data = CommFunc.WriteWORD(data, self.LV)
+        data = CommFunc.WriteBYTE(data, self.Job)
+        data = CommFunc.WriteWORD(data, self.RealmLV)
+        data = CommFunc.WriteDWORD(data, self.EquipShowSwitch)
+        data = CommFunc.WriteBYTE(data, self.EquipShowIDCount)
+        for i in range(self.EquipShowIDCount):
+            data = CommFunc.WriteDWORD(data, self.EquipShowID[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                AddTime:%d,
+                                ServerID:%d,
+                                PlayerID:%d,
+                                NameLen:%d,
+                                Name:%s,
+                                LV:%d,
+                                Job:%d,
+                                RealmLV:%d,
+                                EquipShowSwitch:%d,
+                                EquipShowIDCount:%d,
+                                EquipShowID:%s
+                                '''\
+                                %(
+                                self.AddTime,
+                                self.ServerID,
+                                self.PlayerID,
+                                self.NameLen,
+                                self.Name,
+                                self.LV,
+                                self.Job,
+                                self.RealmLV,
+                                self.EquipShowSwitch,
+                                self.EquipShowIDCount,
+                                "..."
+                                )
+        return DumpString
+
+
+class  tagGCXiangongNewPlayerInfo(Structure):
+    Head = tagHead()
+    XiangongID = 0    #(WORD XiangongID)// 仙宫ID
+    NewPlayerCount = 0    #(BYTE NewPlayerCount)
+    NewPlayerList = list()    #(vector<tagGCXiangongNewPlayer> NewPlayerList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA9
+        self.Head.SubCmd = 0x27
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.XiangongID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.NewPlayerCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.NewPlayerCount):
+            temNewPlayerList = tagGCXiangongNewPlayer()
+            _pos = temNewPlayerList.ReadData(_lpData, _pos)
+            self.NewPlayerList.append(temNewPlayerList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA9
+        self.Head.SubCmd = 0x27
+        self.XiangongID = 0
+        self.NewPlayerCount = 0
+        self.NewPlayerList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 2
+        length += 1
+        for i in range(self.NewPlayerCount):
+            length += self.NewPlayerList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteWORD(data, self.XiangongID)
+        data = CommFunc.WriteBYTE(data, self.NewPlayerCount)
+        for i in range(self.NewPlayerCount):
+            data = CommFunc.WriteString(data, self.NewPlayerList[i].GetLength(), self.NewPlayerList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                XiangongID:%d,
+                                NewPlayerCount:%d,
+                                NewPlayerList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.XiangongID,
+                                self.NewPlayerCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagGCXiangongNewPlayerInfo=tagGCXiangongNewPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCXiangongNewPlayerInfo.Head.Cmd,m_NAtagGCXiangongNewPlayerInfo.Head.SubCmd))] = m_NAtagGCXiangongNewPlayerInfo
+
+
+#------------------------------------------------------
+# A9 28 仙宫仙名录玩家信息 #tagGCXiangongRecPlayerInfo
+
+class  tagGCXiangongRecPlayer(Structure):
+    AddTime = 0    #(DWORD AddTime)// 新晋时间戳
+    ServerID = 0    #(DWORD ServerID)
+    PlayerID = 0    #(DWORD PlayerID)
+    NameLen = 0    #(BYTE NameLen)
+    Name = ""    #(String Name)// 玩家名,size = NameLen
+    LV = 0    #(WORD LV)// 玩家等级
+    Job = 0    #(BYTE Job)// 玩家职业
+    RealmLV = 0    #(WORD RealmLV)// 玩家境界
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.AddTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.Name,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
+        self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        return _pos
+
+    def Clear(self):
+        self.AddTime = 0
+        self.ServerID = 0
+        self.PlayerID = 0
+        self.NameLen = 0
+        self.Name = ""
+        self.LV = 0
+        self.Job = 0
+        self.RealmLV = 0
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 4
+        length += 4
+        length += 4
+        length += 1
+        length += len(self.Name)
+        length += 2
+        length += 1
+        length += 2
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteDWORD(data, self.AddTime)
+        data = CommFunc.WriteDWORD(data, self.ServerID)
+        data = CommFunc.WriteDWORD(data, self.PlayerID)
+        data = CommFunc.WriteBYTE(data, self.NameLen)
+        data = CommFunc.WriteString(data, self.NameLen, self.Name)
+        data = CommFunc.WriteWORD(data, self.LV)
+        data = CommFunc.WriteBYTE(data, self.Job)
+        data = CommFunc.WriteWORD(data, self.RealmLV)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                AddTime:%d,
+                                ServerID:%d,
+                                PlayerID:%d,
+                                NameLen:%d,
+                                Name:%s,
+                                LV:%d,
+                                Job:%d,
+                                RealmLV:%d
+                                '''\
+                                %(
+                                self.AddTime,
+                                self.ServerID,
+                                self.PlayerID,
+                                self.NameLen,
+                                self.Name,
+                                self.LV,
+                                self.Job,
+                                self.RealmLV
+                                )
+        return DumpString
+
+
+class  tagGCXiangongRecPlayerInfo(Structure):
+    Head = tagHead()
+    XiangongID = 0    #(WORD XiangongID)// 仙宫ID
+    RecPlayerCount = 0    #(BYTE RecPlayerCount)
+    RecPlayerList = list()    #(vector<tagGCXiangongRecPlayer> RecPlayerList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA9
+        self.Head.SubCmd = 0x28
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.XiangongID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.RecPlayerCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.RecPlayerCount):
+            temRecPlayerList = tagGCXiangongRecPlayer()
+            _pos = temRecPlayerList.ReadData(_lpData, _pos)
+            self.RecPlayerList.append(temRecPlayerList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA9
+        self.Head.SubCmd = 0x28
+        self.XiangongID = 0
+        self.RecPlayerCount = 0
+        self.RecPlayerList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 2
+        length += 1
+        for i in range(self.RecPlayerCount):
+            length += self.RecPlayerList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteWORD(data, self.XiangongID)
+        data = CommFunc.WriteBYTE(data, self.RecPlayerCount)
+        for i in range(self.RecPlayerCount):
+            data = CommFunc.WriteString(data, self.RecPlayerList[i].GetLength(), self.RecPlayerList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                XiangongID:%d,
+                                RecPlayerCount:%d,
+                                RecPlayerList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.XiangongID,
+                                self.RecPlayerCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagGCXiangongRecPlayerInfo=tagGCXiangongRecPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCXiangongRecPlayerInfo.Head.Cmd,m_NAtagGCXiangongRecPlayerInfo.Head.SubCmd))] = m_NAtagGCXiangongRecPlayerInfo
+
+
+#------------------------------------------------------
 # AC 10 仙盟抢Boss所有Boss伤血进度信息 #tagGCAllFamilyBossHurtInfoList
 
 class  tagGCFamilyBossHurtInfo(Structure):
@@ -50177,6 +50527,80 @@
 
 
 #------------------------------------------------------
+# B1 15 天道树信息 #tagMCTiandaoTreeInfo
+
+class  tagMCTiandaoTreeInfo(Structure):
+    Head = tagHead()
+    Qiyun = 0    #(DWORD Qiyun)// 当前气运值
+    AwardCount = 0    #(BYTE AwardCount)// 天道果领取记录值个数
+    AwardStateList = list()    #(vector<DWORD> AwardStateList)// 天道果领取记录值列表,按奖励索引位二进制记录是否已领取,一个值可存31位,如值1存0~30,值2存31~61,...
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x15
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Qiyun,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.AwardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.AwardCount):
+            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+            self.AwardStateList.append(value)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x15
+        self.Qiyun = 0
+        self.AwardCount = 0
+        self.AwardStateList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 4
+        length += 1
+        length += 4 * self.AwardCount
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteDWORD(data, self.Qiyun)
+        data = CommFunc.WriteBYTE(data, self.AwardCount)
+        for i in range(self.AwardCount):
+            data = CommFunc.WriteDWORD(data, self.AwardStateList[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Qiyun:%d,
+                                AwardCount:%d,
+                                AwardStateList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Qiyun,
+                                self.AwardCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCTiandaoTreeInfo=tagMCTiandaoTreeInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCTiandaoTreeInfo.Head.Cmd,m_NAtagMCTiandaoTreeInfo.Head.SubCmd))] = m_NAtagMCTiandaoTreeInfo
+
+
+#------------------------------------------------------
 # B1 12 培养功能境界信息 #tagMCTrainRealmLVInfo
 
 class  tagMCTrainRealmLV(Structure):
@@ -50285,6 +50709,121 @@
 
 
 #------------------------------------------------------
+# B1 14 仙宫信息 #tagMCXiangongInfo
+
+class  tagMCXiangong(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("XiangongID", c_ushort),    # 仙宫ID
+                  ("LikeStateToday", c_ubyte),    # 今日是否已点赞
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.XiangongID = 0
+        self.LikeStateToday = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCXiangong)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B1 14 仙宫信息 //tagMCXiangongInfo:
+                                XiangongID:%d,
+                                LikeStateToday:%d
+                                '''\
+                                %(
+                                self.XiangongID,
+                                self.LikeStateToday
+                                )
+        return DumpString
+
+
+class  tagMCXiangongInfo(Structure):
+    Head = tagHead()
+    LikeStateToday = 0    #(BYTE LikeStateToday)// 今日是否已点赞,指仙宫的外层点赞,非某个指定仙宫
+    XiangongCount = 0    #(BYTE XiangongCount)
+    XiangongList = list()    #(vector<tagMCXiangong> XiangongList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x14
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.LikeStateToday,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.XiangongCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.XiangongCount):
+            temXiangongList = tagMCXiangong()
+            _pos = temXiangongList.ReadData(_lpData, _pos)
+            self.XiangongList.append(temXiangongList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x14
+        self.LikeStateToday = 0
+        self.XiangongCount = 0
+        self.XiangongList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        for i in range(self.XiangongCount):
+            length += self.XiangongList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.LikeStateToday)
+        data = CommFunc.WriteBYTE(data, self.XiangongCount)
+        for i in range(self.XiangongCount):
+            data = CommFunc.WriteString(data, self.XiangongList[i].GetLength(), self.XiangongList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                LikeStateToday:%d,
+                                XiangongCount:%d,
+                                XiangongList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.LikeStateToday,
+                                self.XiangongCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCXiangongInfo=tagMCXiangongInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCXiangongInfo.Head.Cmd,m_NAtagMCXiangongInfo.Head.SubCmd))] = m_NAtagMCXiangongInfo
+
+
+#------------------------------------------------------
 # B1 20 战令信息 #tagMCZhanlingInfo
 
 class  tagMCZhanling(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Championship.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Championship.py
index 70f1838..2666ce2 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Championship.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Championship.py
@@ -19,6 +19,7 @@
 import CrossChampionship
 import PlayerDBGSEvent
 import ShareDefine
+import time
 
 
 #逻辑实现
@@ -44,6 +45,9 @@
         GameWorld.DebugAnswer(curPlayer, "如果没有指定ID则该组重新随机匹配")
         GameWorld.DebugAnswer(curPlayer, "命令需在对应的阶段设置才有效;")
         GameWorld.DebugAnswer(curPlayer, "重置活动数据需在非活动时间重置,不然可能导致活动状态异常")
+        GameWorld.DebugAnswer(curPlayer, "虚拟结算排名: Championship 8 分区 第1名ID ...")
+        GameWorld.DebugAnswer(curPlayer, "虚拟结算执行: Championship over")
+        GameWorld.DebugAnswer(curPlayer, "注:虚拟结算的命令主要用于快速测试结算用,玩家ID不足则假人代替")
         
     else:
         value1 = gmList[0]
@@ -207,9 +211,59 @@
         CrossChampionship.Send_CrossServerMsg_ChampionshipGroup(groupMark)
         return
     
+    if value1 == 8:
+        __FackOverData(playerID, serverGroupID, gmList)
+        return
+    if value1 == "over":
+        GameWorld.DebugAnswerCross(playerID, serverGroupID, "虚拟结算执行")
+        CrossChampionship.DoCrossChampionshipFinalOver()
+        return
     GameWorld.DebugAnswerCross(playerID, serverGroupID, "命令参数错误,详见命令说明")
     return
 
+def __FackOverData(playerID, serverGroupID, gmList):
+    ## 虚拟结算数据
+    zoneID = gmList[1] if len(gmList) > 1 else 0
+    rankPlayerIDList = gmList[2:]
+    batPlayerCount = CrossChampionship.Def_CrossChampionshipPlayerWFCount
+    # 先设置参赛玩家
+    champMgr = CrossChampionship.GetChampionshipMgr()
+    pkZoneMgr = champMgr.GetChampPKZoneMgr(zoneID, True)
+    if len(rankPlayerIDList) < batPlayerCount:
+        # 不足的机器人补足
+        zonePlayerIDStar = zoneID * 100 + 1 # 确保每个分区的假人不重复
+        rankPlayerIDList += range(zonePlayerIDStar, zonePlayerIDStar + (batPlayerCount - len(rankPlayerIDList)))
+    pkZoneMgr.playerDict = {} # 清空玩家,重新设置
+    CrossChampionship.Send_CrossServerMsg_ChampionshipPlayer(isSync=True, clearPlayer=True)
+    for pID in rankPlayerIDList:
+        batPlayer = CrossChampionship.ChampionshipBatPlayer()
+        batPlayer.zoneID = zoneID
+        batPlayer.playerID = pID
+        pkZoneMgr.playerDict[pID] = batPlayer
+    CrossChampionship.Send_CrossServerMsg_ChampionshipPlayer(isSync=True)
+    
+    # 虚拟战斗场次
+    overTime = int(time.time())
+    pkZoneMgr.battleInfo = {} # 清空对战记录
+    battleIndexDict = {8:[[1, 5], [3, 7], [2, 6], [4, 8]], 4:[[1, 3], [5, 7], [2, 4], [6, 8]], 2:[[1, 2], [3, 4], [5, 6], [7, 8]]}
+    for groupMark in [8, 4, 2]:
+        battleList = battleIndexDict[groupMark]
+        for battleNum in range(1, 1 + len(battleList)):
+            battleRankInfo = battleList[battleNum - 1]
+            battle = CrossChampionship.ChampionshipBattle()
+            battle.overTime = overTime
+            battle.zoneID = zoneID
+            battle.groupMark = groupMark
+            battle.battleNum = battleNum
+            battle.playerIDA = rankPlayerIDList[battleRankInfo[0] - 1]
+            battle.playerIDB = rankPlayerIDList[battleRankInfo[1] - 1]
+            battle.winPlayerID = battle.playerIDA
+            pkZoneMgr.AddBattle(groupMark, battleNum, battle)
+        CrossChampionship.Send_CrossServerMsg_ChampionshipGroup(groupMark)
+        
+    GameWorld.DebugAnswerCross(playerID, serverGroupID, "虚拟结算排名:分区%s,%s" % (zoneID, rankPlayerIDList))
+    return
+
 def __PrintChampionshipInfo():
     GameWorld.Log("================ 跨服排位当前信息 ==================")
     ID = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_CrossChampionshipID)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Xiangong.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Xiangong.py
new file mode 100644
index 0000000..6457ac6
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Xiangong.py
@@ -0,0 +1,117 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.Xiangong
+#
+# @todo:仙宫
+# @author hxp
+# @date 2024-09-04
+# @version 1.0
+#
+# 详细描述: 仙宫
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-04 16:30"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import ShareDefine
+import IpyGameDataPY
+import PyDataManager
+import GameXiangong
+
+import random
+import time
+
+#逻辑实现
+## 执行逻辑
+#  @param curPlayer 当前玩家
+#  @param gmList [cmdIndex gmAccID msg]
+#  @return None
+#  @remarks 函数详细说明.
+def OnExec(curPlayer, gmList):
+    ## 本服处理
+    if not gmList:
+        GameWorld.DebugAnswer(curPlayer, "插入新晋仙官: Xiangong a 仙宫ID 个数 [可视区服IDA 至区服IDB 名次 可指定ID ...]")
+        GameWorld.DebugAnswer(curPlayer, "清除仙宫仙官: Xiangong d 仙宫ID")
+        GameWorld.DebugAnswer(curPlayer, "输出仙宫仙官: Xiangong p 仙宫ID")
+        GameWorld.DebugAnswer(curPlayer, "注:插入指定仙官ID前提得该玩家在跨服有缓存")
+        return
+    return
+
+def OnGetMergeParam(curPlayer):
+    playerID = curPlayer.GetPlayerID()
+    serverGroupID = GameWorld.GetServerGroupID()
+    return [serverGroupID, playerID]
+
+def OnMergeServerExec(gmList, tick):
+    ## 跨服处理
+    
+    serverGroupID = gmList[-2]
+    playerID = gmList[-1]
+    
+    gmList = gmList[:-2]
+    if not gmList:
+        return
+    
+    value1 = gmList[0]
+    
+    if value1 == "a":
+        xiangongID = gmList[1] if len(gmList) > 1 else 0
+        addCount = gmList[2] if len(gmList) > 2 else 1
+        serverIDA = gmList[3] if len(gmList) > 3 else 1
+        serverIDB = gmList[4] if len(gmList) > 4 else 9999
+        order = gmList[5] if len(gmList) > 5 else None
+        playerIDList = gmList[6:] if len(gmList) > 6 else []
+        
+        serverIDList = [[serverIDA, serverIDB]]
+        
+        ipyData = IpyGameDataPY.GetIpyGameData("Xiangong", xiangongID)
+        if not ipyData:
+            GameWorld.DebugAnswerCross(playerID, serverGroupID, "仙宫ID不存在:%s" % (xiangongID))
+            return
+        
+        syncDict = {}
+        for _ in xrange(addCount):
+            if playerIDList:
+                addPlayerID = playerIDList.pop(0)
+            else:
+                addPlayerID = random.randint(1000, 2000)
+            GameXiangong.AddXiangongPlayer(xiangongID, addPlayerID, serverIDList, order, syncDict)
+        GameXiangong.SendNewXiangongPlayerToClientServer(syncDict)
+        
+        gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+        recDataList = gameRecMgr.GetGameRecDataList(ShareDefine.Def_GameRecType_Xiangong, xiangongID)
+        GameWorld.DebugAnswerCross(playerID, serverGroupID, "插入新晋仙官:%s, 仙官ID:%s, 仙官总数:%s" % (addCount, xiangongID, len(recDataList)))
+        return
+    
+    if value1 == "d":
+        xiangongID = gmList[1] if len(gmList) > 1 else 0
+        ipyData = IpyGameDataPY.GetIpyGameData("Xiangong", xiangongID)
+        if not ipyData:
+            GameWorld.DebugAnswerCross(playerID, serverGroupID, "仙宫ID不存在:%s" % (xiangongID))
+            return
+        gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+        delCount = gameRecMgr.DelGameRecDataByTypeID(ShareDefine.Def_GameRecType_Xiangong, xiangongID)
+        GameWorld.DebugAnswerCross(playerID, serverGroupID, "清除仙宫仙官:%s, 仙官ID:%s" % (delCount, xiangongID))
+        GameWorld.DebugAnswerCross(playerID, serverGroupID, "如果要获得正确的展示仙官请重登")
+        return
+    
+    if value1 == "p":
+        xiangongID = gmList[1] if len(gmList) > 1 else 0
+        startIndex = gmList[2] if len(gmList) > 2 else 0
+        gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+        recDataList = gameRecMgr.GetGameRecDataList(ShareDefine.Def_GameRecType_Xiangong, xiangongID)
+        GameWorld.DebugAnswerCross(playerID, serverGroupID, "仙宫ID:%s, 仙官总数:%s" % (xiangongID, len(recDataList)))
+        curTime = int(time.time())
+        for i, recData in enumerate(recDataList[startIndex:startIndex + 20], startIndex):
+            xgPlayerID = GameXiangong.GetXGPlayerID(recData)
+            serverIDList = recData.GetUserDataByKey(GameXiangong.Def_UserDataKey_ServerIDList)
+            addTime = recData.GetTime()
+            passDays = GameWorld.GetDiff_Day(curTime, addTime) + 1
+            GameWorld.DebugAnswerCross(playerID, serverGroupID, " %s,ID:%s,天数:%s,区服:%s" % (i, xgPlayerID, passDays, serverIDList))
+        return
+    
+    return
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
index 3de2fd9..62cfc6b 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
@@ -476,6 +476,15 @@
         return mainServerID
     return 0
 
+def CheckServerIDInList(serverID, serverIDList):
+    if not serverIDList:
+        return True
+    for serverIDInfo in serverIDList:
+        if (isinstance(serverIDInfo, tuple) and serverIDInfo[0] <= serverID <= serverIDInfo[1]) \
+            or (isinstance(serverIDInfo, list) and serverIDInfo[0] <= serverID <= serverIDInfo[1]) \
+            or (isinstance(serverIDInfo, int) and serverIDInfo == serverID):
+            return True
+    return False
 
 #===============================================================================
 # 平台ID = appid
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py
index 0dcbbdd..200effc 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py
@@ -29,6 +29,7 @@
 import PlayerControl
 import PyDataManager
 import NetPackCommon
+import GameXiangong
 import GameWorship
 import PyGameData
 import ChConfig
@@ -1955,6 +1956,7 @@
     GameWorld.Log("pkZoneIDList=%s" % pkZoneIDList)
     
     worshipList = []
+    syncNewXiangongDict = {}
     for zoneID in pkZoneIDList:
         GameWorld.Log("=== 结算排位分区: zoneID=%s ===" % zoneID, zoneID)
         finalPlayerIDList = []
@@ -1986,8 +1988,9 @@
             rankIpyData = IpyGameDataPY.GetIpyGameData("ChampionshipRank", rank)
             officialID = rankIpyData.GetMainOfficialID() if rankIpyData else 0
             rankAwardItemList = rankIpyData.GetRankAwardItemList() if rankIpyData else []
-            GameWorld.Log("    最终排名: zoneID=%s,rank=%s,playerID=%s,officialID=%s,rankAwardItemList=%s,accID=%s,fightPower=%s" 
-                          % (zoneID, rank, playerID, officialID, rankAwardItemList, accID, fightPower), zoneID)
+            xiangongID = rankIpyData.GetXiangongID() if rankIpyData else 0
+            GameWorld.Log("    最终排名: zoneID=%s,rank=%s,playerID=%s,officialID=%s,xiangongID=%s,rankAwardItemList=%s,accID=%s,fightPower=%s" 
+                          % (zoneID, rank, playerID, officialID, xiangongID, rankAwardItemList, accID, fightPower), zoneID)
             
             if officialID:
                 offObj = ChampionshipOfficial()
@@ -2007,6 +2010,12 @@
             paramList = [rank]
             PlayerCompensation.SendMailByKey("CrossChampionshipPKRank", [playerID], rankAwardItemList, paramList, crossMail=True)
             
+            if xiangongID:
+                crossZoneName = GameWorld.GetCrossZoneName()
+                zoneIpyData = IpyGameDataPY.GetIpyGameData("CrossZonePK", crossZoneName, zoneID)
+                serverIDRangeList = zoneIpyData.GetServerGroupIDList() if zoneIpyData else []
+                GameXiangong.AddXiangongPlayer(xiangongID, playerID, serverIDRangeList, rank, syncNewXiangongDict)
+                
         # 处理4强竞猜发奖励
         guessType = 4
         moneyType = ShareDefine.TYPE_Price_GongdePoint
@@ -2048,6 +2057,7 @@
     
     # 通知新添加的膜拜
     GameWorship.SyncAddCrossWorship(worshipList)
+    GameXiangong.SendNewXiangongPlayerToClientServer(syncNewXiangongDict)
     GameWorld.Log("===================================================================")
     return
 
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
index 45a4c8b..6a5341b 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
@@ -37,6 +37,7 @@
 import CrossYaomoBoss
 import GameWorldBoss
 import CrossRealmPK
+import GameXiangong
 import GameWorship
 import PlayerQuery
 import PlayerTalk
@@ -201,6 +202,9 @@
             
         elif msgType == ShareDefine.ClientServerMsg_QueryFuncTeam:
             PlayerFuncTeam.ClientServerMsg_QueryFuncTeam(serverGroupID, msgData)
+            
+        elif msgType == ShareDefine.ClientServerMsg_QueryXiangong:
+            GameXiangong.ClientServerMsg_QueryXiangong(serverGroupID, msgData)
             
         # 需要发送到地图服务器处理的
         elif msgType in [ShareDefine.ClientServerMsg_Reborn, ShareDefine.ClientServerMsg_CollectNPC]:
@@ -408,6 +412,9 @@
         elif msgType == ShareDefine.CrossServerMsg_Worship:
             GameWorship.CrossServerMsg_Worship(msgData)
             
+        elif msgType == ShareDefine.CrossServerMsg_Xiangong:
+            GameXiangong.CrossServerMsg_Xiangong(msgData)
+            
         elif msgType == ShareDefine.CrossServerMsg_ChampionshipState:
             CrossChampionship.CrossServerMsg_ChampionshipState(msgData)
             
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameRecData.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameRecData.py
new file mode 100644
index 0000000..80f819d
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameRecData.py
@@ -0,0 +1,377 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GameRecData
+#
+# @todo:通用记录表新
+# @author hxp
+# @date 2024-09-04
+# @version 1.0
+#
+# 详细描述: 通用记录表新,原通用记录字符长度记录有限,且针对某个记录类型下的子类型查找每次需要遍历,效率不高
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-04 16:30"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PyGameDataStruct
+import ShareDefine
+import CommFunc
+
+import time
+import json
+
+class GameRecData():
+    
+    def __init__(self, dbRecData=None):
+        if not dbRecData:
+            dbRecData = PyGameDataStruct.tagDBGameRec()
+        self.dbRecData = dbRecData
+        self.__userDataDict = None
+        self.__userDataChange = False
+        return
+    def clear(self):
+        self.dbRecData.clear()
+        self.__userDataDict = None
+        self.__userDataChange = False
+        return
+    def GetRecType(self): return self.dbRecData.RecType
+    def SetRecType(self, recType): self.dbRecData.RecType = recType
+    def GetRecID(self): return self.dbRecData.RecID
+    def SetRecID(self, recID): self.dbRecData.RecID = recID
+    def GetTime(self): return self.dbRecData.Time
+    def SetTime(self, sTime): self.dbRecData.Time = sTime
+    def GetValue1(self): return self.dbRecData.Value1
+    def SetValue1(self, value1): self.dbRecData.Value1 = value1
+    def GetValue2(self): return self.dbRecData.Value2
+    def SetValue2(self, value2): self.dbRecData.Value2 = value2
+    def GetValue3(self): return self.dbRecData.Value3
+    def SetValue3(self, value3): self.dbRecData.Value3 = value3
+    def GetValue4(self): return self.dbRecData.Value4
+    def SetValue4(self, value4): self.dbRecData.Value4 = value4
+    def GetValue5(self): return self.dbRecData.Value5
+    def SetValue5(self, value5): self.dbRecData.Value5 = value5
+    def GetValue6(self): return self.dbRecData.Value6
+    def SetValue6(self, value6): self.dbRecData.Value6 = value6
+    def GetValue7(self): return self.dbRecData.Value7
+    def SetValue7(self, value7): self.dbRecData.Value7 = value7
+    def GetValue8(self): return self.dbRecData.Value8
+    def SetValue8(self, value8): self.dbRecData.Value8 = value8
+    def __GetUserDataDict(self):
+        if self.__userDataDict == None:
+            try:
+                self.__userDataDict = eval(self.dbRecData.UserData)
+            except:
+                self.__userDataDict = {}
+        return self.__userDataDict
+    def GetUserDataByKey(self, key, defaultValue=None):
+        userDataDict = self.__GetUserDataDict()
+        return userDataDict.get(str(key), defaultValue)
+    def SetUserDataByKey(self, key, value):
+        userDataDict = self.__GetUserDataDict()
+        userDataDict[str(key)] = value
+        self.__userDataChange = True
+        return
+    def GetUserData(self):
+        if self.__userDataChange:
+            self.SaveUserData()
+        return self.dbRecData.UserData
+    def SaveUserData(self):
+        userDataDict = self.__GetUserDataDict()
+        self.dbRecData.UserData = json.dumps(userDataDict, ensure_ascii=False).replace(" ", "")
+        self.dbRecData.UserDataLen = len(self.dbRecData.UserData)
+        self.__userDataChange = False
+        return
+    
+    def IsMatchValue(self, valueList):
+        # 检查记录值列表是否配置该记录
+        # @param valueList: [value1, value2, ...] value为None时不判断该值
+        if not valueList:
+            return False
+        for i, value in enumerate(valueList, 1):
+            if value == None:
+                continue
+            if not hasattr(self, "GetValue%s" % i):
+                continue
+            curValue = getattr(self, "GetValue%s" % i)()
+            if curValue != value:
+                return False
+        return True
+    
+    def GetString(self):
+        return {"RecID":self.GetRecID(), "RecType":self.GetRecType(), "Time":self.GetTime(), 
+                "Value1":self.GetValue1(), "Value2":self.GetValue2(), "Value3":self.GetValue3(), "Value4":self.GetValue4(),
+                "Value5":self.GetValue5(), "Value6":self.GetValue6(), "Value7":self.GetValue7(), "Value8":self.GetValue8(), 
+                "UserDataDict":self.__GetUserDataDict()
+                }
+    def SetAttr(self, attrDict, isClear=False):
+        if isClear:
+            self.clear()
+        for k, v in attrDict.items():
+            if hasattr(self, "Set%s" % k):
+                getattr(self, "Set%s" % k, v)(v)
+            elif k == "UserDataDict":
+                self.__userDataDict = v
+        return
+    
+class DBGameRecDataManager():
+    ## 通用记录管理
+    
+    def __init__(self):
+        self.Clear()
+        return
+    
+    def Clear(self):
+        self.recTypeDict = {} # {recType:{recID:[GameRecData, ...], ...}}
+        self.recValueIndexDict = {} # {recType:{recID:{indexKey:[GameRecData, ...], ...}, ...}, ...}
+        return
+    
+    def DelGameRecDataByType(self, recType):
+        ## 删除某个记录类型所有记录
+        recDict = self.recTypeDict.pop(recType, {})
+        delCount = 0
+        for recList in recDict.values():
+            delCount += len(recList)
+        GameWorld.DebugLog("删除指定新通用记录类型所有记录: recType=%s,delCount=%s" % (recType, delCount))
+        self.recValueIndexDict.pop(recType, {})
+        return delCount
+    
+    def DelGameRecDataByTypeID(self, recType, delRecID):
+        ## 删除某个类型对应的ID记录
+        if recType not in self.recTypeDict:
+            return 0
+        recDataDict = self.recTypeDict[recType]
+        recDataList = recDataDict.pop(delRecID, None)
+        delCount = len(recDataList) if recDataList else 0
+        GameWorld.DebugLog("删除指定新通用记录类型某个记录ID所有记录: recType=%s,delRecID=%s,delCount=%s" % (recType, delRecID, delCount))
+        if recType in self.recValueIndexDict:
+            recIndexDataDict = self.recValueIndexDict[recType]
+            recIndexDataDict.pop(delRecID, None)
+        return delCount
+    
+    def DelGameRecDataByTypeValue(self, recType, valueList, delRecID=None):
+        ## 删除某个记录类型匹配Value值列表的记录
+        # @param valueList: [value1, value2, ...] value为None时不判断该值
+        # @param delRecID: 可指定只删除记录ID的记录
+        
+        if not valueList:
+            return 0
+        if recType not in self.recTypeDict:
+            return 0
+        delCountTotal = 0
+        recDict = self.recTypeDict[recType]
+        for recID, recDataList in recDict.items():
+            if delRecID and recID != delRecID:
+                continue
+            delCount = 0
+            for recData in recDataList[::-1]: # 倒序处理删除
+                if recData.IsMatchValue(valueList):
+                    delCount += self.DelGameRecData(recData)
+                    
+            if delCount:
+                delCountTotal += delCount
+                GameWorld.DebugLog("删除某个新通用记录类型所有Value1匹配值的记录: recType=%s,valueList=%s,delRecID=%s,delCount=%s" 
+                                   % (recType, valueList, recID, delCount))
+        return delCountTotal
+    
+    def DelGameRecData(self, recData):
+        ## 删除指定记录
+        recID = recData.GetRecID()
+        recType = recData.GetRecType()
+        if recType not in self.recTypeDict:
+            return 0
+        recDataDict = self.recTypeDict[recType]
+        if recID not in recDataDict:
+            return 0
+        recDataList = recDataDict[recID]
+        if recData in recDataList:
+            recDataList.remove(recData)
+            
+        keyStr = self.__GetValueIndexKey(recData)
+        if keyStr:
+            recIndexDataDict = self.recValueIndexDict.get(recType, {})
+            valueIndexDict = recIndexDataDict.get(recID, {})
+            recIndexDataList = valueIndexDict.get(keyStr, [])
+            if recData in recIndexDataList:
+                recIndexDataList.remove(recData)
+        return 1
+    
+    def AddGameRecData(self, recType, recID, valueSetList=None, maxCount=0):
+        '''添加记录
+        @param recType: 记录类型
+        @param recID: 记录类型对应的子ID,比如可以是玩家ID或者其他自定的ID,该ID在同个记录类型中唯一,不同记录类型可重复
+        @param valueList: [value1, value2, ...] 设置的Value值列表
+        @param maxCount: 每种记录ID最大可保存记录条数,默认0不限制
+        '''
+        recData = GameRecData()
+        recData.clear()
+        recData.SetRecType(recType)
+        recData.SetRecID(recID)
+        recData.SetTime(int(time.time()))
+        if valueSetList:
+            for num, v in enumerate(valueSetList, 1):
+                if not hasattr(recData, "SetValue%s" % num):
+                    continue
+                getattr(recData, "SetValue%s" % num)(v)
+        recDataList = self.__AddGameRecData(recData)
+        
+        doCount = len(recDataList)
+        while maxCount and len(recDataList) > maxCount and doCount > 0:
+            GameWorld.DebugLog("超过记录上限删除记录: recType=%s,recID=%s,recCount=%s,maxCount=%s" % (recType, recID, len(recDataList), maxCount))
+            doCount -= 1
+            self.DelGameRecData(recDataList[0]) # 超过最大上限,删除第一个
+            
+        return recData
+    
+    def AddGameRecDataByDict(self, attrDict):
+        ## 一般是跨服同步过来数据添加用
+        recData = GameRecData()
+        recData.SetAttr(attrDict, True)
+        self.__AddGameRecData(recData)
+        return recData
+    
+    def __AddGameRecData(self, recData):
+        recID = recData.GetRecID()
+        recType = recData.GetRecType()
+        if recType not in self.recTypeDict:
+            self.recTypeDict[recType] = {}
+        recDataDict = self.recTypeDict[recType]
+        if recID not in recDataDict:
+            recDataDict[recID] = []
+        recDataList = recDataDict[recID]
+        recDataList.append(recData)
+        
+        keyStr = self.__GetValueIndexKey(recData)
+        if keyStr:
+            if recType not in self.recValueIndexDict:
+                self.recValueIndexDict[recType] = {}
+            recIndexDataDict = self.recValueIndexDict[recType]
+            if recID not in recIndexDataDict:
+                recIndexDataDict[recID] = {}
+            valueIndexDict = recIndexDataDict[recID]
+            if keyStr not in valueIndexDict:
+                valueIndexDict[keyStr] = []
+            recIndexDataList = valueIndexDict[keyStr]
+            recIndexDataList.append(recData)
+        return recDataList
+    
+    def __GetValueIndexKey(self, recData):
+        ## 获取记录对象对应字典key值,默认使用value1
+        recType = recData.GetRecType()
+        if recType not in ShareDefine.Def_GameRecValueKeyDict:
+            return
+        valueNumList = ShareDefine.Def_GameRecValueKeyDict[recType]
+        if not valueNumList:
+            valueNumList = [1]
+        keyStr = ""
+        for num in valueNumList:
+            if not hasattr(recData, "GetValue%s" % num):
+                return
+            if keyStr:
+                keyStr += "_"
+            keyStr += str(getattr(recData, "GetValue%s" % num)())
+        return keyStr
+    
+    def GetGameRecDataMatch(self, recType, recID, valueList, findone=False):
+        '''获取记录类型对应的匹配value值记录
+        @param recType: 记录类型
+        @param recID: 记录类型对应的子ID
+        @param valueList: [value1, value2, ...] value为None时不判断该值
+        @param findone: 是否只匹配一条满足的记录
+        @return: recData or [recData, ...] or None
+        '''
+        
+        # 有配置value索引key的,直接快速获取
+        if recType in ShareDefine.Def_GameRecValueKeyDict:
+            if recType not in self.recValueIndexDict:
+                return
+            recIndexDataDict = self.recValueIndexDict[recType]
+            if recID not in recIndexDataDict:
+                return
+            valueIndexDict = recIndexDataDict[recID]
+            keyStr = ""
+            for v in valueList:
+                if keyStr:
+                    keyStr += "_"
+                keyStr += str(v)
+            if keyStr not in valueIndexDict:
+                return
+            recIndexDataList = valueIndexDict[keyStr]
+            if not recIndexDataList:
+                return
+            return recIndexDataList[0] if findone else recIndexDataList
+        
+        # 没有的则遍历匹配
+        recDataList = self.GetGameRecDataList(recType, recID)
+        if not recDataList:
+            return
+        matchRecDataList = []
+        for recData in recDataList:
+            if not recData.IsMatchValue(valueList):
+                continue
+            if findone:
+                return recData
+            matchRecDataList.append(recData)
+        return matchRecDataList
+    
+    def GetGameRecDataList(self, recType, recID):
+        ## 获取记录类型对应记录列表 [recData, ...]
+        if recType not in self.recTypeDict:
+            self.recTypeDict[recType] = {}
+        recDataDict = self.recTypeDict[recType]
+        if recID not in recDataDict:
+            recDataDict[recID] = []
+        recDataList = recDataDict[recID]
+        return recDataList
+    
+    def GetGameRecDataDict(self, recType):
+        ## 获取记录类型对应所有记录字典 {recID:[recData, ...], ...}
+        if recType not in self.recTypeDict:
+            return {}
+        return self.recTypeDict[recType]
+    
+    def SortGameRecDataList(self, recDataList):
+        recDataList.sort(key=lambda r: (r.GetTime()), reverse=False)
+        return
+    
+    # 保存数据 存数据库和realtimebackup
+    def GetSaveData(self):
+        savaData = ""
+        cntData = ""
+        cnt = 0
+        
+        for recDataDict in self.recTypeDict.values():
+            for recDataList in recDataDict.values():
+                for recData in recDataList:
+                    cnt += 1
+                    recData.SaveUserData()
+                    savaData += recData.dbRecData.getBuffer()
+                    
+        GameWorld.Log("Save DBGameRec count :%s len=%s" % (cnt, len(savaData)))
+        return CommFunc.WriteDWORD(cntData, cnt) + savaData
+    
+    # 从数据库载入数据
+    def LoadPyGameData(self, datas, pos, dataslen):
+        cnt, pos = CommFunc.ReadDWORD(datas, pos)
+        GameWorld.Log("Load DBGameRec count :%s" % cnt)
+        
+        self.Clear()
+        
+        for _ in xrange(cnt):
+            recData = PyGameDataStruct.tagDBGameRec()
+            recData.clear()
+            pos += recData.readData(datas, pos, dataslen)
+            
+            self.__AddGameRecData(GameRecData(recData))
+            
+        # 按时间升序排序下
+        for recDataDict in self.recTypeDict.values():
+            for recDataList in recDataDict.values():
+                recDataList.sort(key=lambda d: (d.GetTime()))
+        return pos
+    
+GameRecDataTemp = GameRecData()
+
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameXiangong.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameXiangong.py
new file mode 100644
index 0000000..96d3670
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameXiangong.py
@@ -0,0 +1,366 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GameXiangong
+#
+# @todo:仙宫
+# @author hxp
+# @date 2024-09-04
+# @version 1.0
+#
+# 详细描述: 仙宫
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-04 16:30"""
+#-------------------------------------------------------------------------------
+
+import ShareDefine
+import PyDataManager
+import NetPackCommon
+import ChPyNetSendPack
+import PlayerCompensation
+import PlayerViewCache
+import CrossRealmMsg
+import IpyGameDataPY
+import PyGameData
+import GameWorld
+
+import time
+
+Def_UserDataKey_ServerIDList = "ServerIDList"
+Def_UserDataKey_PlayerInfo = "PlayerInfo"
+
+# 仙宫玩家记录
+def GetXGPlayerID(recData): return recData.GetValue1() # 仙宫玩家ID
+##--------------------------------------------------------------------------------------------------
+
+def OnPlayerLogin_CrossLogic(serverGroupID, serverID, playerID):
+    ## 玩家登录 - 跨服处理逻辑
+    
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetXiangongCount()):
+        ipyData = ipyDataMgr.GetXiangongByIndex(index)
+        if not ipyData:
+            continue
+        SendShowXiangongPlayerToClientServer(ipyData, serverGroupID, serverID, playerID)
+        
+    return
+
+def IsXiangongPlayer(playerID):
+    ## 是否仙宫玩家
+    gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+    recDataDict = gameRecMgr.GetGameRecDataDict(ShareDefine.Def_GameRecType_Xiangong)
+    for xiangongID in recDataDict.keys():
+        if gameRecMgr.GetGameRecDataMatch(ShareDefine.Def_GameRecType_Xiangong, xiangongID, [playerID], findone=True):
+            return True
+    return False
+
+def AddXiangongPlayer(xiangongID, playerID, serverIDList, rank=None, syncDict=None):
+    ## 添加新晋仙官玩家
+    if not xiangongID:
+        return
+    
+    ipyData = IpyGameDataPY.GetIpyGameData("Xiangong", xiangongID)
+    if not ipyData:
+        return
+    
+    gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+    recData = gameRecMgr.AddGameRecData(ShareDefine.Def_GameRecType_Xiangong, xiangongID, [playerID])
+    playerInfo = PlayerViewCache.GetShotCacheDict(playerID, "ServerID")
+    
+    serverID = playerInfo.get("ServerID", 0)
+    saveServerIDList = [] + serverIDList # 重新创建一份存储,不改变传入值
+    # 确保玩家自身一定能看到自己,跨服排位赛历史分区问题
+    if saveServerIDList and serverID and not GameWorld.CheckServerIDInList(serverID, saveServerIDList):
+        saveServerIDList.append(serverID)
+    recData.SetUserDataByKey(Def_UserDataKey_ServerIDList, saveServerIDList) # 保存当下的区服ID范围        
+    recData.SetUserDataByKey(Def_UserDataKey_PlayerInfo, playerInfo) # 保存当下的玩家基本信息
+    GameWorld.Log("新晋仙官玩家: xiangongID=%s,playerID=%s,rank=%s,serverID=%s,saveServerIDList=%s,%s" 
+                  % (xiangongID, playerID, rank, serverID, saveServerIDList, playerInfo))
+    
+    # 晋升邮件通知
+    if playerID > 10000 and rank:
+        titleID = ipyData.GetTitleID()
+        addItemList = ipyData.GetAwardItemList()
+        addQiyun = 0 if not addItemList else addItemList[0][1]
+        paramList = [rank, titleID, addQiyun]
+        PlayerCompensation.SendMailByKey(ipyData.GetMailKey(), [playerID], addItemList, paramList, crossMail=True)
+        
+    if isinstance(syncDict, dict):
+        if xiangongID not in syncDict:
+            syncDict[xiangongID] = []
+        newRecDataList = syncDict[xiangongID]
+        newRecDataList.append(recData)
+    return
+
+def SendNewXiangongPlayerToClientServer(syncDict):
+    ## 同步新晋仙宫玩家到子服
+    if not syncDict or not isinstance(syncDict, dict):
+        return
+    for xiangongID, newRecDataList in syncDict.items():
+        ipyData = IpyGameDataPY.GetIpyGameData("Xiangong", xiangongID)
+        if not ipyData:
+            continue
+        SendShowXiangongPlayerToClientServer(ipyData, syncRecDataList=newRecDataList)
+    return
+
+def SendShowXiangongPlayerToClientServer(ipyData, serverGroupID=0, playerServerID=0, queryPlayerID=0, syncRecDataList=None):
+    ## 发送需要展示的新晋仙宫玩家到子服
+    
+    if not ipyData:
+        return
+    xiangongID = ipyData.GetXiangongID()
+    showDays = ipyData.GetShowDays()
+    
+    curTime = int(time.time())
+    if syncRecDataList:
+        recDataList = syncRecDataList
+    else:
+        gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+        recDataList = gameRecMgr.GetGameRecDataList(ShareDefine.Def_GameRecType_Xiangong, xiangongID)
+        
+    if not recDataList:
+        return
+    
+    GameWorld.DebugLog("发送需要展示的新晋仙宫玩家到子服: xiangongID=%s,recDataLen=%s" % (xiangongID, len(recDataList)))
+    GameWorld.DebugLog("serverGroupID=%s,playerServerID=%s,queryPlayerID=%s" % (serverGroupID, playerServerID, queryPlayerID))
+    playerInfoList = []
+    for recData in recDataList[::-1]:
+        xgPlayerID = GetXGPlayerID(recData)
+        addTime = recData.GetTime()
+        passDays = GameWorld.GetDiff_Day(curTime, addTime) + 1
+        if passDays > showDays:
+            GameWorld.DebugLog("    xgPlayerID=%s,addTime=%s,passDays=%s > %s" % (xgPlayerID, addTime, passDays, showDays))
+            break
+        serverIDList = recData.GetUserDataByKey(Def_UserDataKey_ServerIDList)
+        if playerServerID:
+            if serverIDList == None:
+                GameWorld.DebugLog("    xgPlayerID=%s,serverIDList is None" % (xgPlayerID))
+                continue
+            if not GameWorld.CheckServerIDInList(playerServerID, serverIDList):
+                GameWorld.DebugLog("    xgPlayerID=%s,playerServerID=%s not in %s" % (xgPlayerID, playerServerID, serverIDList))
+                continue
+            
+        playerInfo = PlayerViewCache.GetShotCacheDict(xgPlayerID, "PlayerID", "ServerID", "Model")
+        if not playerInfo:
+            GameWorld.Log("找不到玩家缓存的暂不同步仙宫新晋仙官! xgPlayerID=%s" % xgPlayerID)
+            continue
+        playerInfo["AddTime"] = addTime
+        playerInfo["ServerIDList"] = serverIDList
+        
+        playerInfoList.insert(0, playerInfo)
+        
+    GameWorld.DebugLog("playerInfoListLen=%s" % (len(playerInfoList)))
+    if not playerInfoList:
+        return
+    
+    serverGroupIDList = [serverGroupID] if serverGroupID else []
+    dataMsg = {"msgType":"ShowXiangongPlayer", "xiangongID":xiangongID, "playerInfoList":playerInfoList, "queryPlayerID":queryPlayerID}
+    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_Xiangong, dataMsg, serverGroupIDList)
+    return
+
+def ClientServerMsg_QueryXiangong(serverGroupID, msgData):
+    ## 收到子服 - 查看仙名录
+    
+    serverID = msgData["serverID"]
+    queryPlayerID = msgData["queryPlayerID"]
+    xiangongID = msgData["xiangongID"]
+    
+    playerInfoList = []
+    maxSyncCount = min(IpyGameDataPY.GetFuncCfg("XiangongSet", 2), 200)
+    gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+    recDataList = gameRecMgr.GetGameRecDataList(ShareDefine.Def_GameRecType_Xiangong, xiangongID)
+    
+    for recData in recDataList[::-1]:
+        serverIDList = recData.GetUserDataByKey(Def_UserDataKey_ServerIDList)
+        playerInfo = recData.GetUserDataByKey(Def_UserDataKey_PlayerInfo)
+        if not playerInfo or not GameWorld.CheckServerIDInList(serverID, serverIDList):
+            continue
+        playerInfo["AddTime"] = recData.GetTime()
+        playerInfo["PlayerID"] = GetXGPlayerID(recData)
+        playerInfoList.insert(0, playerInfo)
+        if len(playerInfoList) >= maxSyncCount:
+            break
+        
+    # 没有记录也要回包
+    serverGroupList = [serverGroupID] # 仅通知查询服即可
+    sendMsg = {"msgType":"QueryXiangongPlayer", "xiangongID":xiangongID, "playerInfoList":playerInfoList, "queryPlayerID":queryPlayerID}
+    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_Xiangong, sendMsg, serverGroupList)
+    return
+
+##--------------------------------------------------------------------------------------------------
+
+#// A9 06 查看仙宫仙名录 #tagCGQueryXiangongRecPlayers
+#
+#struct    tagCGQueryXiangongRecPlayers
+#{
+#    tagHead        Head;
+#    WORD        XiangongID;    // 仙宫ID
+#};
+def OnQueryXiangongRecPlayers(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    xiangongID = clientData.XiangongID
+    
+    serverID = GameWorld.GetPlayerServerID(curPlayer)
+    dataMsg = {"serverID":serverID, "queryPlayerID":playerID, "xiangongID":xiangongID}
+    CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_QueryXiangong, dataMsg)
+    return
+
+#// A9 07 点赞仙宫 #tagCGLikeXiangong
+#
+#struct    tagCGLikeXiangong
+#{
+#    tagHead        Head;
+#    WORD        XiangongID;    // 仙宫ID,为0时代表每日的仙宫点赞
+#};
+def OnLikeXiangong(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    playerID = curPlayer.GetPlayerID()
+    xiangongID = clientData.XiangongID
+    
+    if xiangongID:
+        ipyData = IpyGameDataPY.GetIpyGameData("Xiangong", xiangongID)
+        if not ipyData:
+            return
+        showDays = ipyData.GetShowDays()
+        timeDict = PyGameData.g_xiangongCanLikeTimeDict.get(playerID, {})
+        if xiangongID not in timeDict:
+            GameWorld.DebugLog("该仙宫没有需要展示的新晋玩家记录! xiangongID=%s" % xiangongID, playerID)
+            return
+        addTime = timeDict[xiangongID]
+        passDays = GameWorld.GetDiff_Day(int(time.time()), addTime) + 1
+        if passDays > showDays:
+            GameWorld.DebugLog("该仙宫新晋展示时间超过最大展示天数,无法点赞! xiangongID=%s,addTime=%s,passDays=%s > %s" 
+                               % (xiangongID, addTime, passDays, showDays), playerID)
+            return
+        moneyType, moneyValue = ipyData.GetMoneyType(), ipyData.GetMoneyValue()
+    else:
+        moneyType, moneyValue = IpyGameDataPY.GetFuncEvalCfg("XiangongSet", 1)
+        
+    msgInfo = str(["LikeXiangong", [xiangongID, moneyType, moneyValue]])
+    curPlayer.MapServer_QueryPlayerResult(0, 0, "Xiangong", msgInfo, len(msgInfo))
+    return
+
+def CrossServerMsg_Xiangong(msgData):
+    ## 子服收到跨服信息
+    
+    msgType = msgData["msgType"]
+    
+    if msgType == "ShowXiangongPlayer":
+        __Client_ShowXiangongPlayer(msgData)
+        
+    elif msgType == "QueryXiangongPlayer":
+        __Client_QueryXiangongPlayer(msgData)
+        
+    return
+
+def __Client_ShowXiangongPlayer(msgData):
+    ## 子服收到 - 跨服同步展示的新晋仙宫玩家
+    
+    xiangongID = msgData["xiangongID"]
+    playerInfoList = msgData["playerInfoList"]
+    queryPlayerID = msgData.get("queryPlayerID", 0)
+    
+    if not playerInfoList:
+        return
+    
+    newPlayerList = []
+    for playerInfo in playerInfoList:
+        newP = ChPyNetSendPack.tagGCXiangongNewPlayer()
+        newP.AddTime = playerInfo["AddTime"]
+        newP.ServerID = playerInfo["ServerID"]
+        newP.PlayerID = playerInfo["PlayerID"]
+        newP.Name = playerInfo["Name"]
+        newP.NameLen = len(newP.Name)
+        newP.LV = playerInfo["LV"]
+        newP.Job = playerInfo["Job"]
+        newP.RealmLV = playerInfo["RealmLV"]
+        newP.EquipShowSwitch = playerInfo["EquipShowSwitch"]
+        newP.EquipShowID = playerInfo["EquipShowID"]
+        newP.EquipShowIDCount = len(newP.EquipShowID)
+        newPlayerList.append(newP)
+        
+    if not newPlayerList:
+        return
+    
+    if queryPlayerID:
+        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(queryPlayerID)
+        if not curPlayer:
+            return
+        __updXiangongCanLikeTime(queryPlayerID, xiangongID, playerInfoList[-1]["AddTime"])
+        clientPack = ChPyNetSendPack.tagGCXiangongNewPlayerInfo()
+        clientPack.XiangongID = xiangongID
+        clientPack.NewPlayerList = newPlayerList[-255:]
+        clientPack.NewPlayerCount = len(clientPack.NewPlayerList)
+        NetPackCommon.SendFakePack(curPlayer, clientPack)
+        return
+    
+    ## 全服同步
+    clientPack = ChPyNetSendPack.tagGCXiangongNewPlayerInfo()
+    clientPack.XiangongID = xiangongID
+    
+    playerManager = GameWorld.GetPlayerManager()
+    for i in range(0, playerManager.GetPlayerCount()):
+        curPlayer = playerManager.GetPlayerByIndex(i)
+        if curPlayer == None or not curPlayer.GetInitOK():
+            continue
+        syncNewPlayerList = []
+        for nIndex, newP in enumerate(newPlayerList):
+            playerInfo = playerInfoList[nIndex]
+            serverIDList = playerInfo["ServerIDList"]
+            if not GameWorld.CheckServerIDInList(GameWorld.GetPlayerServerID(curPlayer), serverIDList):
+                continue
+            syncNewPlayerList.append(newP)
+            __updXiangongCanLikeTime(curPlayer.GetPlayerID(), xiangongID, playerInfo["AddTime"])
+        if not syncNewPlayerList:
+            continue
+        clientPack.NewPlayerList = syncNewPlayerList[-255:]
+        clientPack.NewPlayerCount = len(clientPack.NewPlayerList)
+        NetPackCommon.SendFakePack(curPlayer, clientPack)
+        
+    return
+
+def __updXiangongCanLikeTime(playerID, xiangongID, addTime):
+    if playerID not in PyGameData.g_xiangongCanLikeTimeDict:
+        PyGameData.g_xiangongCanLikeTimeDict[playerID] = {}
+    timeDict = PyGameData.g_xiangongCanLikeTimeDict[playerID]
+    canLikeTime = timeDict.get(xiangongID, 0)
+    if addTime > canLikeTime:
+        timeDict[xiangongID] = addTime
+        GameWorld.DebugLog("更新玩家对应仙宫可点赞的最新时间戳: xiangongID=%s,addTime=%s" % (xiangongID, addTime), playerID)
+    return
+
+def __Client_QueryXiangongPlayer(msgData):
+    ## 子服收到 - 跨服同步的查询仙名录回包
+    
+    xiangongID = msgData["xiangongID"]
+    playerInfoList = msgData["playerInfoList"]
+    queryPlayerID = msgData.get("queryPlayerID", 0)
+    
+    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(queryPlayerID)
+    if not curPlayer:
+        return
+    
+    recPlayerList = []
+    for playerInfo in playerInfoList:
+        if not playerInfo:
+            continue
+        recP = ChPyNetSendPack.tagGCXiangongRecPlayer()
+        recP.AddTime = playerInfo["AddTime"]
+        recP.ServerID = playerInfo["ServerID"]
+        recP.PlayerID = playerInfo["PlayerID"]
+        recP.Name = playerInfo["Name"]
+        recP.NameLen = len(recP.Name)
+        recP.LV = playerInfo["LV"]
+        recP.Job = playerInfo["Job"]
+        recP.RealmLV = playerInfo["RealmLV"]
+        recPlayerList.append(recP)
+        
+    clientPack = ChPyNetSendPack.tagGCXiangongRecPlayerInfo()
+    clientPack.XiangongID = xiangongID
+    clientPack.RecPlayerList = recPlayerList
+    clientPack.RecPlayerCount = len(clientPack.RecPlayerList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
index cb07bdd..2a98b53 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -499,6 +499,7 @@
                         ("list", "MemAwardItemList", 0),
                         ("DWORD", "NeedScore", 0),
                         ("dict", "ScoreAwardEx", 0),
+                        ("WORD", "XiangongID", 0),
                         ),
 
                 "CrossActBossTrial":(
@@ -549,6 +550,7 @@
                         ("list", "AwardItemList", 0),
                         ("DWORD", "NeedScore", 0),
                         ("dict", "ScoreAwardEx", 0),
+                        ("WORD", "XiangongID", 0),
                         ),
 
                 "ActGubao":(
@@ -581,6 +583,7 @@
                         ("list", "AwardItemList", 0),
                         ("DWORD", "NeedScore", 0),
                         ("dict", "ScoreAwardEx", 0),
+                        ("WORD", "XiangongID", 0),
                         ),
 
                 "ActXianXiaMJ":(
@@ -615,6 +618,7 @@
                         ("list", "AwardItemList", 0),
                         ("DWORD", "NeedScore", 0),
                         ("dict", "ScoreAwardEx", 0),
+                        ("WORD", "XiangongID", 0),
                         ),
 
                 "ActGodGift":(
@@ -851,6 +855,7 @@
                         ("BYTE", "Rank", 1),
                         ("list", "RankAwardItemList", 0),
                         ("WORD", "MainOfficialID", 0),
+                        ("WORD", "XiangongID", 0),
                         ),
 
                 "ChampionshipOfficial":(
@@ -1139,6 +1144,16 @@
                         ("BYTE", "WorshipDays", 0),
                         ("BYTE", "MoneyType", 0),
                         ("list", "MoneyRange", 0),
+                        ),
+
+                "Xiangong":(
+                        ("WORD", "XiangongID", 1),
+                        ("BYTE", "ShowDays", 0),
+                        ("BYTE", "MoneyType", 0),
+                        ("DWORD", "MoneyValue", 0),
+                        ("DWORD", "TitleID", 0),
+                        ("list", "AwardItemList", 0),
+                        ("char", "MailKey", 0),
                         ),
 
                 "FairyDomain":(
@@ -1840,7 +1855,8 @@
     def GetAwardItemList(self): return self.attrTuple[2] # 奖励物品列表[[物品ID,个数,是否拍品], ...] 仙盟榜时为盟主奖励,如果没有配置,则统一取成员奖励 list
     def GetMemAwardItemList(self): return self.attrTuple[3] # 仙盟榜成员奖励物品信息列表[[物品ID,个数,是否拍品], ...] list
     def GetNeedScore(self): return self.attrTuple[4] # 上榜所需积分 DWORD
-    def GetScoreAwardEx(self): return self.attrTuple[5] # 达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...} dict
+    def GetScoreAwardEx(self): return self.attrTuple[5] # 达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...} dict
+    def GetXiangongID(self): return self.attrTuple[6] # 晋升仙宫ID WORD
 
 # Boss历练跨服活动表
 class IPY_CrossActBossTrial():
@@ -1910,7 +1926,8 @@
     def GetRank(self): return self.attrTuple[1] # 名次 BYTE
     def GetAwardItemList(self): return self.attrTuple[2] # 奖励物品列表[[物品ID,个数,是否拍品], ...] list
     def GetNeedScore(self): return self.attrTuple[3] # 上榜所需积分 DWORD
-    def GetScoreAwardEx(self): return self.attrTuple[4] # 达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...} dict
+    def GetScoreAwardEx(self): return self.attrTuple[4] # 达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...} dict
+    def GetXiangongID(self): return self.attrTuple[5] # 晋升仙宫ID WORD
 
 # 古宝养成活动时间表
 class IPY_ActGubao():
@@ -1957,7 +1974,8 @@
     def GetRank(self): return self.attrTuple[1] # 名次 BYTE
     def GetAwardItemList(self): return self.attrTuple[2] # 奖励物品列表[[物品ID,个数,是否拍品], ...] list
     def GetNeedScore(self): return self.attrTuple[3] # 上榜所需积分 DWORD
-    def GetScoreAwardEx(self): return self.attrTuple[4] # 达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...} dict
+    def GetScoreAwardEx(self): return self.attrTuple[4] # 达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...} dict
+    def GetXiangongID(self): return self.attrTuple[5] # 晋升仙宫ID WORD
 
 # 仙匣秘境活动时间表
 class IPY_ActXianXiaMJ():
@@ -2006,7 +2024,8 @@
     def GetRank(self): return self.attrTuple[1] # 名次 BYTE
     def GetAwardItemList(self): return self.attrTuple[2] # 奖励物品列表[[物品ID,个数,是否拍品], ...] list
     def GetNeedScore(self): return self.attrTuple[3] # 上榜所需积分 DWORD
-    def GetScoreAwardEx(self): return self.attrTuple[4] # 达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...} dict
+    def GetScoreAwardEx(self): return self.attrTuple[4] # 达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...} dict
+    def GetXiangongID(self): return self.attrTuple[5] # 晋升仙宫ID WORD
 
 # 天帝礼包活动时间表
 class IPY_ActGodGift():
@@ -2347,7 +2366,8 @@
         
     def GetRank(self): return self.attrTuple[0] #  名次 BYTE
     def GetRankAwardItemList(self): return self.attrTuple[1] # 名次奖励物品列表 list
-    def GetMainOfficialID(self): return self.attrTuple[2] # 主官职ID WORD
+    def GetMainOfficialID(self): return self.attrTuple[2] # 主官职ID WORD
+    def GetXiangongID(self): return self.attrTuple[3] # 晋升仙宫ID WORD
 
 # 跨服排位官职表
 class IPY_ChampionshipOfficial():
@@ -2777,6 +2797,21 @@
     def GetMoneyType(self): return self.attrTuple[3] # 膜拜货币类型 BYTE
     def GetMoneyRange(self): return self.attrTuple[4] # 货币值范围 list
 
+# 仙宫表
+class IPY_Xiangong():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetXiangongID(self): return self.attrTuple[0] # 仙宫ID WORD
+    def GetShowDays(self): return self.attrTuple[1] # 展示天数 BYTE
+    def GetMoneyType(self): return self.attrTuple[2] # 点赞货币类型 BYTE
+    def GetMoneyValue(self): return self.attrTuple[3] # 货币值 DWORD
+    def GetTitleID(self): return self.attrTuple[4] # 称号ID DWORD
+    def GetAwardItemList(self): return self.attrTuple[5] # 晋级仙宫奖励物品列表 list
+    def GetMailKey(self): return self.attrTuple[6] # 仙官通知邮件 char
+
 # 缥缈仙域表
 class IPY_FairyDomain():
     
@@ -2947,6 +2982,7 @@
         self.__LoadFileData("FamilyWarRankAward", onlyCheck)
         self.__LoadFileData("AssistThanksGift", onlyCheck)
         self.__LoadFileData("Worship", onlyCheck)
+        self.__LoadFileData("Xiangong", onlyCheck)
         self.__LoadFileData("FairyDomain", onlyCheck)
         Log("IPY_DataMgr ReloadOK! onlyCheck=%s" % onlyCheck)
         return
@@ -3881,6 +3917,13 @@
         self.CheckLoadData("Worship")
         return self.ipyWorshipCache[index]
 
+    def GetXiangongCount(self):
+        self.CheckLoadData("Xiangong")
+        return self.ipyXiangongLen
+    def GetXiangongByIndex(self, index):
+        self.CheckLoadData("Xiangong")
+        return self.ipyXiangongCache[index]
+
     def GetFairyDomainCount(self):
         self.CheckLoadData("FairyDomain")
         return self.ipyFairyDomainLen
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
index ec8d8a6..1c6f7dc 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
@@ -81,6 +81,7 @@
 import GameWorldMineArea
 import PlayerRecData
 import GameWorship
+import GameXiangong
 #---------------------------------------------------------------------
 
 #---------------------------------------------------------------------
@@ -666,6 +667,7 @@
     if not PlayerControl.GetIsTJG(curPlayer):
         playerID = curPlayer.GetPlayerID()
         PyGameData.g_unTJLogoffTime[playerID] = int(time.time())
+        PyGameData.g_xiangongCanLikeTimeDict.pop(playerID, None)
         
         #在线状态变更,放最后
         __OnPlayerOnlineStateChange(curPlayer, False)
@@ -703,6 +705,15 @@
     
     isLogout = not isOnline
     PlayerViewCache.UpdCrossCacheBase(playerID, cacheBase, isLogout)
+    serverID = GameWorld.GetAccIDServerID(cacheBase["AccID"])
+    
+    # 上线
+    if isOnline:
+        GameXiangong.OnPlayerLogin_CrossLogic(serverGroupID, serverID, playerID)
+        
+    # 下线
+    else:
+        pass
     
     SyncCrossPlayerOnlineStateToRelatedPlayer(playerID)
     return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActBossTrial.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActBossTrial.py
index b90fac9..f3f8f5d 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActBossTrial.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActBossTrial.py
@@ -27,6 +27,7 @@
 import CrossBillboard
 import PlayerFamily
 import PyDataManager
+import GameXiangong
 
 def OnActStart(actNum):
     ## 活动开启
@@ -565,13 +566,14 @@
     
     PersonalTemplateID = ipyData.GetPersonalTemplateID()
     FamilyTemplateID = ipyData.GetFamilyTemplateID()
+    serverIDRangeList = ipyData.GetServerIDRangeList()
     
-    __GiveCrossOrderAwardPersonal(cfgID, zoneID, PersonalTemplateID, ShareDefine.Def_CBT_BossTrialSubmit)
+    __GiveCrossOrderAwardPersonal(cfgID, zoneID, PersonalTemplateID, ShareDefine.Def_CBT_BossTrialSubmit, serverIDRangeList)
     __GiveCrossOrderAwardFamily(cfgID, zoneID, FamilyTemplateID, ShareDefine.Def_CBT_BossTrialSubmitFamily)
     GameWorld.Log("=================================================================================")
     return
     
-def __GiveCrossOrderAwardPersonal(cfgID, zoneID, templateID, billboardType):
+def __GiveCrossOrderAwardPersonal(cfgID, zoneID, templateID, billboardType, serverIDRangeList):
     
     groupValue1 = zoneID
     #billboardType = ShareDefine.Def_CBT_BossTrialSubmit #榜单类型改为参数传入,异常情况下可特殊处理用备份榜单发奖励
@@ -593,6 +595,7 @@
     if not orderIpyDataList:
         return
     
+    syncNewXiangongDict = {}
     rankPre = 0
     billboardIndex = 0
     for ipyData in orderIpyDataList:
@@ -602,6 +605,7 @@
         scoreAwardExList = scoreAwardEx.keys()
         scoreAwardExList.sort()
         awardItemList = ipyData.GetAwardItemList()
+        xiangongID = ipyData.GetXiangongID()
         orderCountTotal = rank - rankPre # 奖励名次数量
         rankPre = rank
         
@@ -632,6 +636,8 @@
             orderCountTotal -= 1
             billboardIndex += 1
             
+            GameXiangong.AddXiangongPlayer(xiangongID, playerID, serverIDRangeList, playerRank, syncNewXiangongDict)
+    GameXiangong.SendNewXiangongPlayerToClientServer(syncNewXiangongDict)
     return
 
 def __GiveCrossOrderAwardFamily(cfgID, zoneID, templateID, billboardType):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActGubao.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActGubao.py
index 4055fcc..221f58b 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActGubao.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActGubao.py
@@ -26,6 +26,7 @@
 import CrossBillboard
 import PyDataManager
 import CrossRealmMsg
+import GameXiangong
 import GameWorld
 
 def OnActStart(actNum, ipyData):
@@ -316,12 +317,13 @@
     GameWorld.Log("=== 跨服古宝养成活动发放榜单奖励! === cfgID=%s,zoneID=%s" % (cfgID, zoneID))
     
     PersonalTemplateID = ipyData.GetPersonalTemplateID()
+    serverIDRangeList = ipyData.GetServerIDRangeList()
     
-    __GiveCrossOrderAwardPersonal(cfgID, zoneID, PersonalTemplateID, ShareDefine.Def_CBT_GubaoScore)
+    __GiveCrossOrderAwardPersonal(cfgID, zoneID, PersonalTemplateID, ShareDefine.Def_CBT_GubaoScore, serverIDRangeList)
     GameWorld.Log("=================================================================================")
     return
     
-def __GiveCrossOrderAwardPersonal(cfgID, zoneID, templateID, billboardType):
+def __GiveCrossOrderAwardPersonal(cfgID, zoneID, templateID, billboardType, serverIDRangeList):
     
     groupValue1 = zoneID
     billboardMgr = PyDataManager.GetCrossBillboardManager()
@@ -342,6 +344,7 @@
     if not orderIpyDataList:
         return
     
+    syncNewXiangongDict = {}
     rankPre = 0
     billboardIndex = 0
     for ipyData in orderIpyDataList:
@@ -351,6 +354,7 @@
         scoreAwardExList = scoreAwardEx.keys()
         scoreAwardExList.sort()
         awardItemList = ipyData.GetAwardItemList()
+        xiangongID = ipyData.GetXiangongID()
         orderCountTotal = rank - rankPre # 奖励名次数量
         rankPre = rank
         
@@ -381,5 +385,7 @@
             orderCountTotal -= 1
             billboardIndex += 1
             
+            GameXiangong.AddXiangongPlayer(xiangongID, playerID, serverIDRangeList, playerRank, syncNewXiangongDict)
+    GameXiangong.SendNewXiangongPlayerToClientServer(syncNewXiangongDict)
     return
 
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActHorsePetTrain.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActHorsePetTrain.py
index 8ae1bc2..52d56cc 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActHorsePetTrain.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActHorsePetTrain.py
@@ -25,6 +25,7 @@
 import CrossBillboard
 import PyDataManager
 import CrossRealmMsg
+import GameXiangong
 import GameWorld
 
 def OnActStart(actNum, ipyData):
@@ -315,12 +316,13 @@
     GameWorld.Log("=== 跨服骑宠养成活动发放榜单奖励! === cfgID=%s,zoneID=%s" % (cfgID, zoneID))
     
     PersonalTemplateID = ipyData.GetPersonalTemplateID()
+    serverIDRangeList = ipyData.GetServerIDRangeList()
     
-    __GiveCrossOrderAwardPersonal(cfgID, zoneID, PersonalTemplateID, ShareDefine.Def_CBT_HorsePetTrainScore)
+    __GiveCrossOrderAwardPersonal(cfgID, zoneID, PersonalTemplateID, ShareDefine.Def_CBT_HorsePetTrainScore, serverIDRangeList)
     GameWorld.Log("=================================================================================")
     return
     
-def __GiveCrossOrderAwardPersonal(cfgID, zoneID, templateID, billboardType):
+def __GiveCrossOrderAwardPersonal(cfgID, zoneID, templateID, billboardType, serverIDRangeList):
     
     groupValue1 = zoneID
     billboardMgr = PyDataManager.GetCrossBillboardManager()
@@ -341,6 +343,7 @@
     if not orderIpyDataList:
         return
     
+    syncNewXiangongDict = {}
     rankPre = 0
     billboardIndex = 0
     for ipyData in orderIpyDataList:
@@ -350,6 +353,7 @@
         scoreAwardExList = scoreAwardEx.keys()
         scoreAwardExList.sort()
         awardItemList = ipyData.GetAwardItemList()
+        xiangongID = ipyData.GetXiangongID()
         orderCountTotal = rank - rankPre # 奖励名次数量
         rankPre = rank
         
@@ -379,6 +383,8 @@
             
             orderCountTotal -= 1
             billboardIndex += 1
-                
+            
+            GameXiangong.AddXiangongPlayer(xiangongID, playerID, serverIDRangeList, playerRank, syncNewXiangongDict)
+    GameXiangong.SendNewXiangongPlayerToClientServer(syncNewXiangongDict)
     return
 
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActXianXiaMJ.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActXianXiaMJ.py
index 75ed919..02f46f9 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActXianXiaMJ.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerActXianXiaMJ.py
@@ -25,6 +25,7 @@
 import CrossBillboard
 import PyDataManager
 import CrossRealmMsg
+import GameXiangong
 import GameWorld
 
 def OnActStart(actNum, ipyData):
@@ -315,12 +316,13 @@
     GameWorld.Log("=== 跨服仙匣秘境活动发放榜单奖励! === cfgID=%s,zoneID=%s" % (cfgID, zoneID))
     
     PersonalTemplateID = ipyData.GetPersonalTemplateID()
+    serverIDRangeList = ipyData.GetServerIDRangeList()
     
-    __GiveCrossOrderAwardPersonal(cfgID, zoneID, PersonalTemplateID, ShareDefine.Def_CBT_XianXiaMJScore)
+    __GiveCrossOrderAwardPersonal(cfgID, zoneID, PersonalTemplateID, ShareDefine.Def_CBT_XianXiaMJScore, serverIDRangeList)
     GameWorld.Log("=================================================================================")
     return
     
-def __GiveCrossOrderAwardPersonal(cfgID, zoneID, templateID, billboardType):
+def __GiveCrossOrderAwardPersonal(cfgID, zoneID, templateID, billboardType, serverIDRangeList):
     
     groupValue1 = zoneID
     billboardMgr = PyDataManager.GetCrossBillboardManager()
@@ -341,6 +343,7 @@
     if not orderIpyDataList:
         return
     
+    syncNewXiangongDict = {}
     rankPre = 0
     billboardIndex = 0
     for ipyData in orderIpyDataList:
@@ -350,6 +353,7 @@
         scoreAwardExList = scoreAwardEx.keys()
         scoreAwardExList.sort()
         awardItemList = ipyData.GetAwardItemList()
+        xiangongID = ipyData.GetXiangongID()
         orderCountTotal = rank - rankPre # 奖励名次数量
         rankPre = rank
         
@@ -380,5 +384,7 @@
             orderCountTotal -= 1
             billboardIndex += 1
             
+            GameXiangong.AddXiangongPlayer(xiangongID, playerID, serverIDRangeList, playerRank, syncNewXiangongDict)
+    GameXiangong.SendNewXiangongPlayerToClientServer(syncNewXiangongDict)
     return
 
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFuncTeam.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFuncTeam.py
index affb702..3e7543a 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFuncTeam.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFuncTeam.py
@@ -70,7 +70,7 @@
     def GetSyncDict(self):
         # Value 暂时只同步1~2
         syncDict = {"PlayerID":self.GetPlayerID(), "Value1":self.GetValue1(), "Value2":self.GetValue2()}
-        syncDict.update(PlayerViewCache.GetShotCahceDict(self.GetPlayerID(), False))
+        syncDict.update(PlayerViewCache.GetShotCacheDict(self.GetPlayerID(), "PlayerID", "FightPower", "ServerID", "OfflineValue"))
         return syncDict
     
 class PyFuncTeam():
@@ -127,7 +127,7 @@
         ApplyList = []
         if applyDetail:
             for applyID in ApplyIDList[::-1]:
-                applyPlayerDict = PlayerViewCache.GetShotCahceDict(applyID, False)
+                applyPlayerDict = PlayerViewCache.GetShotCacheDict(applyID, "PlayerID", "FightPower", "ServerID")
                 if not applyPlayerDict:
                     ApplyIDList.remove(applyID)
                 else:
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
index 104a736..9e35962 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
@@ -20,6 +20,7 @@
 
 import GameWorld
 import GameWorship
+import GameXiangong
 import PlayerControl
 import NetPackCommon
 import GameWorldArena
@@ -67,6 +68,9 @@
         return True
     
     if PyDataManager.GetDBPyFuncTeamManager().IsTeamPlayer(playerID):
+        return True
+    
+    if GameXiangong.IsXiangongPlayer(playerID):
         return True
     
     if GameWorldSkyTower.IsSkyTowerPassPlayer(playerID):
@@ -188,28 +192,33 @@
         curCache.PropDataDict = eval(curCache.PropData)
     return curCache.PropDataDict
 
-def GetShotCahceDict(playerID, withEquip=False):
+def GetShotCacheDict(playerID, *exAttrs):
     ## 获取玩家简短的缓存信息字典
     viewCache = FindViewCache(playerID)
     cacheDict = GetCachePropDataDict(viewCache)
     if not cacheDict:
         return {}
-    olMgr = ChPlayer.GetOnlinePlayerMgr()
     shotCacheDict = {
-                     "PlayerID":playerID, 
                      "Name":cacheDict["Name"], 
                      "Job":cacheDict["Job"], 
                      "LV":cacheDict["LV"], 
                      "RealmLV":cacheDict["RealmLV"], 
-                     "FightPower":cacheDict["FightPower"],
-                     "ServerID":GameWorld.GetAccIDServerID(cacheDict["AccID"]),
-                     "OfflineValue":olMgr.GetOfflineValue(playerID, viewCache)
                      }
-    if withEquip:
+    if "PlayerID" in exAttrs:
+        shotCacheDict["PlayerID"] = playerID
+    if "FightPower" in exAttrs:
+        shotCacheDict["FightPower"] = cacheDict["FightPower"]
+    if "ServerID" in exAttrs:
+        shotCacheDict["ServerID"] = GameWorld.GetAccIDServerID(cacheDict["AccID"])
+    if "OfflineValue" in exAttrs:
+        olMgr = ChPlayer.GetOnlinePlayerMgr()
+        shotCacheDict["OfflineValue"] = olMgr.GetOfflineValue(playerID, viewCache)
+    # 附带外观模型展示相关
+    if "Model" in exAttrs:
         shotCacheDict.update({
                               "TitleID":cacheDict.get("TitleID", 0),
                               "EquipShowSwitch":cacheDict.get("EquipShowSwitch", 0),
-                              "EquipShowID":cacheDict.get("EquipShowID", 0),
+                              "EquipShowID":cacheDict.get("EquipShowID", []),
                               })
     return shotCacheDict
 
@@ -229,7 +238,7 @@
                  "TitleID":cacheDict.get("TitleID", 0),
                  "FightPower":PlayerControl.GetFightPower(curPlayer),
                  "EquipShowSwitch":cacheDict.get("EquipShowSwitch", 0),
-                 "EquipShowID":cacheDict.get("EquipShowID", 0),
+                 "EquipShowID":cacheDict.get("EquipShowID", []),
                  "ServerGroupID":PlayerControl.GetPlayerServerGroupID(curPlayer),
                  }
     return cacheBase
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py b/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
index 063395f..7abc70c 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
@@ -26,6 +26,7 @@
 import CrossRealmPK
 import AuctionHouse
 import PlayerAssist
+import GameRecData
 import PlayerRecData
 import GameWorldMineArea
 import PyGameDataStruct
@@ -315,6 +316,7 @@
 
 class PyGameDataManager(object):
     def __init__(self):
+        self.DBGameRecDataManager = GameRecData.DBGameRecDataManager()
         self.DBPyFuncTeamManager = PlayerFuncTeam.DBPyFuncTeamManager()
         self.DBPyFuncTeamMemManager = PlayerFuncTeam.DBPyFuncTeamMemManager()
         self.DBPlayerRecDataManager = PlayerRecData.DBPlayerRecDataManager()
@@ -350,6 +352,7 @@
 
     def GetSaveData(self):
         buff = ""
+        buff += self.DBGameRecDataManager.GetSaveData()
         buff += self.DBPyFuncTeamManager.GetSaveData()
         buff += self.DBPyFuncTeamMemManager.GetSaveData()
         buff += self.DBPlayerRecDataManager.GetSaveData()
@@ -384,6 +387,7 @@
         return buff
     
     def LoadGameData(self, gameBuffer, pos):
+        pos = self.DBGameRecDataManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
         pos = self.DBPyFuncTeamManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
         pos = self.DBPyFuncTeamMemManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
         pos = self.DBPlayerRecDataManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
@@ -505,6 +509,11 @@
     pyGameDataMgr = GetPyGameDataManager()
     return pyGameDataMgr.familyStoreItemManager
 
+def GetDBGameRecDataManager():
+    # 通用记录表新管理
+    pyGameDataMgr = GetPyGameDataManager()
+    return pyGameDataMgr.DBGameRecDataManager
+
 def GetDBPyFuncTeamManager():
     # 功能队伍管理
     pyGameDataMgr = GetPyGameDataManager()
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py b/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
index 10891b7..518c228 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
@@ -162,4 +162,6 @@
 g_familyTalkCache = {} #{familyID:[[time,content,extras],..]}
 g_worldTalkCache = [] #[[time,name, playerID, content,extras],..]
 
+g_xiangongCanLikeTimeDict = {} # 本服玩家对应仙宫可点赞最新时间信息 {playerID:{仙宫ID:addTime, ...}, ...}
+
 g_unTJLogoffTime = {} #非脱机离线时间 {playerID:time, ...}
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py b/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
index 9b43f57..92b6bac 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
@@ -3395,4 +3395,134 @@
             self.TeamName = Str
         else:
             self.TeamName = Str[:33]
-            
+
+
+# 通用记录表新 #tagDBGameRec
+class tagDBGameRec(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('RecType', ctypes.c_ushort),
+        ('RecID', ctypes.c_ulong),
+        ('Time', ctypes.c_double),
+        ('Value1', ctypes.c_ulong),
+        ('Value2', ctypes.c_ulong),
+        ('Value3', ctypes.c_ulong),
+        ('Value4', ctypes.c_ulong),
+        ('Value5', ctypes.c_ulong),
+        ('Value6', ctypes.c_ulong),
+        ('Value7', ctypes.c_ulong),
+        ('Value8', ctypes.c_ulong),
+        ('UserDataLen', ctypes.c_ushort),
+        ('UserData', ctypes.c_char_p),
+        ('ADOResult', ctypes.c_ulong),
+    ]
+
+    def __init__(self):
+        Structure.__init__(self)
+        self.clear()
+
+    def clear(self):
+        self.RecType = 0
+        self.RecID = 0
+        self.Time = 0.0
+        self.Value1 = 0
+        self.Value2 = 0
+        self.Value3 = 0
+        self.Value4 = 0
+        self.Value5 = 0
+        self.Value6 = 0
+        self.Value7 = 0
+        self.Value8 = 0
+        self.UserDataLen = 0
+        self.UserData = ''
+
+    def readData(self, buf, pos = 0, length = 0):
+        if not pos <= length:
+            return -1
+        if len(buf) < pos + self.getLength():
+            return -1
+        self.clear()
+        self.RecType, pos = CommFunc.ReadWORD(buf, pos)
+        self.RecID, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Time, pos = CommFunc.ReadDouble(buf, pos)
+        self.Value1, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value2, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value3, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value4, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value5, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value6, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value7, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Value8, pos = CommFunc.ReadDWORD(buf, pos)
+        self.UserDataLen, pos = CommFunc.ReadWORD(buf, pos)
+        tmp, pos = CommFunc.ReadString(buf, pos, self.UserDataLen)
+        self.UserData = ctypes.c_char_p(tmp)
+        return self.getLength()
+
+    def getBuffer(self):
+        buf = ''
+        buf = CommFunc.WriteWORD(buf, self.RecType)
+        buf = CommFunc.WriteDWORD(buf, self.RecID)
+        buf = CommFunc.WriteDouble(buf, self.Time)
+        buf = CommFunc.WriteDWORD(buf, self.Value1)
+        buf = CommFunc.WriteDWORD(buf, self.Value2)
+        buf = CommFunc.WriteDWORD(buf, self.Value3)
+        buf = CommFunc.WriteDWORD(buf, self.Value4)
+        buf = CommFunc.WriteDWORD(buf, self.Value5)
+        buf = CommFunc.WriteDWORD(buf, self.Value6)
+        buf = CommFunc.WriteDWORD(buf, self.Value7)
+        buf = CommFunc.WriteDWORD(buf, self.Value8)
+        buf = CommFunc.WriteWORD(buf, self.UserDataLen)
+        buf = CommFunc.WriteString(buf, self.UserDataLen, self.UserData)
+        return buf
+
+    def getLength(self):
+        length = 0
+        length += sizeof(ctypes.c_ushort)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_double)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ulong)
+        length += sizeof(ctypes.c_ushort)
+        length += self.UserDataLen
+        return length
+
+    def outputString(self):
+        output = '''// 通用记录表新 #tagDBGameRec:
+            RecType = %s,
+            RecID = %s,
+            Time = %s,
+            Value1 = %s,
+            Value2 = %s,
+            Value3 = %s,
+            Value4 = %s,
+            Value5 = %s,
+            Value6 = %s,
+            Value7 = %s,
+            Value8 = %s,
+            UserDataLen = %s,
+            UserData = %s,
+            ADOResult = %s,
+            '''%(
+                self.RecType,
+                self.RecID,
+                self.Time,
+                self.Value1,
+                self.Value2,
+                self.Value3,
+                self.Value4,
+                self.Value5,
+                self.Value6,
+                self.Value7,
+                self.Value8,
+                self.UserDataLen,
+                self.UserData,
+                self.ADOResult,
+            )
+        return output
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
index 2f5a5c6..a43e0ef 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -1146,7 +1146,8 @@
 CDBPlayerRefresh_BossFinalHurtPer,  # Boss最终输出伤害百分比 264
 CDBPlayerRefresh_HorsePetTrainScore, # 骑宠养成积分 265
 CDBPlayerRefresh_GubaoTrainScore, # 古宝养成积分 266
-) = range(146, 267)
+CDBPlayerRefresh_TiandaoFruit, # 天道果 267
+) = range(146, 268)
 
 TYPE_Price_Gold_Paper_Money = 5    # 金钱类型,(先用礼券,再用金子)
 TYPE_Price_Family_Contribution = 6 # 战盟贡献度(活跃度转换得来)
@@ -1181,6 +1182,7 @@
 TYPE_Price_GatherSoul = 44    # 聚魂精华
 TYPE_Price_HorsePetTrainScore = 45    # 骑宠养成积分
 TYPE_Price_GubaoTrainScore = 46    # 古宝养成积分
+TYPE_Price_TiandaoFruit = 47    # 天道果
 TYPE_Price_PayCoin = 99    # 代币
 
 #key可用于遍历所有货币,value仅GM相关会用到
@@ -1188,7 +1190,7 @@
                  1:"仙玉", 2:"绑玉", 3:"铜钱", 6:"战盟贡献度", 10:"战盟仓库积分", 13:"境界修行点", 14:"符印融合石", 15:"仙盟活跃令", 
                  16:"助战积分", 18:"荣誉", 19:"Boss积分", 23:"符印精华", 24:"符印碎片", 25:"寻宝积分", 26:"集市额度", 27:"丹精", 28:"魂尘", 
                  29:"聚魂碎片", 30:"核心环", 31:"功能特权令", 32:"环保值", 33:"GM令", 34:"古神币", 35:"功德点", 
-                 39:"成就积分", 40:"万界积分", 43:"凭证积分", 44:"聚魂精华", 45:"骑宠养成积分", 46:"古宝养成积分", 99:"代币"
+                 39:"成就积分", 40:"万界积分", 43:"凭证积分", 44:"聚魂精华", 45:"骑宠养成积分", 46:"古宝养成积分", 47:"天道果", 99:"代币"
                  }
 
 #以下是旧的金钱类型
@@ -1224,6 +1226,7 @@
                            TYPE_Price_GatherSoul:CDBPlayerRefresh_GatherSoul,
                            TYPE_Price_HorsePetTrainScore:CDBPlayerRefresh_HorsePetTrainScore,
                            TYPE_Price_GubaoTrainScore:CDBPlayerRefresh_GubaoTrainScore,
+                           TYPE_Price_TiandaoFruit:CDBPlayerRefresh_TiandaoFruit,
                            }
 
 # 支持负值的货币及对应0418刷新类型
@@ -1364,6 +1367,15 @@
                          Def_PlayerRecType_WorshipDaily, # 玩家每日膜拜记录 2
                          Def_PlayerRecType_PayCoin, # 代币记录 3
                          ) = range(1, 1 + 3)
+
+#通用信息记录类型 - 新 从 300 开始,原通用记录类型最大到255
+Def_GameRecTypeList = (
+                       Def_GameRecType_Xiangong, # 仙宫记录 300
+                       ) = range(300, 1 + 300)
+#通用信息记录新 - 字典key配置,如果有配置,则可额外按对应记录Value值存储字典,方便快速取值,可配置Value编号 1~8,配空默认 Value1
+Def_GameRecValueKeyDict = {
+                           Def_GameRecType_Xiangong:[1],
+                           }
 
 #通用信息记录类型
 Def_UniversalGameRecTypeList = (
@@ -1611,6 +1623,7 @@
 CrossServerMsg_FamilyFlagwarOver = "FamilyFlagwarOver"  # 逐鹿万界结算信息
 CrossServerMsg_CrossBossTrialFamilyAward = "CrossBossTrialFamilyAward"  # 跨服boss历练仙盟奖励结算
 CrossServerMsg_Worship = "Worship"  # 膜拜信息
+CrossServerMsg_Xiangong = "Xiangong"  # 仙宫信息
 CrossServerMsg_FuncTeamInfo = "FuncTeamInfo"  # 功能队伍信息同步
 CrossServerMsg_FuncTeamDel = "FuncTeamDel"  # 功能队伍删除同步
 CrossServerMsg_FuncTeamList = "FuncTeamList"  # 功能队伍列表同步
@@ -1659,6 +1672,7 @@
 ClientServerMsg_QueryFuncTeam = "QueryFuncTeam"   # 查询功能队伍
 ClientServerMsg_GubaoScore = "GubaoScore" # 古宝养成积分
 ClientServerMsg_HorsePetTrainScore = "HorsePetTrainScore" # 骑宠养成积分
+ClientServerMsg_QueryXiangong = "QueryXiangong" # 查看仙宫仙名录
 
 #跨服广播类型定义
 CrossNotify_CrossAct = "CrossAct"
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index b7d8b2c..3f82e77 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -524,6 +524,7 @@
 Def_Effect_ItemCount = 267     #自动转化为对应物品ID的个数,不存背包
 Def_Effect_GubaoPiece = 270     #古宝碎片效果ID, A值-古宝ID
 Def_Effect_TrainRealmLV = 272     #境界培养卡,值A-功能(1-坐骑;2-灵宠;3-灵器), 值B-境界
+Def_Effect_TiandaoQiyun = 273   #增加天道树气运;A值-增加值   效果值B: 领取是否默认直接使用
 #----以下未使用或代码依然存在的---
 Def_Effect_ItemGiveGongXun = 1920        #使用道具给予功勋
 Def_Effect_ItemGiveRuneJH = 1925       #使用道具给予符印精华
@@ -4487,6 +4488,12 @@
 Def_PDict_MineTreasureState = "MineTreasureState" # 聚宝盆激活状态,按类型位运算记录是否已激活
 Def_PDict_MineTreasureAward = "MineTreasureAward" # 聚宝盆奖励状态,按类型位运算记录是否已领取
 Def_PDict_MineTreasureProgess = "MineTreasureProgess_%s" # 聚宝盆进度值,参数(聚宝盆类型)
+
+#仙宫
+Def_PDict_XiangongLikeState = "XiangongLikeState_%s" # 指定仙宫今日是否已点赞,参数(仙宫ID),仙宫ID为0时代表每日的仙宫功能点赞
+Def_PDict_TiandaoQiyun = "TiandaoQiyun" # 天道树当前气运
+Def_PDict_TiandaoAward = "TiandaoAward_%s" # 天道树领奖记录,按奖励索引记录是否已领取,参数(key编号)
+
 #-------------------------------------------------------------------------------
 #可以从07 41封包购买的背包类型,和对应字典{背包类型:[字典key, 默认格子数]}
 
@@ -5979,7 +5986,8 @@
 Def_RewardType_ActBuyCountGift, # 领取购买次数礼包活动 72
 Def_RewardType_Guaji, # 领取挂机收益 73
 Def_RewardType_FamilyCTGAssist, # 仙盟充值互助奖励 74
-)= range(75)
+Def_RewardType_TiandaoTree, # 仙宫天道树奖励 75
+)= range(76)
 
 #boss复活相关活动定义
 BossRebornActIDList = (
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 416480f..4265437 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -1252,6 +1252,58 @@
 
 
 #------------------------------------------------------
+# A9 07 点赞仙宫 #tagCGLikeXiangong
+
+class  tagCGLikeXiangong(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("XiangongID", c_ushort),    # 仙宫ID,为0时代表每日的仙宫点赞
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA9
+        self.SubCmd = 0x07
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA9
+        self.SubCmd = 0x07
+        self.XiangongID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCGLikeXiangong)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A9 07 点赞仙宫 //tagCGLikeXiangong:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                XiangongID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.XiangongID
+                                )
+        return DumpString
+
+
+m_NAtagCGLikeXiangong=tagCGLikeXiangong()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGLikeXiangong.Cmd,m_NAtagCGLikeXiangong.SubCmd))] = m_NAtagCGLikeXiangong
+
+
+#------------------------------------------------------
 # A9 A5 查看竞技场对战玩家最新信息 #tagCGQueryArenaBattlePlayer
 
 class  tagCGQueryArenaBattlePlayer(Structure):
@@ -1572,6 +1624,58 @@
 
 
 #------------------------------------------------------
+# A9 06 查看仙宫仙名录 #tagCGQueryXiangongRecPlayers
+
+class  tagCGQueryXiangongRecPlayers(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("XiangongID", c_ushort),    # 仙宫ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA9
+        self.SubCmd = 0x06
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.Cmd = 0xA9
+        self.SubCmd = 0x06
+        self.XiangongID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCGQueryXiangongRecPlayers)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A9 06 查看仙宫仙名录 //tagCGQueryXiangongRecPlayers:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                XiangongID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.XiangongID
+                                )
+        return DumpString
+
+
+m_NAtagCGQueryXiangongRecPlayers=tagCGQueryXiangongRecPlayers()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGQueryXiangongRecPlayers.Cmd,m_NAtagCGQueryXiangongRecPlayers.SubCmd))] = m_NAtagCGQueryXiangongRecPlayers
+
+
+#------------------------------------------------------
 #A9 A6 设置邮件(补偿)已读状态 #tagCGReadCompensation
 
 class  tagCGReadCompensation(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 09acf79..716b89d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -5736,6 +5736,356 @@
 
 
 #------------------------------------------------------
+# A9 27 仙宫新晋玩家信息 #tagGCXiangongNewPlayerInfo
+
+class  tagGCXiangongNewPlayer(Structure):
+    AddTime = 0    #(DWORD AddTime)// 新晋时间戳
+    ServerID = 0    #(DWORD ServerID)
+    PlayerID = 0    #(DWORD PlayerID)
+    NameLen = 0    #(BYTE NameLen)
+    Name = ""    #(String Name)// 玩家名,size = NameLen
+    LV = 0    #(WORD LV)// 玩家等级
+    Job = 0    #(BYTE Job)// 玩家职业
+    RealmLV = 0    #(WORD RealmLV)// 玩家境界
+    EquipShowSwitch = 0    #(DWORD EquipShowSwitch)
+    EquipShowIDCount = 0    #(BYTE EquipShowIDCount)
+    EquipShowID = list()    #(vector<DWORD> EquipShowID)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.AddTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.Name,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
+        self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.EquipShowSwitch,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.EquipShowIDCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.EquipShowIDCount):
+            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+            self.EquipShowID.append(value)
+        return _pos
+
+    def Clear(self):
+        self.AddTime = 0
+        self.ServerID = 0
+        self.PlayerID = 0
+        self.NameLen = 0
+        self.Name = ""
+        self.LV = 0
+        self.Job = 0
+        self.RealmLV = 0
+        self.EquipShowSwitch = 0
+        self.EquipShowIDCount = 0
+        self.EquipShowID = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 4
+        length += 4
+        length += 4
+        length += 1
+        length += len(self.Name)
+        length += 2
+        length += 1
+        length += 2
+        length += 4
+        length += 1
+        length += 4 * self.EquipShowIDCount
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteDWORD(data, self.AddTime)
+        data = CommFunc.WriteDWORD(data, self.ServerID)
+        data = CommFunc.WriteDWORD(data, self.PlayerID)
+        data = CommFunc.WriteBYTE(data, self.NameLen)
+        data = CommFunc.WriteString(data, self.NameLen, self.Name)
+        data = CommFunc.WriteWORD(data, self.LV)
+        data = CommFunc.WriteBYTE(data, self.Job)
+        data = CommFunc.WriteWORD(data, self.RealmLV)
+        data = CommFunc.WriteDWORD(data, self.EquipShowSwitch)
+        data = CommFunc.WriteBYTE(data, self.EquipShowIDCount)
+        for i in range(self.EquipShowIDCount):
+            data = CommFunc.WriteDWORD(data, self.EquipShowID[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                AddTime:%d,
+                                ServerID:%d,
+                                PlayerID:%d,
+                                NameLen:%d,
+                                Name:%s,
+                                LV:%d,
+                                Job:%d,
+                                RealmLV:%d,
+                                EquipShowSwitch:%d,
+                                EquipShowIDCount:%d,
+                                EquipShowID:%s
+                                '''\
+                                %(
+                                self.AddTime,
+                                self.ServerID,
+                                self.PlayerID,
+                                self.NameLen,
+                                self.Name,
+                                self.LV,
+                                self.Job,
+                                self.RealmLV,
+                                self.EquipShowSwitch,
+                                self.EquipShowIDCount,
+                                "..."
+                                )
+        return DumpString
+
+
+class  tagGCXiangongNewPlayerInfo(Structure):
+    Head = tagHead()
+    XiangongID = 0    #(WORD XiangongID)// 仙宫ID
+    NewPlayerCount = 0    #(BYTE NewPlayerCount)
+    NewPlayerList = list()    #(vector<tagGCXiangongNewPlayer> NewPlayerList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA9
+        self.Head.SubCmd = 0x27
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.XiangongID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.NewPlayerCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.NewPlayerCount):
+            temNewPlayerList = tagGCXiangongNewPlayer()
+            _pos = temNewPlayerList.ReadData(_lpData, _pos)
+            self.NewPlayerList.append(temNewPlayerList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA9
+        self.Head.SubCmd = 0x27
+        self.XiangongID = 0
+        self.NewPlayerCount = 0
+        self.NewPlayerList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 2
+        length += 1
+        for i in range(self.NewPlayerCount):
+            length += self.NewPlayerList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteWORD(data, self.XiangongID)
+        data = CommFunc.WriteBYTE(data, self.NewPlayerCount)
+        for i in range(self.NewPlayerCount):
+            data = CommFunc.WriteString(data, self.NewPlayerList[i].GetLength(), self.NewPlayerList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                XiangongID:%d,
+                                NewPlayerCount:%d,
+                                NewPlayerList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.XiangongID,
+                                self.NewPlayerCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagGCXiangongNewPlayerInfo=tagGCXiangongNewPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCXiangongNewPlayerInfo.Head.Cmd,m_NAtagGCXiangongNewPlayerInfo.Head.SubCmd))] = m_NAtagGCXiangongNewPlayerInfo
+
+
+#------------------------------------------------------
+# A9 28 仙宫仙名录玩家信息 #tagGCXiangongRecPlayerInfo
+
+class  tagGCXiangongRecPlayer(Structure):
+    AddTime = 0    #(DWORD AddTime)// 新晋时间戳
+    ServerID = 0    #(DWORD ServerID)
+    PlayerID = 0    #(DWORD PlayerID)
+    NameLen = 0    #(BYTE NameLen)
+    Name = ""    #(String Name)// 玩家名,size = NameLen
+    LV = 0    #(WORD LV)// 玩家等级
+    Job = 0    #(BYTE Job)// 玩家职业
+    RealmLV = 0    #(WORD RealmLV)// 玩家境界
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        self.AddTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.NameLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.Name,_pos = CommFunc.ReadString(_lpData, _pos,self.NameLen)
+        self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.Job,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        return _pos
+
+    def Clear(self):
+        self.AddTime = 0
+        self.ServerID = 0
+        self.PlayerID = 0
+        self.NameLen = 0
+        self.Name = ""
+        self.LV = 0
+        self.Job = 0
+        self.RealmLV = 0
+        return
+
+    def GetLength(self):
+        length = 0
+        length += 4
+        length += 4
+        length += 4
+        length += 1
+        length += len(self.Name)
+        length += 2
+        length += 1
+        length += 2
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteDWORD(data, self.AddTime)
+        data = CommFunc.WriteDWORD(data, self.ServerID)
+        data = CommFunc.WriteDWORD(data, self.PlayerID)
+        data = CommFunc.WriteBYTE(data, self.NameLen)
+        data = CommFunc.WriteString(data, self.NameLen, self.Name)
+        data = CommFunc.WriteWORD(data, self.LV)
+        data = CommFunc.WriteBYTE(data, self.Job)
+        data = CommFunc.WriteWORD(data, self.RealmLV)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                AddTime:%d,
+                                ServerID:%d,
+                                PlayerID:%d,
+                                NameLen:%d,
+                                Name:%s,
+                                LV:%d,
+                                Job:%d,
+                                RealmLV:%d
+                                '''\
+                                %(
+                                self.AddTime,
+                                self.ServerID,
+                                self.PlayerID,
+                                self.NameLen,
+                                self.Name,
+                                self.LV,
+                                self.Job,
+                                self.RealmLV
+                                )
+        return DumpString
+
+
+class  tagGCXiangongRecPlayerInfo(Structure):
+    Head = tagHead()
+    XiangongID = 0    #(WORD XiangongID)// 仙宫ID
+    RecPlayerCount = 0    #(BYTE RecPlayerCount)
+    RecPlayerList = list()    #(vector<tagGCXiangongRecPlayer> RecPlayerList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA9
+        self.Head.SubCmd = 0x28
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.XiangongID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        self.RecPlayerCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.RecPlayerCount):
+            temRecPlayerList = tagGCXiangongRecPlayer()
+            _pos = temRecPlayerList.ReadData(_lpData, _pos)
+            self.RecPlayerList.append(temRecPlayerList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA9
+        self.Head.SubCmd = 0x28
+        self.XiangongID = 0
+        self.RecPlayerCount = 0
+        self.RecPlayerList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 2
+        length += 1
+        for i in range(self.RecPlayerCount):
+            length += self.RecPlayerList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteWORD(data, self.XiangongID)
+        data = CommFunc.WriteBYTE(data, self.RecPlayerCount)
+        for i in range(self.RecPlayerCount):
+            data = CommFunc.WriteString(data, self.RecPlayerList[i].GetLength(), self.RecPlayerList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                XiangongID:%d,
+                                RecPlayerCount:%d,
+                                RecPlayerList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.XiangongID,
+                                self.RecPlayerCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagGCXiangongRecPlayerInfo=tagGCXiangongRecPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCXiangongRecPlayerInfo.Head.Cmd,m_NAtagGCXiangongRecPlayerInfo.Head.SubCmd))] = m_NAtagGCXiangongRecPlayerInfo
+
+
+#------------------------------------------------------
 # AC 10 仙盟抢Boss所有Boss伤血进度信息 #tagGCAllFamilyBossHurtInfoList
 
 class  tagGCFamilyBossHurtInfo(Structure):
@@ -50177,6 +50527,80 @@
 
 
 #------------------------------------------------------
+# B1 15 天道树信息 #tagMCTiandaoTreeInfo
+
+class  tagMCTiandaoTreeInfo(Structure):
+    Head = tagHead()
+    Qiyun = 0    #(DWORD Qiyun)// 当前气运值
+    AwardCount = 0    #(BYTE AwardCount)// 天道果领取记录值个数
+    AwardStateList = list()    #(vector<DWORD> AwardStateList)// 天道果领取记录值列表,按奖励索引位二进制记录是否已领取,一个值可存31位,如值1存0~30,值2存31~61,...
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x15
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Qiyun,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.AwardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.AwardCount):
+            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+            self.AwardStateList.append(value)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x15
+        self.Qiyun = 0
+        self.AwardCount = 0
+        self.AwardStateList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 4
+        length += 1
+        length += 4 * self.AwardCount
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteDWORD(data, self.Qiyun)
+        data = CommFunc.WriteBYTE(data, self.AwardCount)
+        for i in range(self.AwardCount):
+            data = CommFunc.WriteDWORD(data, self.AwardStateList[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Qiyun:%d,
+                                AwardCount:%d,
+                                AwardStateList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Qiyun,
+                                self.AwardCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCTiandaoTreeInfo=tagMCTiandaoTreeInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCTiandaoTreeInfo.Head.Cmd,m_NAtagMCTiandaoTreeInfo.Head.SubCmd))] = m_NAtagMCTiandaoTreeInfo
+
+
+#------------------------------------------------------
 # B1 12 培养功能境界信息 #tagMCTrainRealmLVInfo
 
 class  tagMCTrainRealmLV(Structure):
@@ -50285,6 +50709,121 @@
 
 
 #------------------------------------------------------
+# B1 14 仙宫信息 #tagMCXiangongInfo
+
+class  tagMCXiangong(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("XiangongID", c_ushort),    # 仙宫ID
+                  ("LikeStateToday", c_ubyte),    # 今日是否已点赞
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        return
+
+    def ReadData(self, stringData, _pos=0, _len=0):
+        self.Clear()
+        memmove(addressof(self), stringData[_pos:], self.GetLength())
+        return _pos + self.GetLength()
+
+    def Clear(self):
+        self.XiangongID = 0
+        self.LikeStateToday = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCXiangong)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B1 14 仙宫信息 //tagMCXiangongInfo:
+                                XiangongID:%d,
+                                LikeStateToday:%d
+                                '''\
+                                %(
+                                self.XiangongID,
+                                self.LikeStateToday
+                                )
+        return DumpString
+
+
+class  tagMCXiangongInfo(Structure):
+    Head = tagHead()
+    LikeStateToday = 0    #(BYTE LikeStateToday)// 今日是否已点赞,指仙宫的外层点赞,非某个指定仙宫
+    XiangongCount = 0    #(BYTE XiangongCount)
+    XiangongList = list()    #(vector<tagMCXiangong> XiangongList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x14
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.LikeStateToday,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.XiangongCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.XiangongCount):
+            temXiangongList = tagMCXiangong()
+            _pos = temXiangongList.ReadData(_lpData, _pos)
+            self.XiangongList.append(temXiangongList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xB1
+        self.Head.SubCmd = 0x14
+        self.LikeStateToday = 0
+        self.XiangongCount = 0
+        self.XiangongList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 1
+        for i in range(self.XiangongCount):
+            length += self.XiangongList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.LikeStateToday)
+        data = CommFunc.WriteBYTE(data, self.XiangongCount)
+        for i in range(self.XiangongCount):
+            data = CommFunc.WriteString(data, self.XiangongList[i].GetLength(), self.XiangongList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                LikeStateToday:%d,
+                                XiangongCount:%d,
+                                XiangongList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.LikeStateToday,
+                                self.XiangongCount,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCXiangongInfo=tagMCXiangongInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCXiangongInfo.Head.Cmd,m_NAtagMCXiangongInfo.Head.SubCmd))] = m_NAtagMCXiangongInfo
+
+
+#------------------------------------------------------
 # B1 20 战令信息 #tagMCZhanlingInfo
 
 class  tagMCZhanling(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Xiangong.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Xiangong.py
new file mode 100644
index 0000000..12ecdaf
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Xiangong.py
@@ -0,0 +1,71 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.Xiangong
+#
+# @todo:仙宫
+# @author hxp
+# @date 2024-09-04
+# @version 1.0
+#
+# 详细描述: 仙宫
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-04 16:30"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PlayerControl
+import IpyGameDataPY
+import PlayerXiangong
+import ChConfig
+
+#-------------------------------------------------------------------------------
+#逻辑实现
+## GM命令执行入口
+#  @param curPlayer 当前玩家
+#  @param list 参数列表 [npcID]
+#  @return None
+#  @remarks 函数详细说明.
+def OnExec(curPlayer, msgList):
+    
+    if not msgList:
+        GameWorld.DebugAnswer(curPlayer, "---------- %s" % GameWorld.GetCurrentDataTimeStr())
+        GameWorld.DebugAnswer(curPlayer, "重置仙宫点赞: Xiangong 0 like")
+        GameWorld.DebugAnswer(curPlayer, "重置气运奖励: Xiangong 0 tree")
+        GameWorld.DebugAnswer(curPlayer, "设置当前气运: Xiangong q 气运值")
+        return True
+    
+    if msgList[0] == 0:
+        if len(msgList) == 1 or msgList[1] == "like":
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_XiangongLikeState % 0, 0)
+            xiangongIDList = []
+            ipyMgr = IpyGameDataPY.IPY_Data()
+            for index in range(ipyMgr.GetXiangongCount()):
+                ipyData = ipyMgr.GetXiangongByIndex(index)
+                xiangongID = ipyData.GetXiangongID()
+                if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_XiangongLikeState % xiangongID):
+                    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_XiangongLikeState % xiangongID, 0)
+                    xiangongIDList.append(xiangongID)
+            PlayerXiangong.SyncXiangongInfo(curPlayer, xiangongIDList)
+            GameWorld.DebugAnswer(curPlayer, "重置仙宫点赞:%s" % xiangongIDList)
+            
+        if len(msgList) == 1 or msgList[1] == "tree":
+            for keyNum in range(50):
+                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TiandaoAward % keyNum, 0)
+            PlayerXiangong.SyncTiandaoTreeInfo(curPlayer)
+            GameWorld.DebugAnswer(curPlayer, "重置气运奖励:%s" % xiangongIDList)
+            
+        return
+    
+    if msgList[0] == "q":
+        setQiyun = msgList[1] if len(msgList) > 1 else 0
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TiandaoQiyun, setQiyun)
+        PlayerXiangong.SyncTiandaoTreeInfo(curPlayer)
+        GameWorld.DebugAnswer(curPlayer, "设置当前气运:%s" % setQiyun)
+        return
+    
+    return True
+
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 7339c16..ca7d617 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -2435,6 +2435,16 @@
                         ("list", "ZLRewardItemList", 0),
                         ("list", "ZLRewardItemListH", 0),
                         ),
+
+                "Xiangong":(
+                        ("WORD", "XiangongID", 1),
+                        ),
+
+                "TiandaoTree":(
+                        ("WORD", "AwardIndex", 1),
+                        ("DWORD", "NeedQiyun", 0),
+                        ("list", "AwardItemList", 0),
+                        ),
                 }
 
 
@@ -6080,6 +6090,26 @@
     def GetFreeRewardItemList(self): return self.attrTuple[3] # 免费奖励物品列表 [[物品ID,个数,是否拍品],...] list
     def GetZLRewardItemList(self): return self.attrTuple[4] # 战令奖励物品列表 [[物品ID,个数,是否拍品],...] list
     def GetZLRewardItemListH(self): return self.attrTuple[5] # 高级战令奖励物品列表 [[物品ID,个数,是否拍品],...] list
+
+# 仙宫表
+class IPY_Xiangong():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetXiangongID(self): return self.attrTuple[0] # 仙宫ID WORD
+
+# 仙宫天道树
+class IPY_TiandaoTree():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetAwardIndex(self): return self.attrTuple[0] # 奖励索引 WORD
+    def GetNeedQiyun(self): return self.attrTuple[1] # 所需气运值 DWORD
+    def GetAwardItemList(self): return self.attrTuple[2] # 奖励物品列表 list
 
 
 def Log(msg, playerID=0, par=0):
@@ -6384,6 +6414,8 @@
         self.__LoadFileData("HistoryRechargeAward", onlyCheck)
         self.__LoadFileData("CustomAward", onlyCheck)
         self.__LoadFileData("Zhanling", onlyCheck)
+        self.__LoadFileData("Xiangong", onlyCheck)
+        self.__LoadFileData("TiandaoTree", onlyCheck)
         Log("IPY_DataMgr ReloadOK! onlyCheck=%s" % onlyCheck)
         return
     
@@ -8324,6 +8356,20 @@
     def GetZhanlingByIndex(self, index):
         self.CheckLoadData("Zhanling")
         return self.ipyZhanlingCache[index]
+
+    def GetXiangongCount(self):
+        self.CheckLoadData("Xiangong")
+        return self.ipyXiangongLen
+    def GetXiangongByIndex(self, index):
+        self.CheckLoadData("Xiangong")
+        return self.ipyXiangongCache[index]
+
+    def GetTiandaoTreeCount(self):
+        self.CheckLoadData("TiandaoTree")
+        return self.ipyTiandaoTreeLen
+    def GetTiandaoTreeByIndex(self, index):
+        self.CheckLoadData("TiandaoTree")
+        return self.ipyTiandaoTreeCache[index]
 
 IPYData = IPY_DataMgr()
 def IPY_Data(): return IPYData
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
index a076940..a996a07 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
@@ -726,6 +726,7 @@
                             ChConfig.Def_Effect_PrizeCoin:"Item_PrizeCoin", # 奖励充值点券
                             ChConfig.Def_Effect_AddVIPExp:"Item_AddVIPExp", # 增加VIP经验
                             ChConfig.Def_Effect_VIPLVCard:"Item_VIPLVCard", # VIP等级直升卡
+                            ChConfig.Def_Effect_TiandaoQiyun:"Item_TiandaoQiyun", # 天道树气运
                             ChConfig.Def_Effect_GubaoPiece:"Item_GubaoPiece", # 古宝碎片效果ID
                             ChConfig.Def_Effect_TrainRealmLV:"Item_TrainRealmLV", # 境界培养卡
                             ChConfig.Def_Effect_ResetBossKillCnt:"Item_ResetBossKillCnt", # 重置boss击杀疲劳
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
index 5e021b1..2fe7019 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
@@ -34,6 +34,7 @@
 import PlayerFairyCeremony
 import PlayerActBossTrial
 import PlayerMagicWeapon
+import PlayerXiangong
 import IpyGameDataPY
 import DataRecordPack
 import PlayerGubao
@@ -1138,6 +1139,14 @@
                 PlayerGubao.AddGubaoPiece(curPlayer, gubaoID, tagItemCount, itemID)
                 tagItem.Clear()
                 return True
+        #气运
+        if itemEff.GetEffectID() == ChConfig.Def_Effect_TiandaoQiyun:
+            isAutoUse = itemEff.GetEffectValue(1)
+            if isAutoUse:
+                addQiyun = itemEff.GetEffectValue(0) * tagItemCount
+                PlayerXiangong.AddTiandaoQiyun(curPlayer, addQiyun, {"ItemID":itemID, "ItemCount":tagItemCount, "isAutoUse":1})
+                tagItem.Clear()
+                return True
         #直升VIP
         if itemEff.GetEffectID() == ChConfig.Def_Effect_VIPLVCard:
             isAutoUse = itemEff.GetEffectValue(1)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_TiandaoQiyun.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_TiandaoQiyun.py
new file mode 100644
index 0000000..40d6dc1
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/Item_TiandaoQiyun.py
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package UseItem.Item_TiandaoQiyun
+#
+# @todo:天道气运
+# @author hxp
+# @date 2024-09-04
+# @version 1.0
+#
+# 详细描述: 天道气运
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-04 16:30"""
+#-------------------------------------------------------------------------------
+
+import ItemCommon
+import PlayerXiangong
+
+def BatchUseItem(curPlayer, curRoleItem, tick, useCnt, exData):
+    ##批量使用物品
+    
+    curEff = curRoleItem.GetEffectByIndex(0)
+    addValue = curEff.GetEffectValue(0) * useCnt
+    
+    PlayerXiangong.AddTiandaoQiyun(curPlayer, addValue, {"ItemID":curRoleItem.GetItemTypeID(), "ItemCount":useCnt})
+    
+    succCnt = useCnt # 默认值使用1个
+    ItemCommon.DelItem(curPlayer, curRoleItem, succCnt)
+    return True, succCnt
+    
+    
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
index ffa8e74..2d8a9e7 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -161,6 +161,7 @@
 import GameObj
 import PlayerChangeJob
 import PlayerGuaji
+import PlayerXiangong
 import PlayerMineArea
 import PlayerActLoginNew
 import PlayerActBuyCountGift
@@ -988,6 +989,7 @@
         pass
     
     else:
+        PlayerXiangong.OnPlayerLogin(curPlayer)
         PlayerGubao.OnPlayerLogin(curPlayer)
         PlayerShentong.OnPlayerLogin(curPlayer)
         PlayerZhanling.OnPlayerLogin(curPlayer)
@@ -5728,6 +5730,9 @@
     # 仙盟充值互助活动奖励
     elif rewardType == ChConfig.Def_RewardType_FamilyCTGAssist:
         PlayerActFamilyCTGAssist.GetFamilyCTGAssistAward(curPlayer, dataEx, dataExStr)
+    # 天道树奖励
+    elif rewardType == ChConfig.Def_RewardType_TiandaoTree:
+        PlayerXiangong.GetTiandaoTreeAward(curPlayer, dataEx)
     #缥缈奇遇领取
     elif rewardType == ChConfig.Def_RewardType_FairyAdventuresAward:
         PlayerFairyDomain.GetFairyAdventuresAward(curPlayer, dataEx, dataExStr)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
index d315b2f..b2e5745 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -134,6 +134,7 @@
 import PyGameData
 import PlayerTJG
 import PlayerGuaji
+import PlayerXiangong
 import PlayerFuncTeam
 import PlayerMineArea
 
@@ -561,6 +562,8 @@
         PlayerActTurntable.PlayerOnDay(curPlayer)
         #情缘
         PlayerLove.DoPlayerOnDay(curPlayer)
+        #仙宫
+        PlayerXiangong.PlayerOnDay(curPlayer)
         #玩法前瞻奖励
         gameNoticeAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GameNoticeAwardState)
         if gameNoticeAwardState:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerXiangong.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerXiangong.py
new file mode 100644
index 0000000..00703f5
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerXiangong.py
@@ -0,0 +1,169 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.PlayerXiangong
+#
+# @todo:仙宫
+# @author hxp
+# @date 2024-09-04
+# @version 1.0
+#
+# 详细描述: 仙宫
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-04 16:30"""
+#-------------------------------------------------------------------------------
+
+import ChConfig
+import IpyGameDataPY
+import PlayerControl
+import ChPyNetSendPack
+import DataRecordPack
+import NetPackCommon
+import ItemControler
+import GameWorld
+
+def OnPlayerLogin(curPlayer):
+    SyncXiangongInfo(curPlayer)
+    SyncTiandaoTreeInfo(curPlayer, True)
+    return
+
+def PlayerOnDay(curPlayer):
+    
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_XiangongLikeState % 0, 0)
+    
+    xiangongIDList = []
+    ipyMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyMgr.GetXiangongCount()):
+        ipyData = ipyMgr.GetXiangongByIndex(index)
+        xiangongID = ipyData.GetXiangongID()
+        if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_XiangongLikeState % xiangongID):
+            continue
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_XiangongLikeState % xiangongID, 0)
+        xiangongIDList.append(xiangongID)
+        
+    if xiangongIDList:
+        SyncXiangongInfo(curPlayer, xiangongIDList)
+        
+    return
+
+def AddTiandaoQiyun(curPlayer, addValue, addDict={}):
+    curQiyun = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TiandaoQiyun)
+    updQiyun = min(curQiyun + addValue, ChConfig.Def_UpperLimit_DWord)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_TiandaoQiyun, updQiyun)
+    dataDict = {'PlayerID':curPlayer.GetPlayerID(), "PlayerName":curPlayer.GetPlayerName(), 
+                'AccID':curPlayer.GetAccID(), "updQiyun":updQiyun, "addValue":addValue}
+    dataDict.update(addDict)
+    DataRecordPack.SendEventPack("AddTiandaoQiyun", dataDict, curPlayer)
+    SyncTiandaoTreeInfo(curPlayer)
+    return updQiyun
+
+def GameServer_Xiangong_DoResult(curPlayer, msgData):
+    
+    msgType = msgData[0]
+    dataMsg = msgData[1]
+    
+    ## 点赞仙宫
+    if msgType == "LikeXiangong":
+        __DoLikeXiangong(curPlayer, dataMsg)
+        
+    return
+
+def __DoLikeXiangong(curPlayer, dataMsg):
+    
+    xiangongID, moneyType, moneyValue = dataMsg
+    
+    playerID = curPlayer.GetPlayerID()
+    likeState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_XiangongLikeState % xiangongID)
+    if likeState:
+        GameWorld.DebugLog("该仙宫已点赞! xiangongID=%s" % xiangongID, playerID)
+        return
+    GameWorld.DebugLog("仙宫点赞! xiangongID=%s,moneyType=%s,moneyValue=%s" % (xiangongID, moneyType, moneyValue), playerID)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_XiangongLikeState % xiangongID, 1)
+    SyncXiangongInfo(curPlayer, [xiangongID])
+    PlayerControl.GiveMoney(curPlayer, moneyType, moneyValue, "LikeXiangong", {"xiangongID":xiangongID})
+    return
+
+def GetTiandaoTreeAward(curPlayer, awardIndex):
+    ## 领取天道树奖励
+    
+    playerID = curPlayer.GetPlayerID()
+    ipyData = IpyGameDataPY.GetIpyGameData("TiandaoTree", awardIndex)
+    if not ipyData:
+        return
+    if GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_TiandaoAward, awardIndex):
+        GameWorld.DebugLog("该天道树奖励已领奖! awardIndex=%s" % awardIndex, playerID)
+        return
+    
+    needQiyun = ipyData.GetNeedQiyun()
+    awardItemList = ipyData.GetAwardItemList()
+    
+    qiyun = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TiandaoQiyun)
+    if qiyun < needQiyun:
+        GameWorld.DebugLog("当前天道树气运不足,无法领奖! awardIndex=%s,qiyun=%s < %s" % (awardIndex, qiyun, needQiyun), playerID)
+        return
+    
+    GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_TiandaoAward, awardIndex, 1)
+    
+    ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList)
+    
+    SyncTiandaoTreeInfo(curPlayer)
+    return
+
+def SyncXiangongInfo(curPlayer, xiangongIDList=None):
+    syncXiangongIDList = []
+    if xiangongIDList == None:
+        ipyMgr = IpyGameDataPY.IPY_Data()
+        for index in range(ipyMgr.GetXiangongCount()):
+            ipyData = ipyMgr.GetXiangongByIndex(index)
+            syncXiangongIDList.append(ipyData.GetXiangongID())
+    else:
+        syncXiangongIDList = xiangongIDList
+        
+    xiangongList = []
+    for xiangongID in syncXiangongIDList:
+        if not xiangongID:
+            continue
+        likeState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_XiangongLikeState % xiangongID)
+        if not likeState and xiangongIDList == None:
+            continue
+        xg = ChPyNetSendPack.tagMCXiangong()
+        xg.XiangongID = xiangongID
+        xg.LikeStateToday = likeState
+        xiangongList.append(xg)
+        
+    likeStateToday = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_XiangongLikeState % 0)
+    if xiangongIDList == None and not xiangongList and not likeStateToday:
+        return
+    
+    clientPack = ChPyNetSendPack.tagMCXiangongInfo()
+    clientPack.LikeStateToday = likeStateToday
+    clientPack.XiangongList = xiangongList
+    clientPack.XiangongCount = len(clientPack.XiangongList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def SyncTiandaoTreeInfo(curPlayer, isLogin=False):
+    ipyMgr = IpyGameDataPY.IPY_Data()
+    treeCount = ipyMgr.GetTiandaoTreeCount()
+    if not treeCount:
+        return
+    lastIpyData = ipyMgr.GetTiandaoTreeByIndex(treeCount - 1)
+    if not lastIpyData:
+        return
+    keyNumMax = lastIpyData.GetAwardIndex() / 31 + 1
+    awardStateList = []
+    for keyNum in range(keyNumMax):
+        awardStateList.append(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TiandaoAward % keyNum))
+        
+    qiyun = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TiandaoQiyun)
+    if isLogin and not qiyun and awardStateList.count(0) == len(awardStateList):
+        return
+    
+    clientPack = ChPyNetSendPack.tagMCTiandaoTreeInfo()
+    clientPack.Qiyun = qiyun
+    clientPack.AwardStateList = awardStateList
+    clientPack.AwardCount = len(clientPack.AwardStateList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_Xiangong.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_Xiangong.py
new file mode 100644
index 0000000..e4a2832
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_Xiangong.py
@@ -0,0 +1,48 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.RemoteQuery.GY_Query_Xiangong
+#
+# @todo:仙宫
+# @author hxp
+# @date 2024-09-04
+# @version 1.0
+#
+# 详细描述: 仙宫
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-09-04 16:30"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PlayerXiangong
+
+#------------------------------------------------------------------------------ 
+## 跨服赛报名调用接口
+#  @param query_Type 请求类型
+#  @param query_ID 请求的玩家ID
+#  @param packCMDList 发包命令
+#  @param tick 当前时间
+#  @return "True" or "False" or ""
+#  @remarks 函数详细说明.
+def DoLogic(query_Type, query_ID, packCMDList, tick): 
+    return
+
+
+#------------------------------------------------------------------------------ 
+## 执行结果
+#  @param curPlayer 发出请求的玩家
+#  @param callFunName 功能名称
+#  @param funResult 查询的结果
+#  @param tick 当前时间
+#  @return None
+#  @remarks 函数详细说明.
+def DoResult(curPlayer, callFunName, funResult, tick):
+    GameWorld.DebugLog("GY_Query_Xiangong DoResult %s" % str(funResult), curPlayer.GetPlayerID())
+    if funResult != "":
+        PlayerXiangong.GameServer_Xiangong_DoResult(curPlayer, eval(funResult))
+    return
+
+    
+    
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 2f5a5c6..a43e0ef 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -1146,7 +1146,8 @@
 CDBPlayerRefresh_BossFinalHurtPer,  # Boss最终输出伤害百分比 264
 CDBPlayerRefresh_HorsePetTrainScore, # 骑宠养成积分 265
 CDBPlayerRefresh_GubaoTrainScore, # 古宝养成积分 266
-) = range(146, 267)
+CDBPlayerRefresh_TiandaoFruit, # 天道果 267
+) = range(146, 268)
 
 TYPE_Price_Gold_Paper_Money = 5    # 金钱类型,(先用礼券,再用金子)
 TYPE_Price_Family_Contribution = 6 # 战盟贡献度(活跃度转换得来)
@@ -1181,6 +1182,7 @@
 TYPE_Price_GatherSoul = 44    # 聚魂精华
 TYPE_Price_HorsePetTrainScore = 45    # 骑宠养成积分
 TYPE_Price_GubaoTrainScore = 46    # 古宝养成积分
+TYPE_Price_TiandaoFruit = 47    # 天道果
 TYPE_Price_PayCoin = 99    # 代币
 
 #key可用于遍历所有货币,value仅GM相关会用到
@@ -1188,7 +1190,7 @@
                  1:"仙玉", 2:"绑玉", 3:"铜钱", 6:"战盟贡献度", 10:"战盟仓库积分", 13:"境界修行点", 14:"符印融合石", 15:"仙盟活跃令", 
                  16:"助战积分", 18:"荣誉", 19:"Boss积分", 23:"符印精华", 24:"符印碎片", 25:"寻宝积分", 26:"集市额度", 27:"丹精", 28:"魂尘", 
                  29:"聚魂碎片", 30:"核心环", 31:"功能特权令", 32:"环保值", 33:"GM令", 34:"古神币", 35:"功德点", 
-                 39:"成就积分", 40:"万界积分", 43:"凭证积分", 44:"聚魂精华", 45:"骑宠养成积分", 46:"古宝养成积分", 99:"代币"
+                 39:"成就积分", 40:"万界积分", 43:"凭证积分", 44:"聚魂精华", 45:"骑宠养成积分", 46:"古宝养成积分", 47:"天道果", 99:"代币"
                  }
 
 #以下是旧的金钱类型
@@ -1224,6 +1226,7 @@
                            TYPE_Price_GatherSoul:CDBPlayerRefresh_GatherSoul,
                            TYPE_Price_HorsePetTrainScore:CDBPlayerRefresh_HorsePetTrainScore,
                            TYPE_Price_GubaoTrainScore:CDBPlayerRefresh_GubaoTrainScore,
+                           TYPE_Price_TiandaoFruit:CDBPlayerRefresh_TiandaoFruit,
                            }
 
 # 支持负值的货币及对应0418刷新类型
@@ -1364,6 +1367,15 @@
                          Def_PlayerRecType_WorshipDaily, # 玩家每日膜拜记录 2
                          Def_PlayerRecType_PayCoin, # 代币记录 3
                          ) = range(1, 1 + 3)
+
+#通用信息记录类型 - 新 从 300 开始,原通用记录类型最大到255
+Def_GameRecTypeList = (
+                       Def_GameRecType_Xiangong, # 仙宫记录 300
+                       ) = range(300, 1 + 300)
+#通用信息记录新 - 字典key配置,如果有配置,则可额外按对应记录Value值存储字典,方便快速取值,可配置Value编号 1~8,配空默认 Value1
+Def_GameRecValueKeyDict = {
+                           Def_GameRecType_Xiangong:[1],
+                           }
 
 #通用信息记录类型
 Def_UniversalGameRecTypeList = (
@@ -1611,6 +1623,7 @@
 CrossServerMsg_FamilyFlagwarOver = "FamilyFlagwarOver"  # 逐鹿万界结算信息
 CrossServerMsg_CrossBossTrialFamilyAward = "CrossBossTrialFamilyAward"  # 跨服boss历练仙盟奖励结算
 CrossServerMsg_Worship = "Worship"  # 膜拜信息
+CrossServerMsg_Xiangong = "Xiangong"  # 仙宫信息
 CrossServerMsg_FuncTeamInfo = "FuncTeamInfo"  # 功能队伍信息同步
 CrossServerMsg_FuncTeamDel = "FuncTeamDel"  # 功能队伍删除同步
 CrossServerMsg_FuncTeamList = "FuncTeamList"  # 功能队伍列表同步
@@ -1659,6 +1672,7 @@
 ClientServerMsg_QueryFuncTeam = "QueryFuncTeam"   # 查询功能队伍
 ClientServerMsg_GubaoScore = "GubaoScore" # 古宝养成积分
 ClientServerMsg_HorsePetTrainScore = "HorsePetTrainScore" # 骑宠养成积分
+ClientServerMsg_QueryXiangong = "QueryXiangong" # 查看仙宫仙名录
 
 #跨服广播类型定义
 CrossNotify_CrossAct = "CrossAct"

--
Gitblit v1.8.0