From 01a0e539b786ae0f1c46646874502367f5410aca Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 04 二月 2026 18:18:51 +0800
Subject: [PATCH] 66 【公会】基础主体-服务端(优化游戏服及跨服启动、通讯逻辑;服务器类型增加跨服中心、跨服事件、时间管理;跨服玩家在线状态、基础信息、玩家资源增减管理、发送跨服个人邮件等;跨服公会初版,修复公会成员审核、成员战力刷新等bug,增加公会名次同步;跨服公会暂未测试;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/CrossMgr.py                    |  331 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py                   |  152 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py                        | 1731 +++++++++------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                            |  347 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py                     |   17 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py                                 |   10 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py                     | 1046 ++++++++-
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py                          |   26 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py                      |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ReadChConfig.py                               |   98 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChServerToServerPyPack.py                     |  179 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/GMShell.py                                 |   49 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                              |   37 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                            |  193 +
 PySysDB/PySysDBPY.h                                                                                               |   19 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLuckyCloudBuy.py                 |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyZhenbaoge.py               |   91 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/UpdatePlayerName.py                    |    9 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventShell.py                           |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayer.py                         |  438 ++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py                       |   55 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                |   58 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py                     |   83 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Family.py                         |   34 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py                    |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerMail.py                          |   23 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py          |   15 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NetPackCommon.py                              |   66 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyEmblem.py                  |   56 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py |   52 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/RecvPackToMapDB.py                  |    8 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py                  |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPrestigeSys.py                   |    7 
 /dev/null                                                                                                         |  156 -
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py                        |    5 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/CrossMsg.py                    |  201 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py                                |    8 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py              |  114 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py                    |    6 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py                              |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py                                  |  188 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py                          |   11 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyTaofa.py                   |   10 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py                  |  189 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py                                |   35 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyCrossServerPack.ini                                |   30 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                                   |    2 
 47 files changed, 4,582 insertions(+), 1,621 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 08c7837..ff3fd56 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -2693,7 +2693,16 @@
 	dict		Attr;	//属性
 };
 
-//仙盟等级表
+//跨服公会表
+struct	FamilyCross
+{
+	char		_AppID;	//AppID
+	WORD		_ZoneID;	//分区ID
+	DWORD		CrossServerID;	//跨服服务器ID
+	list		ServerIDList;	//互通服务器ID列表
+};
+
+//公会等级表
 struct	Family
 {
 	BYTE		_FamilyLV;	//仙盟等级
@@ -2704,7 +2713,7 @@
 	DWORD		ZhenbaogeWeights;	//珍宝阁总权重
 };
 
-//仙盟徽章表
+//公会徽章表
 struct FamilyEmblem
 {
 	BYTE		_EmblemID;	//徽章ID
@@ -2713,7 +2722,7 @@
 	DWORD		CustomFamilyID;	//定制仙盟ID
 };
 
-//仙盟捐献表
+//公会捐献表
 struct FamilyDonate
 {
 	BYTE		_DonateType;	//捐献类型
@@ -2723,7 +2732,7 @@
 	list		AwardItemList;	//获得奖励列表[[物品ID,个数], ...]
 };
 
-//仙盟珍宝阁砍价表
+//公会珍宝阁砍价表
 struct FamilyZhenbaogeCut
 {
 	BYTE		_CutNum;	//砍价人次
@@ -2732,7 +2741,7 @@
 	float		RandRatio;	//随机比值
 };
 
-//仙盟珍宝阁物品表
+//公会珍宝阁物品表
 struct FamilyZhenbaogeItem
 {
 	BYTE		_ItemGroupNum;	//物品组编号
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyCrossServerPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyCrossServerPack.ini
index 5aa4c46..6e8a17e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyCrossServerPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyCrossServerPack.ini
@@ -2,18 +2,32 @@
 ;服务器间的跨服包,既是发包也是收包
 
 ;跨服PY包注册
-[CrossServerPackLogic]
-ScriptName = CrossServerPackLogic.py
-Writer = alee
-Releaser = alee
+[CrossMgr]
+ScriptName = CrossMgr.py
+Writer = hxp
+Releaser = hxp
 RegType = 0
-RegisterPackCount = 2
-
+RegisterPackCount = 3
 
 PacketCMD_1=0xC2
 PacketSubCMD_1=0x01
-PacketCallFunc_1=OnTest
+PacketCallFunc_1=OnServerHeart
 
 PacketCMD_2=0xC2
 PacketSubCMD_2=0x02
-PacketCallFunc_2=OnSSCommMsg
+PacketCallFunc_2=OnServerConnOK
+
+PacketCMD_3=0xC2
+PacketSubCMD_3=0x03
+PacketCallFunc_3=OnCrossCenterEvent
+
+[CrossMsg]
+ScriptName = CrossMsg.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 1
+
+PacketCMD_1=0xC2
+PacketSubCMD_1=0x10
+PacketCallFunc_1=OnSSCommMsg
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
index 4d17c83..74a1e71 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -29,7 +29,6 @@
 import GameWorld
 import PlayerLLMJ
 import PlayerPrestigeSys
-import CrossServerPackLogic
 import DataRecordPack
 import PlayerSuccess
 import IpyGameDataPY
@@ -45,6 +44,7 @@
 import TurnBuff
 import FBCommon
 import CommFunc
+import CrossMsg
 import FBLogic
 
 import random
@@ -1279,17 +1279,17 @@
             isMultiMap = True
             
     if isMultiMap:
-        CrossServerPackLogic.SendBattleRequest(reqInfo, guid, mapID, funcLineID, reqPlayerID)
+        CrossMsg.SendBattleRequest(reqInfo, guid, mapID, funcLineID, reqPlayerID)
     else:
-        SSMsg_BattleRequest(reqInfo, fromServerID)
+        S2B_BattleRequest(reqInfo, fromServerID)
     return
 
-def SSMsg_BattleRequest(reqInfo, fromServerID, msgType=""):
+def S2B_BattleRequest(reqInfo, fromServerID, msgType=""):
     ## 请求执行战斗,由本地图或其他服务器地图分配过来的战斗请求
     guid, mapID, funcLineID, lineupDictA, lineupDictB, reqPlayerID, playerServerID, npcLineupIDList, strongerLV, difficulty, reqData = reqInfo
-    if msgType:
-        GameWorld.Log("OnServerReceiveMsg => %s, fromServerID=%s,funcMapID=%s,funcLineID=%s,%s,%s" 
-                      % (msgType, fromServerID, mapID, funcLineID, guid, time.time()), reqPlayerID)
+    #if msgType:
+    #    GameWorld.Log("OnServerReceiveMsg => %s, fromServerID=%s,funcMapID=%s,funcLineID=%s,%s,%s" 
+    #                  % (msgType, fromServerID, mapID, funcLineID, guid, time.time()), reqPlayerID)
         
     if npcLineupIDList:
         turnFight = DoTurnFightPVE(guid, mapID, funcLineID, reqPlayerID, playerServerID, lineupDictA, npcLineupIDList, strongerLV, difficulty)
@@ -1308,20 +1308,20 @@
     
     # 本地图自己处理的
     if fromServerID == GameWorld.GetGameWorld().GetServerID():
-        SSMsg_BattleResult(retInfo, fromServerID)
+        B2S_BattleResult(retInfo, fromServerID)
         
     # 其他服务器地图请求的,发送战斗结果回去
     else:
-        CrossServerPackLogic.SendBattleResult(retInfo, fromServerID, guid, mapID, funcLineID, reqPlayerID)
+        CrossMsg.SendBattleResult(retInfo, fromServerID, guid, mapID, funcLineID, reqPlayerID)
     return
 
-def SSMsg_BattleResult(retInfo, fromServerID, msgType=""):
+def B2S_BattleResult(retInfo, fromServerID, msgType=""):
     ## 收到战斗结果信息
     
     guid, mapID, funcLineID, reqPlayerID, winFaction, statMsg, dateStr, reqData = retInfo
-    if msgType:
-        GameWorld.Log("OnServerReceiveMsg => %s, fromServerID=%s,funcMapID=%s,funcLineID=%s,%s,%s" 
-                      % (msgType, fromServerID, mapID, funcLineID, guid, time.time()), reqPlayerID)
+    #if msgType:
+    #    GameWorld.Log("OnServerReceiveMsg => %s, fromServerID=%s,funcMapID=%s,funcLineID=%s,%s,%s" 
+    #                  % (msgType, fromServerID, mapID, funcLineID, guid, time.time()), reqPlayerID)
         
     curPlayer = None
     if reqPlayerID:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index b2a6ba0..7100543 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -2451,6 +2451,7 @@
 TYPE_Time_Format = "%Y-%m-%d %H:%M:%S"
 TYPE_Time_Format_Day = "%Y-%m-%d"
 TYPE_Time_Format_YmdHMS = "%Y%m%d%H%M%S"
+TYPE_Time_Format_YmdH = "%Y%m%d%H"
 #---------------------------------------------------------------------
 
 #请求类型(需要和GameServer中的一致)
@@ -3175,6 +3176,7 @@
 Def_PDict_OnDayEx = "OnDayEx" # 特殊时间点凌晨X点过天
 Def_PDict_OnWeekEx = "OnWeekEx" # 特殊时间点凌晨X点过周
 Def_PDict_OnMonthEx = "OnMonthEx" # 特殊时间点凌晨X点过月
+Def_PDict_OnCrossEvent = "OnCrossEvent" # 跨服过x事件值, yyyyMMddhh
 Def_Player_Dict_PlayerFromPID = "PlayerFromPID"    # pid
 Def_Player_Dict_Account_Type = "account_type"    # account_type
 Def_Player_Dict_FirstLogin = "FirstLogin"    # 首登标记 0-未首登; 1-首登过
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 5986a54..c146402 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -10725,6 +10725,158 @@
 
 
 #------------------------------------------------------
+# A5 05 公会跨服互通信息 #tagSCFamilyCrossInfo
+
+class  tagSCFamilyCrossInfo(Structure):
+    Head = tagHead()
+    ZoneID = 0    #(BYTE ZoneID)// 所属分区
+    ServerCnt = 0    #(WORD ServerCnt)
+    ServerIDList = list()    #(vector<DWORD> ServerIDList)// 互通服务器ID列表
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA5
+        self.Head.SubCmd = 0x05
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.ZoneID,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.ServerCnt,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        for i in range(self.ServerCnt):
+            value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+            self.ServerIDList.append(value)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA5
+        self.Head.SubCmd = 0x05
+        self.ZoneID = 0
+        self.ServerCnt = 0
+        self.ServerIDList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 2
+        length += 4 * self.ServerCnt
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.ZoneID)
+        data = CommFunc.WriteWORD(data, self.ServerCnt)
+        for i in range(self.ServerCnt):
+            data = CommFunc.WriteDWORD(data, self.ServerIDList[i])
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                ZoneID:%d,
+                                ServerCnt:%d,
+                                ServerIDList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.ZoneID,
+                                self.ServerCnt,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagSCFamilyCrossInfo=tagSCFamilyCrossInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCFamilyCrossInfo.Head.Cmd,m_NAtagSCFamilyCrossInfo.Head.SubCmd))] = m_NAtagSCFamilyCrossInfo
+
+
+#------------------------------------------------------
+# A5 24 公会成员删除 #tagSCFamilyMemDel
+
+class  tagSCFamilyMemDel(Structure):
+    Head = tagHead()
+    Type = 0    #(BYTE Type)// 0-踢出;1-主动退出
+    PlayerID = 0    #(DWORD PlayerID)
+    NameLen = 0    #(BYTE NameLen)
+    Name = ""    #(String Name)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA5
+        self.Head.SubCmd = 0x24
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Type,_pos = CommFunc.ReadBYTE(_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)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA5
+        self.Head.SubCmd = 0x24
+        self.Type = 0
+        self.PlayerID = 0
+        self.NameLen = 0
+        self.Name = ""
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 4
+        length += 1
+        length += len(self.Name)
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.Type)
+        data = CommFunc.WriteDWORD(data, self.PlayerID)
+        data = CommFunc.WriteBYTE(data, self.NameLen)
+        data = CommFunc.WriteString(data, self.NameLen, self.Name)
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Type:%d,
+                                PlayerID:%d,
+                                NameLen:%d,
+                                Name:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Type,
+                                self.PlayerID,
+                                self.NameLen,
+                                self.Name
+                                )
+        return DumpString
+
+
+m_NAtagSCFamilyMemDel=tagSCFamilyMemDel()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCFamilyMemDel.Head.Cmd,m_NAtagSCFamilyMemDel.Head.SubCmd))] = m_NAtagSCFamilyMemDel
+
+
+#------------------------------------------------------
 # A5 22 家族申请加入的玩家信息 #tagMCFamilyReqJoinInfo
 
 class  tagMCFamilyReqJoinPlayer(Structure):
@@ -11338,6 +11490,7 @@
     TotalPage = 0    #(BYTE TotalPage)//一共有多少页
     FamilyCount = 0    #(BYTE FamilyCount)
     FamilyList = list()    #(vector<tagMCFamilyView> FamilyList)//本页家族信息列表
+    Rank = 0    #(DWORD Rank)//玩家公会所在名次,0-没有公会或没有在榜上;>0-对应排名
     data = None
 
     def __init__(self):
@@ -11359,6 +11512,7 @@
             temFamilyList = tagMCFamilyView()
             _pos = temFamilyList.ReadData(_lpData, _pos)
             self.FamilyList.append(temFamilyList)
+        self.Rank,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -11373,6 +11527,7 @@
         self.TotalPage = 0
         self.FamilyCount = 0
         self.FamilyList = list()
+        self.Rank = 0
         return
 
     def GetLength(self):
@@ -11386,6 +11541,7 @@
         length += 1
         for i in range(self.FamilyCount):
             length += self.FamilyList[i].GetLength()
+        length += 4
 
         return length
 
@@ -11400,6 +11556,7 @@
         data = CommFunc.WriteBYTE(data, self.FamilyCount)
         for i in range(self.FamilyCount):
             data = CommFunc.WriteString(data, self.FamilyList[i].GetLength(), self.FamilyList[i].GetBuffer())
+        data = CommFunc.WriteDWORD(data, self.Rank)
         return data
 
     def OutputString(self):
@@ -11411,7 +11568,8 @@
                                 ShowCount:%d,
                                 TotalPage:%d,
                                 FamilyCount:%d,
-                                FamilyList:%s
+                                FamilyList:%s,
+                                Rank:%d
                                 '''\
                                 %(
                                 self.Head.OutputString(),
@@ -11421,7 +11579,8 @@
                                 self.ShowCount,
                                 self.TotalPage,
                                 self.FamilyCount,
-                                "..."
+                                "...",
+                                self.Rank
                                 )
         return DumpString
 
@@ -11738,6 +11897,7 @@
     LeaderID = 0    #(DWORD LeaderID)//族长玩家ID
     MemberCount = 0    #(BYTE MemberCount)//人数
     MemberList = list()    #(vector<tagMCRoleFamilyMember> MemberList)//size = MemberCount
+    Extra1 = 0    #(DWORD Extra1)//附加字段1
     data = None
 
     def __init__(self):
@@ -11768,6 +11928,7 @@
             temMemberList = tagMCRoleFamilyMember()
             _pos = temMemberList.ReadData(_lpData, _pos)
             self.MemberList.append(temMemberList)
+        self.Extra1,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         return _pos
 
     def Clear(self):
@@ -11791,6 +11952,7 @@
         self.LeaderID = 0
         self.MemberCount = 0
         self.MemberList = list()
+        self.Extra1 = 0
         return
 
     def GetLength(self):
@@ -11813,6 +11975,7 @@
         length += 1
         for i in range(self.MemberCount):
             length += self.MemberList[i].GetLength()
+        length += 4
 
         return length
 
@@ -11836,6 +11999,7 @@
         data = CommFunc.WriteBYTE(data, self.MemberCount)
         for i in range(self.MemberCount):
             data = CommFunc.WriteString(data, self.MemberList[i].GetLength(), self.MemberList[i].GetBuffer())
+        data = CommFunc.WriteDWORD(data, self.Extra1)
         return data
 
     def OutputString(self):
@@ -11856,7 +12020,8 @@
                                 Broadcast:%s,
                                 LeaderID:%d,
                                 MemberCount:%d,
-                                MemberList:%s
+                                MemberList:%s,
+                                Extra1:%d
                                 '''\
                                 %(
                                 self.Head.OutputString(),
@@ -11875,7 +12040,8 @@
                                 self.Broadcast,
                                 self.LeaderID,
                                 self.MemberCount,
-                                "..."
+                                "...",
+                                self.Extra1
                                 )
         return DumpString
 
@@ -48857,12 +49023,133 @@
 
 
 #------------------------------------------------------
-# C2 02 跨服通用信息包 #tagSSCommMsg
+# C2 03 跨服中心事件同步 #tagSSCrossCenterEvent
+
+class  tagSSCrossCenterEvent(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ServerID", c_int),    
+                  ("ServerType", c_ubyte),    #服务器类型
+                  ("EventValue", c_int),    #事件值,yyyyMMddhh用于判断过天等
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xC2
+        self.SubCmd = 0x03
+        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 = 0xC2
+        self.SubCmd = 0x03
+        self.ServerID = 0
+        self.ServerType = 0
+        self.EventValue = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagSSCrossCenterEvent)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// C2 03 跨服中心事件同步 //tagSSCrossCenterEvent:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ServerID:%d,
+                                ServerType:%d,
+                                EventValue:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ServerID,
+                                self.ServerType,
+                                self.EventValue
+                                )
+        return DumpString
+
+
+m_NAtagSSCrossCenterEvent=tagSSCrossCenterEvent()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSSCrossCenterEvent.Cmd,m_NAtagSSCrossCenterEvent.SubCmd))] = m_NAtagSSCrossCenterEvent
+
+
+#------------------------------------------------------
+# C2 02 服务器连接跨服成功 #tagSSServerConnOK
+
+class  tagSSServerConnOK(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ServerID", c_int),    
+                  ("ServerType", c_ubyte),    #服务器类型
+                  ("IsReconn", c_ubyte),    #是否重连的
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xC2
+        self.SubCmd = 0x02
+        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 = 0xC2
+        self.SubCmd = 0x02
+        self.ServerID = 0
+        self.ServerType = 0
+        self.IsReconn = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagSSServerConnOK)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// C2 02 服务器连接跨服成功 //tagSSServerConnOK:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ServerID:%d,
+                                ServerType:%d,
+                                IsReconn:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ServerID,
+                                self.ServerType,
+                                self.IsReconn
+                                )
+        return DumpString
+
+
+m_NAtagSSServerConnOK=tagSSServerConnOK()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSSServerConnOK.Cmd,m_NAtagSSServerConnOK.SubCmd))] = m_NAtagSSServerConnOK
+
+
+#------------------------------------------------------
+# C2 10 跨服通用信息包 #tagSSCommMsg
 
 class  tagSSCommMsg(Structure):
     Head = tagHead()
     FromServerID = 0    #(DWORD FromServerID)//哪个服发的
-    ServerTime = 0    #(DWORD ServerTime)//来源服务器时间戳
+    ServerType = 0    #(BYTE ServerType)//服务器类型
+    PlayerID = 0    #(DWORD PlayerID)//哪个玩家触发发送的
     TypeLen = 0    #(BYTE TypeLen)
     MsgType = ""    #(String MsgType)
     Len = 0    #(DWORD Len)
@@ -48872,14 +49159,15 @@
     def __init__(self):
         self.Clear()
         self.Head.Cmd = 0xC2
-        self.Head.SubCmd = 0x02
+        self.Head.SubCmd = 0x10
         return
 
     def ReadData(self, _lpData, _pos=0, _Len=0):
         self.Clear()
         _pos = self.Head.ReadData(_lpData, _pos)
         self.FromServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.ServerTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ServerType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.TypeLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.MsgType,_pos = CommFunc.ReadString(_lpData, _pos,self.TypeLen)
         self.Len,_pos = CommFunc.ReadDWORD(_lpData, _pos)
@@ -48890,9 +49178,10 @@
         self.Head = tagHead()
         self.Head.Clear()
         self.Head.Cmd = 0xC2
-        self.Head.SubCmd = 0x02
+        self.Head.SubCmd = 0x10
         self.FromServerID = 0
-        self.ServerTime = 0
+        self.ServerType = 0
+        self.PlayerID = 0
         self.TypeLen = 0
         self.MsgType = ""
         self.Len = 0
@@ -48903,6 +49192,7 @@
         length = 0
         length += self.Head.GetLength()
         length += 4
+        length += 1
         length += 4
         length += 1
         length += len(self.MsgType)
@@ -48915,7 +49205,8 @@
         data = ''
         data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
         data = CommFunc.WriteDWORD(data, self.FromServerID)
-        data = CommFunc.WriteDWORD(data, self.ServerTime)
+        data = CommFunc.WriteBYTE(data, self.ServerType)
+        data = CommFunc.WriteDWORD(data, self.PlayerID)
         data = CommFunc.WriteBYTE(data, self.TypeLen)
         data = CommFunc.WriteString(data, self.TypeLen, self.MsgType)
         data = CommFunc.WriteDWORD(data, self.Len)
@@ -48926,7 +49217,8 @@
         DumpString = '''
                                 Head:%s,
                                 FromServerID:%d,
-                                ServerTime:%d,
+                                ServerType:%d,
+                                PlayerID:%d,
                                 TypeLen:%d,
                                 MsgType:%s,
                                 Len:%d,
@@ -48935,7 +49227,8 @@
                                 %(
                                 self.Head.OutputString(),
                                 self.FromServerID,
-                                self.ServerTime,
+                                self.ServerType,
+                                self.PlayerID,
                                 self.TypeLen,
                                 self.MsgType,
                                 self.Len,
@@ -48949,14 +49242,16 @@
 
 
 #------------------------------------------------------
-# C2 01 跨服服务器间的测试包 #tagSSTest
+# C2 01 跨服服务器心跳包 #tagSSHeart
 
-class  tagSSTest(Structure):
+class  tagSSHeart(Structure):
     _pack_ = 1
     _fields_ = [
                   ("Cmd", c_ubyte),
                   ("SubCmd", c_ubyte),
-                  ("Data", c_int),    #测试
+                  ("ServerID", c_int),    
+                  ("ServerType", c_ubyte),    #服务器类型
+                  ("ServerTime", c_int),    #服务器时间戳
                   ]
 
     def __init__(self):
@@ -48973,28 +49268,34 @@
     def Clear(self):
         self.Cmd = 0xC2
         self.SubCmd = 0x01
-        self.Data = 0
+        self.ServerID = 0
+        self.ServerType = 0
+        self.ServerTime = 0
         return
 
     def GetLength(self):
-        return sizeof(tagSSTest)
+        return sizeof(tagSSHeart)
 
     def GetBuffer(self):
         return string_at(addressof(self), self.GetLength())
 
     def OutputString(self):
-        DumpString = '''// C2 01 跨服服务器间的测试包 //tagSSTest:
+        DumpString = '''// C2 01 跨服服务器心跳包 //tagSSHeart:
                                 Cmd:%s,
                                 SubCmd:%s,
-                                Data:%d
+                                ServerID:%d,
+                                ServerType:%d,
+                                ServerTime:%d
                                 '''\
                                 %(
                                 self.Cmd,
                                 self.SubCmd,
-                                self.Data
+                                self.ServerID,
+                                self.ServerType,
+                                self.ServerTime
                                 )
         return DumpString
 
 
-m_NAtagSSTest=tagSSTest()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSSTest.Cmd,m_NAtagSSTest.SubCmd))] = m_NAtagSSTest
\ No newline at end of file
+m_NAtagSSHeart=tagSSHeart()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSSHeart.Cmd,m_NAtagSSHeart.SubCmd))] = m_NAtagSSHeart
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChServerToServerPyPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChServerToServerPyPack.py
index 071b9d6..6a433c4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChServerToServerPyPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChServerToServerPyPack.py
@@ -36,8 +36,8 @@
     def GetLength(self):
         length = 0
         length += 1
-        length += self.Name.Length()
-        return  length
+        length += self.Name.Length();
+        return  length;
 
     def GetBuffer(self):
         data = ''
@@ -81,7 +81,7 @@
         length = 0
         length += 1
         length += 1
-        return  length
+        return  length;
 
     def GetBuffer(self):
         data = ''
@@ -101,12 +101,133 @@
 
         return  DumpString
 #------------------------------------------------------
-# C2 02 跨服通用信息包 #tagSSCommMsg
+# C2 03 跨服中心事件同步 #tagSSCrossCenterEvent
+
+class  tagSSCrossCenterEvent(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ServerID", c_int),    
+                  ("ServerType", c_ubyte),    #服务器类型
+                  ("EventValue", c_int),    #事件值,yyyyMMddhh用于判断过天等
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xC2
+        self.SubCmd = 0x03
+        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 = 0xC2
+        self.SubCmd = 0x03
+        self.ServerID = 0
+        self.ServerType = 0
+        self.EventValue = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagSSCrossCenterEvent)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// C2 03 跨服中心事件同步 //tagSSCrossCenterEvent:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ServerID:%d,
+                                ServerType:%d,
+                                EventValue:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ServerID,
+                                self.ServerType,
+                                self.EventValue
+                                )
+        return DumpString
+
+
+m_NAtagSSCrossCenterEvent=tagSSCrossCenterEvent()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSSCrossCenterEvent.Cmd,m_NAtagSSCrossCenterEvent.SubCmd))] = m_NAtagSSCrossCenterEvent
+
+
+#------------------------------------------------------
+# C2 02 服务器连接跨服成功 #tagSSServerConnOK
+
+class  tagSSServerConnOK(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ServerID", c_int),    
+                  ("ServerType", c_ubyte),    #服务器类型
+                  ("IsReconn", c_ubyte),    #是否重连的
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xC2
+        self.SubCmd = 0x02
+        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 = 0xC2
+        self.SubCmd = 0x02
+        self.ServerID = 0
+        self.ServerType = 0
+        self.IsReconn = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagSSServerConnOK)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// C2 02 服务器连接跨服成功 //tagSSServerConnOK:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ServerID:%d,
+                                ServerType:%d,
+                                IsReconn:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ServerID,
+                                self.ServerType,
+                                self.IsReconn
+                                )
+        return DumpString
+
+
+m_NAtagSSServerConnOK=tagSSServerConnOK()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSSServerConnOK.Cmd,m_NAtagSSServerConnOK.SubCmd))] = m_NAtagSSServerConnOK
+
+
+#------------------------------------------------------
+# C2 10 跨服通用信息包 #tagSSCommMsg
 
 class  tagSSCommMsg(Structure):
     Head = tagHead()
     FromServerID = 0    #(DWORD FromServerID)//哪个服发的
-    ServerTime = 0    #(DWORD ServerTime)//来源服务器时间戳
+    ServerType = 0    #(BYTE ServerType)//服务器类型
+    PlayerID = 0    #(DWORD PlayerID)//哪个玩家触发发送的
     TypeLen = 0    #(BYTE TypeLen)
     MsgType = ""    #(String MsgType)
     Len = 0    #(DWORD Len)
@@ -116,14 +237,15 @@
     def __init__(self):
         self.Clear()
         self.Head.Cmd = 0xC2
-        self.Head.SubCmd = 0x02
+        self.Head.SubCmd = 0x10
         return
 
     def ReadData(self, _lpData, _pos=0, _Len=0):
         self.Clear()
         _pos = self.Head.ReadData(_lpData, _pos)
         self.FromServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
-        self.ServerTime,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ServerType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
         self.TypeLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
         self.MsgType,_pos = CommFunc.ReadString(_lpData, _pos,self.TypeLen)
         self.Len,_pos = CommFunc.ReadDWORD(_lpData, _pos)
@@ -134,9 +256,10 @@
         self.Head = tagHead()
         self.Head.Clear()
         self.Head.Cmd = 0xC2
-        self.Head.SubCmd = 0x02
+        self.Head.SubCmd = 0x10
         self.FromServerID = 0
-        self.ServerTime = 0
+        self.ServerType = 0
+        self.PlayerID = 0
         self.TypeLen = 0
         self.MsgType = ""
         self.Len = 0
@@ -147,6 +270,7 @@
         length = 0
         length += self.Head.GetLength()
         length += 4
+        length += 1
         length += 4
         length += 1
         length += len(self.MsgType)
@@ -159,7 +283,8 @@
         data = ''
         data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
         data = CommFunc.WriteDWORD(data, self.FromServerID)
-        data = CommFunc.WriteDWORD(data, self.ServerTime)
+        data = CommFunc.WriteBYTE(data, self.ServerType)
+        data = CommFunc.WriteDWORD(data, self.PlayerID)
         data = CommFunc.WriteBYTE(data, self.TypeLen)
         data = CommFunc.WriteString(data, self.TypeLen, self.MsgType)
         data = CommFunc.WriteDWORD(data, self.Len)
@@ -170,7 +295,8 @@
         DumpString = '''
                                 Head:%s,
                                 FromServerID:%d,
-                                ServerTime:%d,
+                                ServerType:%d,
+                                PlayerID:%d,
                                 TypeLen:%d,
                                 MsgType:%s,
                                 Len:%d,
@@ -179,7 +305,8 @@
                                 %(
                                 self.Head.OutputString(),
                                 self.FromServerID,
-                                self.ServerTime,
+                                self.ServerType,
+                                self.PlayerID,
                                 self.TypeLen,
                                 self.MsgType,
                                 self.Len,
@@ -193,14 +320,16 @@
 
 
 #------------------------------------------------------
-# C2 01 跨服服务器间的测试包 #tagSSTest
+# C2 01 跨服服务器心跳包 #tagSSHeart
 
-class  tagSSTest(Structure):
+class  tagSSHeart(Structure):
     _pack_ = 1
     _fields_ = [
                   ("Cmd", c_ubyte),
                   ("SubCmd", c_ubyte),
-                  ("Data", c_int),    #测试
+                  ("ServerID", c_int),    
+                  ("ServerType", c_ubyte),    #服务器类型
+                  ("ServerTime", c_int),    #服务器时间戳
                   ]
 
     def __init__(self):
@@ -217,28 +346,34 @@
     def Clear(self):
         self.Cmd = 0xC2
         self.SubCmd = 0x01
-        self.Data = 0
+        self.ServerID = 0
+        self.ServerType = 0
+        self.ServerTime = 0
         return
 
     def GetLength(self):
-        return sizeof(tagSSTest)
+        return sizeof(tagSSHeart)
 
     def GetBuffer(self):
         return string_at(addressof(self), self.GetLength())
 
     def OutputString(self):
-        DumpString = '''// C2 01 跨服服务器间的测试包 //tagSSTest:
+        DumpString = '''// C2 01 跨服服务器心跳包 //tagSSHeart:
                                 Cmd:%s,
                                 SubCmd:%s,
-                                Data:%d
+                                ServerID:%d,
+                                ServerType:%d,
+                                ServerTime:%d
                                 '''\
                                 %(
                                 self.Cmd,
                                 self.SubCmd,
-                                self.Data
+                                self.ServerID,
+                                self.ServerType,
+                                self.ServerTime
                                 )
         return DumpString
 
 
-m_NAtagSSTest=tagSSTest()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSSTest.Cmd,m_NAtagSSTest.SubCmd))] = m_NAtagSSTest
\ No newline at end of file
+m_NAtagSSHeart=tagSSHeart()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSSHeart.Cmd,m_NAtagSSHeart.SubCmd))] = m_NAtagSSHeart
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/CrossServerPackLogic.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/CrossServerPackLogic.py
deleted file mode 100644
index f65d7e5..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/CrossServerPackLogic.py
+++ /dev/null
@@ -1,178 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#
-#
-##@package CrossServerPackLogic.py
-# @todo: 跨服服务器间封包逻辑
-# 跨服服务器间的封包 既是收包也是发包
-
-import GameWorld
-import ShareDefine
-import NetPackCommon
-import ChServerToServerPyPack
-import TurnAttack
-import PyGameData
-import ChPlayer
-
-import traceback
-import cPickle
-import time
-
-def OnTest(netPack):
-
-    GameWorld.Log("收到跨服包 " + str(netPack.Data))
-
-
-def SendTest(dirType, serverList):
-    pack = ChServerToServerPyPack.tagSSTest()
-    pack.Data = 12
-    #0全广播,1通知主服务器排除合服子服,2通知服务器包含合服子服, 3通知跨服服务器 
-    NetPackCommon.SendCrossServerToServerPack(dirType, serverList, pack.GetBuffer())
-    return
-
-def GetCrossServerID():
-    ## 获取本服务器所属的跨服中心服务器
-    return 0
-
-def SendToCrossServer(msgType, dataMsg):
-    ## 发送信息到跨服服务器
-    if GameWorld.IsCrossServer():
-        return
-    if not dataMsg:
-        return
-    if msgType not in [ShareDefine.ClientServerMsg_ServerInitOK]:
-        isOpen = GameWorld.GetGameWorld().GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossServerOpen)
-        if not isOpen:
-            GameWorld.Log("跨服服务器未开启或维护中不发送消息! SendMsgToCrossServer => %s" % msgType)
-            return
-    crossServerID = GetCrossServerID()
-    if not crossServerID:
-        return
-    
-    playerID = 0
-    if isinstance(dataMsg, dict):
-        playerID = dataMsg.get("playerID", 0)
-        if not playerID:
-            playerID = dataMsg.get("PlayerID", 0)
-            
-    GameWorld.Log("SendMsgToCrossServer => %s, %s, %s" % (msgType, crossServerID, dataMsg), playerID)
-    SendToServer(msgType, dataMsg, [crossServerID], ShareDefine.dirType_Cross, playerID, isLog=False)
-    return
-
-def SendToClientServer(msgType, dataMsg, serverIDList=None):
-    ''' 发送信息到子服务器
-        @param serverGroupIDList: 发送指定的服务器组ID列表,内部已经针对列表中组ID去重,
-        所以外部逻辑可直接添加,不用考虑组ID重复问题,没有指定服务器组ID时,默认广播所有子服
-    '''
-    if not GameWorld.IsCrossServer():
-        return
-    
-    if not PyGameData.g_serverInitOK:
-        GameWorld.ErrLog("跨服服务器未启动好,不允许向子服发送数据! %s, %s, %s" % (msgType, serverIDList, dataMsg))
-        return
-    
-    playerID = 0
-    if isinstance(dataMsg, dict):
-        playerID = dataMsg.get("playerID", 0)
-        if not playerID:
-            playerID = dataMsg.get("PlayerID", 0)
-            
-    GameWorld.Log("SendToClientServer => %s, %s, %s" % (msgType, serverIDList, dataMsg), playerID)
-    SendToServer(msgType, dataMsg, serverIDList, ShareDefine.dirType_Main, playerID, isLog=False) # 默认发给主服即可
-    return
-
-def SendBattleRequest(dataMsg, guid, mapID, funcLineID, reqPlayerID=0):
-    msgType = ShareDefine.SSMsg_BattleRequest
-    GameWorld.Log("SendToBattleServer => %s, funcMapID=%s,funcLineID=%s,%s,%s" % (msgType, mapID, funcLineID, guid, time.time()), reqPlayerID)
-    SendToServer(msgType, dataMsg, dirType=ShareDefine.dirType_Battle, playerID=reqPlayerID, isLog=False)
-    return
-
-def SendBattleResult(retInfo, fromServerID, guid, mapID, funcLineID, reqPlayerID=0):
-    msgType = ShareDefine.SSMsg_BattleResult
-    GameWorld.Log("SendToFromServer => %s, fromServerID=%s,funcMapID=%s,funcLineID=%s,%s,%s" 
-                  % (msgType, fromServerID, mapID, funcLineID, guid, time.time()), reqPlayerID)
-    SendToServer(msgType, retInfo, [fromServerID], ShareDefine.dirType_Main, reqPlayerID, isLog=False)
-    return
-
-def SendToServer(msgType, dataMsg, serverIDList=None, dirType=ShareDefine.dirType_Main, playerID=0, isLog=True):
-    '''发送给其他服务器
-    @param msgType: 功能信息类型字符定义
-    @param dataMsg: 发送的数据,任意格式,由功能自行决定
-    @param serverIDList: 指定目标服务器ID 或   服务器ID列表
-    '''
-    
-    if isinstance(serverIDList, int):
-        serverIDList = [serverIDList]
-    elif not isinstance(serverIDList, list):
-        serverIDList = []
-    else:
-        serverIDList = list(set(serverIDList)) # 去重
-        
-    if isLog:
-        GameWorld.Log("SendToServer => %s, %s, %s" % (msgType, serverIDList, dataMsg), playerID)
-        
-    # 协议要用最高级2,可减少长度
-    sendMsg = cPickle.dumps(dataMsg, 2)
-    
-    pack = ChServerToServerPyPack.tagSSCommMsg()
-    pack.FromServerID = GameWorld.GetGameWorld().GetServerID()
-    pack.ServerTime = int(time.time())
-    pack.MsgType = msgType
-    pack.TypeLen = len(pack.MsgType)
-    pack.Data = sendMsg
-    pack.Len = len(pack.Data)
-    NetPackCommon.SendCrossServerToServerPack(dirType, serverIDList, pack.GetBuffer())
-    return
-
-def OnSSCommMsg(netPack):
-    ## 收到其他服务器发来的消息
-    
-    fromServerID = netPack.FromServerID
-    fromServerTime = netPack.ServerTime
-    msgType = netPack.MsgType
-    recvMsg = netPack.Data
-    
-    if not PyGameData.g_serverInitOK:
-        GameWorld.Log("服务器未启动好,不处理其他服务器信息! %s, fromServerID=%s" % (msgType, fromServerID))
-        return
-    
-    try:
-        dataMsg = cPickle.loads(recvMsg)
-        if GameWorld.IsCrossServer():
-            pass #GameWorld.Log("OnCrossServerReceiveMsg: %s, fromServerID=%s, %s" % (msgType, fromServerID, dataMsg))
-        else:
-            pass #GameWorld.Log("OnClientServerReceiveMsg: %s, fromServerID=%s, %s" % (msgType, fromServerID, dataMsg))
-            
-            crossServerID = GetCrossServerID()
-            if crossServerID == fromServerID:
-                __fixCrossServerTime(msgType, fromServerTime)
-                
-        if msgType == ShareDefine.SSMsg_BattleRequest:
-            TurnAttack.SSMsg_BattleRequest(dataMsg, fromServerID, msgType)
-        elif msgType == ShareDefine.SSMsg_BattleResult:
-            TurnAttack.SSMsg_BattleResult(dataMsg, fromServerID, msgType)
-            
-    except:
-        GameWorld.RaiseException("服务器接收信息处理报错 \r\n%s" % str(traceback.format_exc()))
-    return
-
-def __fixCrossServerTime(msgType, crossServerTime):
-    # 子服矫正跨服服务器时间
-    curServerTime = int(time.time())
-    curServerCrossServerTime = GameWorld.ChangeTimeStrToNum(GameWorld.GetCrossServerTimeStr())
-    diffSeconds = curServerCrossServerTime - crossServerTime # 本服计算误差
-    
-    PyGameData.g_crossServerTimeInfo = [crossServerTime, curServerTime] # 覆盖更新
-    
-    # 误差超过30秒 或强制同步时间的
-    if abs(diffSeconds) >= 30 or msgType == ShareDefine.CrossServerMsg_CrossServerTime:
-        GameWorld.DebugLog("同步跨服服务器时间,本服与跨服服务器时间计算误差! diffSeconds=%s" % (diffSeconds))
-        playerManager = GameWorld.GetPlayerManager()
-        for i in xrange(playerManager.GetPlayerCount()):
-            curPlayer = playerManager.GetPlayerByIndex(i)
-            if not GameWorld.IsNormalPlayer(curPlayer):
-                continue
-            ChPlayer.Sync_PyServerDataTimeToClient(curPlayer)
-    return
-
-
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
index 9ec0831..87923d5 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/DBStruct.py
@@ -747,6 +747,11 @@
         ('FightPowerEx', ctypes.c_ulong),
         ('EmblemID', ctypes.c_ushort),
         ('EmblemWord', ctypes.c_char * 3),
+        ('Extra1', ctypes.c_ulong),
+        ('Extra2', ctypes.c_ulong),
+        ('Extra3', ctypes.c_ulong),
+        ('Extra4', ctypes.c_ulong),
+        ('Extra5', ctypes.c_ulong),
         ('ADOResult', ctypes.c_ulong),
     ]
 
@@ -770,6 +775,11 @@
         self.FightPowerEx = 0
         self.EmblemID = 0
         self.EmblemWord = ''
+        self.Extra1 = 0
+        self.Extra2 = 0
+        self.Extra3 = 0
+        self.Extra4 = 0
+        self.Extra5 = 0
 
     def readData(self, buf, pos = 0, length = 0):
         if not pos <= length:
@@ -793,6 +803,11 @@
         self.FightPowerEx, pos = CommFunc.ReadDWORD(buf, pos)
         self.EmblemID, pos = CommFunc.ReadWORD(buf, pos)
         self.EmblemWord, pos = CommFunc.ReadString(buf, pos, 3)
+        self.Extra1, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Extra2, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Extra3, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Extra4, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Extra5, pos = CommFunc.ReadDWORD(buf, pos)
         return self.getLength()
 
     def getBuffer(self):
@@ -812,6 +827,11 @@
         buf = CommFunc.WriteDWORD(buf, self.FightPowerEx)
         buf = CommFunc.WriteWORD(buf, self.EmblemID)
         buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 3, self.EmblemWord)
+        buf = CommFunc.WriteDWORD(buf, self.Extra1)
+        buf = CommFunc.WriteDWORD(buf, self.Extra2)
+        buf = CommFunc.WriteDWORD(buf, self.Extra3)
+        buf = CommFunc.WriteDWORD(buf, self.Extra4)
+        buf = CommFunc.WriteDWORD(buf, self.Extra5)
         return buf
 
     def getLength(self):
@@ -831,6 +851,11 @@
         length += sizeof(ctypes.c_ulong)
         length += sizeof(ctypes.c_ushort)
         length += sizeof(ctypes.c_char) * 3
+        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)
         return length
 
     def outputString(self):
@@ -850,6 +875,11 @@
             FightPowerEx = %s,
             EmblemID = %s,
             EmblemWord = %s,
+            Extra1 = %s,
+            Extra2 = %s,
+            Extra3 = %s,
+            Extra4 = %s,
+            Extra5 = %s,
             ADOResult = %s,
             '''%(
                 self.ID,
@@ -867,6 +897,11 @@
                 self.FightPowerEx,
                 self.EmblemID,
                 self.EmblemWord,
+                self.Extra1,
+                self.Extra2,
+                self.Extra3,
+                self.Extra4,
+                self.Extra5,
                 self.ADOResult,
             )
         return output
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py
index 5d66d8b..81d7080 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBFamily.py
@@ -15,20 +15,25 @@
 #"""Version = 2025-05-09 12:20"""
 #-------------------------------------------------------------------------------
 
+import ChPlayer
 import DBStruct
 import CommFunc
 import GameWorld
 import ShareDefine
-import PlayerControl
 import PlayerViewCache
+import ChPyNetSendPack
+import NetPackCommon
+import IpyGameDataPY
 import PyMongoMain
 import DBDataMgr
+import CrossMgr
+import CrossMsg
 import ChConfig
 import DBComm
 
 import time
 
-FamilyUpperLimitCount = 2000
+#FamilyUpperLimitCount = 2000
 
 class FamilyActionData():
     
@@ -192,11 +197,15 @@
     
 class FamilyMem():
     
-    def __init__(self, dbData=None):
+    def __init__(self, dbData=None, family=None):
         self.__dbData = DBStruct.tagDBFamilyMem() if not dbData else dbData
+        self.__family = family
         return
     
-    def GetFamily(self): return DBDataMgr.GetFamilyMgr().FindFamily(self.__dbData.FamilyID)
+    def GetFamily(self):
+        if not self.__family:
+            self.__family = DBDataMgr.GetFamilyMgr().FindFamily(self.__dbData.FamilyID)
+        return self.__family
     def GetPlayerID(self): return self.__dbData.PlayerID
     def GetFamilyID(self): return self.__dbData.FamilyID
     def GetJoinTime(self): return self.__dbData.JoinTime
@@ -238,7 +247,9 @@
     def GetBuffer(self): return self.__dbData.getBuffer()
     
     def RefreshMemberByID(self, playerID):
-        ## 根据玩家ID更新成员数据,一般用于离线功能,如添加离线成员,直接使用查看缓存更新
+        '''刷新成员信息,仙盟成员属于永久功能数据,除非仙盟解散,所以单独存一份成员基础信息,支持离线玩家,直接使用查看缓存更新
+        @return: 战力是否变更
+        '''
         if playerID != self.GetPlayerID():
             return
         viewCache = PlayerViewCache.FindViewCache(playerID)
@@ -254,35 +265,12 @@
         self.SetServerID(viewCache.GetServerID())
         fpChange = False
         fightPowerTotal = viewCache.GetFightPowerTotal()
-        if self.GetFightPowerTotal() < fightPowerTotal:
+        if self.GetFightPowerTotal() != fightPowerTotal:
             self.SetFightPowerTotal(fightPowerTotal)
             fpChange = True
             family = self.GetFamily()
             if family:
-                family.SetMemFightPowerChange()
-        return fpChange
-    
-    def RefreshMember(self, curPlayer):
-        '''刷新成员信息,仙盟成员属于永久功能数据,除非仙盟解散,所以单独存一份成员基础信息,防止过度依赖查看缓存数据引发的问题
-        @return: 战力是否变更
-        '''
-        if not curPlayer or curPlayer.GetPlayerID() != self.GetPlayerID():
-            return
-        self.SetPlayerName(curPlayer.GetPlayerName())
-        self.SetLV(curPlayer.GetLV())
-        self.SetJob(curPlayer.GetJob())
-        self.SetRealmLV(curPlayer.GetOfficialRank())
-        self.SetFace(curPlayer.GetFace())
-        self.SetFacePic(curPlayer.GetFacePic())
-        self.SetTitleID(PlayerControl.GetTitleID(curPlayer))
-        self.SetServerID(GameWorld.GetPlayerServerID(curPlayer))
-        fightPowerTotal = PlayerControl.GetFightPower(curPlayer)
-        fpChange = self.GetFightPowerTotal() != fightPowerTotal
-        self.SetFightPowerTotal(fightPowerTotal)
-        if fpChange:
-            family = self.GetFamily()
-            if family:
-                family.SetMemFightPowerChange()
+                family.RefrshFightPowerTotal()
         return fpChange
     
 class Family():
@@ -293,7 +281,6 @@
         self.__memberDict = {} # 成员字典 {playerID:FamilyMem, ...}
         self.__familyMgr = DBDataMgr.GetFamilyMgr()
         self.__actionMgr = DBDataMgr.GetFamilyActionMgr()
-        self.__memFightPowerChange = None # 成员战力是否有变化,默认None,代表未处理过
         return
     
     def GetID(self): return self.__dbData.ID
@@ -318,24 +305,39 @@
         return
     def GetFightPower(self): return self.__dbData.FightPower
     def GetFightPowerEx(self): return self.__dbData.FightPowerEx
-    def GetFightPowerTotal(self): return self.__dbData.FightPowerEx * ChConfig.Def_PerPointValue + self.__dbData.FightPower
+    def GetFightPowerTotal(self):
+        return self.__dbData.FightPowerEx * ChConfig.Def_PerPointValue + self.__dbData.FightPower
     def SetFightPowerTotal(self, fightPowerTotal):
+        fpBef = self.GetFightPowerTotal()
         self.__dbData.FightPower = fightPowerTotal % ChConfig.Def_PerPointValue
         self.__dbData.FightPowerEx = fightPowerTotal / ChConfig.Def_PerPointValue
+        fpAft = self.GetFightPowerTotal()
+        if fpBef != fpAft:
+            self.__familyMgr.OnFightPowerChange(self)
         return
     def GetEmblemID(self): return self.__dbData.EmblemID
     def SetEmblemID(self, emblemID): self.__dbData.EmblemID = emblemID
     def GetEmblemWord(self): return self.__dbData.EmblemWord
     def SetEmblemWord(self, emblemWord): self.__dbData.EmblemWord = emblemWord
+    def GetExtra1(self): return self.__dbData.Extra1
+    def SetExtra1(self, extra1): self.__dbData.Extra1 = extra1
+    def GetExtra2(self): return self.__dbData.Extra2
+    def SetExtra2(self, extra2): self.__dbData.Extra2 = extra2
+    def GetExtra3(self): return self.__dbData.Extra3
+    def SetExtra3(self, extra3): self.__dbData.Extra3 = extra3
+    def GetExtra4(self): return self.__dbData.Extra4
+    def SetExtra4(self, extra4): self.__dbData.Extra4 = extra4
+    def GetExtra5(self): return self.__dbData.Extra5
+    def SetExtra5(self, extra5): self.__dbData.Extra5 = extra5
     def GetBuffer(self): return self.__dbData.getBuffer()
-        
+    
     ## ------------------------------------------------
     def InitMemberInstance(self, dbData):
         '''初始化功能数据实例,创建或加载数据时通用,功能一般不调用
         @param dbData: 实例对应绑定的dbData
         @return: 成功返回实例对象,失败返回None
         '''
-        member = FamilyMem(dbData)
+        member = FamilyMem(dbData, self)
         playerID = member.GetPlayerID()
         if playerID in self.__memberDict:
             return
@@ -357,14 +359,16 @@
             member = self.InitMemberInstance(dbData)
             if not member and False:
                 member = FamilyMem()
-        self.__memFightPowerChange = True
+        self.RefrshFightPowerTotal()
+        self.__familyMgr.OnAddMember(self, playerID)
         return member
     
     def DeleteMember(self, playerID):
         delMem = self.__memberDict.pop(playerID, None)
         if delMem in self.__memberList:
             self.__memberList.remove(delMem)
-        self.__memFightPowerChange = True
+        self.RefrshFightPowerTotal()
+        self.__familyMgr.OnDelMember(self, playerID)
         return delMem
     
     def FindMember(self, playerID):
@@ -384,12 +388,8 @@
             mem = FamilyMem()
         return mem
     
-    def SetMemFightPowerChange(self): self.__memFightPowerChange = True
-    def RefrshFightPowerTotal(self, checkChange=False):
+    def RefrshFightPowerTotal(self):
         ## 刷新总战力
-        if checkChange and self.__memFightPowerChange == False: # 默认None,首次必刷新
-            #GameWorld.DebugLog("没有成员战力变化可不刷新仙盟总战力! familyID=%s" % self.GetID())
-            return
         familyFightPowerTotal = 0
         for index in range(self.GetCount()):
             member = self.GetAt(index)
@@ -397,8 +397,6 @@
                 continue
             familyFightPowerTotal += member.GetFightPowerTotal()
         self.SetFightPowerTotal(familyFightPowerTotal)
-        #GameWorld.DebugLog("刷新仙盟总战力! familyID=%s" % self.GetID())
-        self.__memFightPowerChange = False
         return familyFightPowerTotal
     
     def GetReqJoinPlayerInfo(self):
@@ -432,68 +430,121 @@
         return
     
     def OnDelete(self):
+        for memID in self.__memberDict.keys():
+            self.DeleteMember(memID)
         self.DelReqJoinPlayerAll()
         self.__actionMgr.ClearFamilyAction(self.GetID())
         return
     
-class FamilyMgr():
+#class FamilyViewBase():
+#    ## 公会基础信息,本服跨服通用,一般用于本服公会需要用的基本信息,如查看,方便本服可直接取,由跨服同步
+#    
+#    def __init__(self, familyID):
+#        self._familyID = familyID
+#        self._family = None
+#        self._familyName = ""
+#        self._serverID = 0
+#        self._emblemID = 0
+#        self._emblemWord = ""
+#        return
+#    
+#    def SetFamily(self, family): self._family = family
+#    
+#    def GetID(self): return self._familyID
+#    
+#    # 有值以设置的值为准-跨服同步过来的,否则以本服已存在的公会数据为准-即未互通时兼容取本服公会数据
+#    def GetName(self): return self._familyName if self._familyName else (self._family.GetName() if self._family else "")
+#    def GetServerID(self): return self._serverID if self._serverID else (self._family.GetServerID() if self._family else 0)
+#    def GetEmblemID(self): return self._emblemID if self._emblemID else (self._family.GetEmblemID() if self._family else 0)
+#    def GetEmblemWord(self): return self._emblemWord if self._emblemWord else (self._family.GetEmblemWord() if self._family else "")
+#    
+#    def GetSyncData(self):
+#        return [self.GetName(), self.GetServerID(), self.GetEmblemID(), self.GetEmblemWord()]
+#    
+#    def UpdSyncData(self, syncData):
+#        ## 根据跨服同步过来的更新
+#        self._familyName = syncData[0] if len(syncData) > 0 else self._familyName
+#        self._serverID = syncData[1] if len(syncData) > 1 else self._serverID
+#        self._emblemID = syncData[2] if len(syncData) > 2 else self._emblemID
+#        self._emblemWord = syncData[3] if len(syncData) > 3 else self._emblemWord
+#        return
     
-    def __init__(self):
-        self.__familyList = [] # 仙盟对象列表,可进行排序 [Family, ...]
-        self.__familyIDDict = {} # 仙盟ID对象字典,  {familyID:Family, ...}
-        self.__familyNameDict = {} # 仙盟名称对象字典,  {familyName:Family, ...}
-        self.__actionMgr = FamilyActionMgr()
-        self.__playerReqJoinDict = None # 玩家申请加入仙盟列表 {playerID:[familyID, ...], ...}
+class ZoneFamilyMgr():
+    ## 跨服公会互通分区,本服的也使用,默认分区0
+    ## 【注意】跨服分区只是在原公会数据的基础上进行汇总归纳分区,即使分区异常也不要影响公会数据,可重复进行修改配置重新分区
+    
+    def __init__(self, zoneID=0):
+        self.__familyMgr = DBDataMgr.GetFamilyMgr()
+        self.__zoneID = zoneID # 本服默认分区0,即未互通的服务器
+        self.__familyList = [] # 公会对象列表,可进行排序 [Family, ...]
+        self.__familyIDDict = {} # 公会ID对象字典,  {familyID:Family, ...}
+        self.__familyNameDict = {} # 公会名称对象字典,  {familyName:Family, ...}
+        self.__zoneServerIDList = [] # 本分区实际已经互通的公会服务器ID列表 [serverID, ...]
+        self.__familyIDRankDict = {} # 公会名次字典 {familyID:rank, ...}
+        self.__needSort = True
+        
+        ## 注意!注意!注意!暂时只存分区的公会列表管理,其他分区相关的缓存数据暂不要放这里
+        ## 因为分区配置重读变更后会被重置可能导致丢失,如需要存储其他数据再另行处理
         return
     
-    def InitFamilyInstance(self, dbData):
-        '''初始化功能数据实例,创建或加载数据时通用,功能一般不调用
-        @param dbData: 实例对应绑定的dbData
-        @return: 成功返回实例对象,失败返回None
+    def GetZoneID(self): return self.__zoneID
+    
+    def SetSort(self): self.__needSort = True # 设置需要排序
+    
+    def Sort(self, checkSort=False):
+        ''' 默认排序倒序,按  仙盟总战力 -> 仙盟等级
+        @param checkSort: 是否检查需要排序,如果需要排序才会排序,设置True时则强制排序不检查
         '''
-        family = Family(dbData)
+        if checkSort and not self.__needSort:
+            return
+        self.__familyList.sort(key=lambda f: (f.GetFightPowerTotal(), f.GetLV()), reverse=True)
+        self.__familyIDRankDict = {}
+        self.__needSort = False
+        return
+    
+    def AddFamilyToZone(self, family):
+        ## 将某个公会分配给该分区
+        if not family:
+            return
         familyID = family.GetID()
         if familyID in self.__familyIDDict:
             return
-        self.__familyList.append(family)
         self.__familyIDDict[familyID] = family
-        self.__familyNameDict[family.GetName()] = family
-        return family
-    
-    def Sort(self):
-        ''' 默认排序倒序,按  仙盟总战力 -> 仙盟等级
-        '''
-        self.__familyList.sort(key=lambda f: (f.GetFightPowerTotal(), f.GetLV()), reverse=True)
+        
+        familyServerID = family.GetServerID()
+        familyName = family.GetName()
+        # 规定相同分区名字唯一,如重名,强制修改为唯一的;合服数据合并、首次互通传数据等均支持自动改名
+        if familyName in self.__familyNameDict:
+            for doCnt in range(1, 1000):
+                fixName = "%s%s" % (familyName, doCnt) # 强制加个编号
+                if fixName not in self.__familyNameDict:
+                    familyName = fixName
+                    break
+        self.__familyNameDict[familyName] = family
+        
+        if family not in self.__familyList:
+            self.__familyList.append(family)
+            self.__familyIDRankDict = {} # 新公会加入时重置
+            
+        if familyServerID not in self.__zoneServerIDList:
+            self.__zoneServerIDList.append(familyServerID)
+            
+        self.__needSort = True
+        self.__familyMgr.OnAddToZone(family, self.__zoneID)
         return
     
-    def AddFamily(self, familyName, serverID, familyID=None):
-        ## 创建新仙盟
-        newFamily = None
-        if familyID == None:
-            familyID = PyMongoMain.GetUserCtrlDB().GetNewFamilyID()
-            if familyID <= 0:
-                GameWorld.ErrLog("创建仙盟时生成新ID异常!")
-                return newFamily
-        if familyID in self.__familyIDDict:
-            GameWorld.ErrLog("创建仙盟时ID已存在! familyID=%s" % familyID)
-            return newFamily
-        if familyName in self.__familyNameDict:
-            GameWorld.ErrLog("创建仙盟时名称已存在! familyName=%s" % familyName)
-            return newFamily
-        if len(self.__familyList) >= FamilyUpperLimitCount:
-            GameWorld.ErrLog("单服限制创建仙盟数已达上限!")
-            return newFamily
-        
-        dbData = DBStruct.tagDBFamily()
-        dbData.ID = familyID
-        dbData.Name = familyName
-        dbData.ServerID = serverID
-        dbData.CreateTime = int(time.time())
-        
-        newFamily = self.InitFamilyInstance(dbData)
-        if not newFamily and False: # 不执行,为了代码提示
-            newFamily = Family()
-        return newFamily
+    def DelZoneFamily(self, familyID):
+        family = self.__familyIDDict.pop(familyID, None)
+        if not family:
+            return
+        if family in self.__familyList:
+            self.__familyList.remove(family)
+        self.__familyNameDict.pop(family.GetName(), None)
+        self.__familyIDRankDict.pop(familyID, None)
+        self.__needSort = True
+        return
+    
+    def GetZoneServerIDList(self): return self.__zoneServerIDList
     
     def FindFamily(self, familyID):
         family = None
@@ -511,25 +562,6 @@
             family = Family()
         return family
     
-    def DelFamily(self, familyID):
-        family = self.FindFamily(familyID)
-        if family:
-            self.__familyNameDict.pop(family.GetName(), None)
-            if family in self.__familyList:
-                self.__familyList.remove(family)
-            family.OnDelete()
-        self.__familyIDDict.pop(familyID, None)
-        if familyID >= ShareDefine.RealFamilyIDStart:
-            PyMongoMain.GetUserCtrlDB().FreeFamilyID(familyID) # 归还仙盟ID,重复使用
-        return family
-    
-    def DelAllFamily(self):
-        for index in range(self.GetCount())[::-1]:
-            family = self.GetAt(index)
-            familyID = family.GetID()
-            self.DelFamily(familyID)
-        return
-    
     def GetCount(self): return len(self.__familyList)
     def GetAt(self, index):
         family = None
@@ -539,31 +571,196 @@
             family = Family()
         return family
     
-    def GetPlayerFamilyID(self, playerID):
-        ## 获取玩家当前所属的仙盟ID
-        for index in range(self.GetCount()):
-            family = self.GetAt(index)
-            if family.FindMember(playerID):
-                return family.GetID()
-        return 0
+    def GetFamilyRank(self, familyID):
+        ## 获取公会ID所在排名
+        # @return: 0-未上榜; >0-名次
+        if not familyID:
+            return 0
+        if not self.__familyIDRankDict:
+            self.__familyIDRankDict = {}
+            for rank, family in enumerate(self.__familyList, 1):
+                self.__familyIDRankDict[family.GetID()] = rank
+        if familyID not in self.__familyIDRankDict:
+            return 0
+        return self.__familyIDRankDict[familyID]
+    
+class FamilyMgr():
+    ''' 所有分区的公会总管理,本服、跨服通用,zoneID为0时默认是本服的非跨服互通公会
+    '''
+    
+    def __init__(self):
+        
+        ## ----------------------- 公会数据服务器的信息,如【未互通游戏服】 或 【跨服】 ------------------------
+        # 本服务器数据,可能是游戏服本服 或 跨服互通数据
+        self.__familyIDDict = {} # 公会ID对象字典,  {familyID:Family, ...}
+        self.__playerFamilyIDDict = {} # 玩家所属公会ID字典 {playerID:familyID, ...}
+        self.__playerReqJoinDict = {} # 玩家申请加入仙盟列表 {playerID:[familyID, ...], ...}
+        self.__actionMgr = FamilyActionMgr()
+        
+        # 本服数据分区管理,游戏服尚未未分区的默认使用分区0,因为只管理本服公会数据,故不用再按crossServerID区分,默认都属于本服的serverID
+        # 分区可能随时被重置重新分配,故如有需要持久化的逻辑数据需要另行处理,或在重置后复制所需持久化的数据,暂时不用,之后有需要再处理
+        self.__zoneFamilyMgrDict = {} # 分区对应公会分区管理器 {zoneID:ZoneFamilyMgr(), ...}
+        self.__familyIDZoneIDDict = {} # 公会ID对应所属分区 {familyID:zoneID, ...}
+        
+        ## ------------------------ 【所有服务器】会有的信息,由跨服中心或跨服同步 ------------------------
+        # 分区配置说明:
+        # 1. 启动时由跨服中心初步验证配置合理性,如服务器范围有交叉、拆分等,验证不通过不会通知,且邮件通知运维
+        # 2. 跨服中心验证通过后广播给所有跨服服务器,跨服服务器进一步验证是否有未分配的公会,有则验证不通过,且邮件通知运维
+        # 3. 跨服中心、跨服均验证通过后,会按配置的分区初始化各分区公会管理,然后同步给各自的分区游戏服
+        # 4. 热更分区配置时,只更新跨服中心即可,由跨服中心发起验证,同样执行流程 1~3,验证不通过的不会更新配置,保留原分区配置
+        # 5. 热更分区验证通过后,会重新生成公会分区,热更仅对不需要不改变公会数据所在服务器时有效
+        # 6. 如需改变已互通公会数据所在跨服,需停服维护先进行跨服数据合并后,重启服务器
+        # 【注】游戏服首次跨服,根据收到的互通配置进行验证是否开始跨服,开始后同步数据给所属跨服,可重复同步直到成功,否则还是保持使用本服公会数据
+        self.__crossZoneCfgDict = {} # 跨服互通分区配置 {crossServerID:{zoneID:[互通服务器ID范围列表], ...}, ...},由跨服中心同步
+        
+        ## ------------------------ 【游戏服】专有信息,一般由所属互通跨服数据服同步 ----------------------
+        # 互通公会基本信息 - 查看玩家页面需要看到的所属公会最简单的信息,一般只有游戏服用到
+        #self.__familyViewBaseDict = {} # 公会ID对应基础查看信息 {familyID:FamilyViewBase, ...}
+        self.__curZoneServerIDList = [] # 当前游戏服主服所属互通分区实际已经互通的服务器ID列表,同步给前端的
+        self.__curCrossServerID = 0 # 当前游戏服主服公会所属跨服ID
+        self.__curZoneID = 0 # 当前游戏服主服所属互通分区ID
+        ## 【不允许不同互通分区的合服】
+        return
+    
+    def InitFamilyInstance(self, dbData):
+        '''初始化功能数据实例,创建或加载数据时通用,功能一般不调用
+        @param dbData: 实例对应绑定的dbData
+        @return: 成功返回实例对象,失败返回None
+        '''
+        family = Family(dbData)
+        familyID = family.GetID()
+        if familyID in self.__familyIDDict:
+            return self.__familyIDDict[familyID]
+        self.__familyIDDict[familyID] = family
+        return family
+    
+    def AddFamily(self, familyName, serverID, familyID=None):
+        ## 创建新仙盟
+        newFamily = None
+        if not familyName or not serverID:
+            GameWorld.ErrLog("创建公会参数异常,无法创建! serverID=%s" % serverID)
+            return newFamily
+        zoneID = self.GetZoneIDInThisServer(serverID)
+        if zoneID < 0:
+            GameWorld.ErrLog("服务器ID创建的公会不属于本服管理,无法创建! serverID=%s" % serverID)
+            return newFamily
+        if familyID == None:
+            familyID = PyMongoMain.GetUserCtrlDB().GetNewFamilyID()
+            if familyID <= 0:
+                GameWorld.ErrLog("创建公会时生成新ID异常!")
+                return newFamily
+        if familyID in self.__familyIDDict:
+            GameWorld.ErrLog("创建公会时ID已存在! familyID=%s" % familyID)
+            return newFamily
+        # 名字通过分区管理验证并自动修改为不重名
+        #if familyName in self.__familyNameDict:
+        #    GameWorld.ErrLog("创建仙盟时名称已存在! familyName=%s" % familyName)
+        #    return newFamily
+        #if len(self.__familyList) >= FamilyUpperLimitCount:
+        #    GameWorld.ErrLog("单服限制创建仙盟数已达上限!")
+        #    return newFamily
+        
+        dbData = DBStruct.tagDBFamily()
+        dbData.ID = familyID
+        dbData.Name = familyName
+        dbData.ServerID = serverID
+        dbData.CreateTime = int(time.time())
+        
+        newFamily = self.InitFamilyInstance(dbData)
+        if not newFamily and False: # 不执行,为了代码提示
+            newFamily = Family()
+            
+        # 添加到所属分区
+        zoneMgr = self.GetZoneFamilyMgr(zoneID)
+        zoneMgr.AddFamilyToZone(newFamily)
+        
+        return newFamily
+    
+    def OnFightPowerChange(self, family):
+        zoneMgr = self.GetZoneFamilyMgrByFamilyID(family.GetID())
+        if not zoneMgr:
+            return
+        zoneMgr.SetSort()
+        return
+    
+    def OnAddToZone(self, family, zoneID):
+        familyID = family.GetID()
+        self.__familyIDZoneIDDict[familyID] = zoneID
+        return
+    
+    def OnAddMember(self, family, playerID):
+        self.__playerFamilyIDDict[playerID] = family.GetID()
+        return
+    
+    def OnDelMember(self, family, playerID):
+        self.__playerFamilyIDDict.pop(playerID, None)
+        return
+    
+    def GetFamilyIDList(self): return self.__familyIDDict.keys()
+    
+    def FindFamily(self, familyID):
+        family = None
+        if familyID and familyID in self.__familyIDDict:
+            family = self.__familyIDDict[familyID]
+        elif False:
+            family = Family()
+        return family
+    
+    def DelFamily(self, familyID, isFreeID=True):
+        family = self.FindFamily(familyID)
+        self.__familyIDDict.pop(familyID, None)
+        
+        # 同步从分区中删除
+        if familyID in self.__familyIDZoneIDDict:
+            zoneID = self.__familyIDZoneIDDict.get(familyID)
+            zoneMgr = self.GetZoneFamilyMgr(zoneID)
+            zoneMgr.DelZoneFamily(familyID)
+            
+        # 最后删除自身
+        if family:
+            family.OnDelete()
+        if isFreeID and familyID >= ShareDefine.RealFamilyIDStart:
+            PyMongoMain.GetUserCtrlDB().FreeFamilyID(familyID) # 归还仙盟ID,重复使用
+        return family
+    
+    def DelAllFamily(self):
+        for familyID in self.__familyIDDict.keys():
+            self.DelFamily(familyID)
+        return
     
     def GetFamilyActionMgr(self): return self.__actionMgr
     
+    def __afterLoadDBFamilyData(self):
+        self.__playerFamilyIDDict = {}
+        self.__playerReqJoinDict = {}
+        for family in self.__familyIDDict.values():
+            familyID = family.GetID()
+            family.RefrshFightPowerTotal()
+            
+            for index in range(family.GetCount()):
+                member = family.GetAt(index)
+                self.__playerFamilyIDDict[member.GetPlayerID()] = familyID
+                
+            reqPlayerIDDict = family.GetReqJoinPlayerInfo()
+            #key强制转为int,线上的是字符串,做数据兼容
+            for reqIDStr, v in reqPlayerIDDict.items():
+                reqID = int(reqIDStr)
+                reqPlayerIDDict.pop(reqIDStr, None)
+                reqPlayerIDDict[reqID] = v
+                if reqID not in self.__playerReqJoinDict:
+                    self.__playerReqJoinDict[reqID] = []
+                reqFamilyIDList = self.__playerReqJoinDict[reqID]
+                if familyID not in reqFamilyIDList:
+                    reqFamilyIDList.append(familyID)
+                    
+        return
+    
+    def GetPlayerFamilyID(self, playerID):
+        ## 获取玩家ID当前所在的公会ID
+        return self.__playerFamilyIDDict.get(playerID, 0)
+    
     def GetPlayerReqJoinFamilyIDList(self, playerID):
         ## 获取玩家申请加入的仙盟ID列表
-        if self.__playerReqJoinDict == None:
-            self.__playerReqJoinDict = {}
-            for index in xrange(self.GetCount()):
-                family = self.GetAt(index)
-                familyID = family.GetID()
-                reqPlayerIDDict = family.GetReqJoinPlayerInfo()
-                for reqID in reqPlayerIDDict.keys():
-                    if reqID not in self.__playerReqJoinDict:
-                        self.__playerReqJoinDict[reqID] = []
-                    reqFamilyIDList = self.__playerReqJoinDict[reqID]
-                    if familyID not in reqFamilyIDList:
-                        reqFamilyIDList.append(familyID)
-                        
         if playerID not in self.__playerReqJoinDict:
             self.__playerReqJoinDict[playerID] = []
         return self.__playerReqJoinDict[playerID]
@@ -596,13 +793,168 @@
             family.DelReqJoinPlayerID(playerID)
         return
     
+    def GetCrossZoneCfgDict(self): return self.__crossZoneCfgDict # {crossServerID:{zoneID:[互通服务器ID范围列表], ...}, ...}
+    def SetCrossZoneCfgDict(self, crossZoneCfgDict): self.__crossZoneCfgDict = crossZoneCfgDict # 直接设置的不做更新检测逻辑,一般游戏服用
+    def UpdCrossZoneCfgDict(self, updCrossZoneCfgDict):
+        ## 更新分区配置,重置分区,重新分配
+        ## @return: 本跨服是否成功更新分区,验证不通过的话不会重置,保留原分区
+        GameWorld.Log("跨服公会互通配置更新! updCrossZoneCfgDict=%s" % updCrossZoneCfgDict)
+        if not CheckCrossZoneCfg(self.__crossZoneCfgDict, updCrossZoneCfgDict):
+            return
+        
+        crossServerID = GameWorld.GetGameWorld().GetServerID()
+        if crossServerID not in updCrossZoneCfgDict:
+            GameWorld.Log("本跨服未分配分区的只更新配置即可!")
+            self.__crossZoneCfgDict = updCrossZoneCfgDict
+            return
+        zoneDict = updCrossZoneCfgDict[crossServerID]
+        
+        # 存在没有分配的公会,不应该处理,可能分区配置与实际数据不一致,一般发生在调整分区时,邮件通知运维
+        familyZoneDict = {}
+        noZoneServerIDList = [] # 没有所属分区的服务器ID列表
+        for family in self.__familyIDDict.values():
+            familyID = family.GetID()
+            familyServerID = family.GetServerID()
+            zoneID = 0
+            for zID, serverIDRangeList in zoneDict.items():
+                if GameWorld.CheckServerIDInList(familyServerID, serverIDRangeList):
+                    zoneID = zID
+                    break
+            if not zoneID:
+                if familyServerID not in noZoneServerIDList:
+                    noZoneServerIDList.append(familyServerID)
+            else:
+                familyZoneDict[familyID] = zoneID
+                
+        if noZoneServerIDList:
+            GameWorld.SendGameErrorEx("FamilyCrossZoneCfgError", "noZoneServerIDList=%s" % noZoneServerIDList)
+            return
+        
+        # 更新配置、重置、重新分区
+        self.__crossZoneCfgDict = updCrossZoneCfgDict
+        self.__zoneFamilyMgrDict = {}
+        self.__familyIDZoneIDDict = {}
+        zoneDict = self.__crossZoneCfgDict[crossServerID]
+        for family in self.__familyIDDict.values():
+            familyID = family.GetID()
+            zoneID = familyZoneDict.get(familyID, 0) # 理论上不可能再为0
+            zoneMgr = self.GetZoneFamilyMgr(zoneID)
+            zoneMgr.AddFamilyToZone(family)
+            
+        return True
+    
+    def __setFamilyToDefaultZone(self):
+        ## 将本服公会全部归到默认分区0,仅游戏服使用
+        self.__zoneFamilyMgrDict = {}
+        self.__familyIDZoneIDDict = {}
+        zoneID = 0
+        zoneMgr = self.GetZoneFamilyMgr(zoneID)
+        for family in self.__familyIDDict.values():
+            zoneMgr.AddFamilyToZone(family)
+        return
+    
+    def GetZoneIDInThisServer(self, serverID=None):
+        '''获取服务器ID在本公会数据服务器中所属的分区ID,
+        @return: zoneID -2-或传输数据中;-1-分区不在本服务器;0-未互通默认分区0;>0-在本服数据中所在分区ID
+        '''
+        curServerID = GameWorld.GetGameWorld().GetServerID()
+        if not serverID:
+            serverID = curServerID
+        zoneID = -1
+        serverType = GameWorld.GetServerType()
+        if serverType == ShareDefine.serverType_Main:
+            if IsFamilyCrossInTransData():
+                zoneID = -2
+            elif not IsFamilyCross():
+                zoneID = 0 # 本服未跨服互通的默认分区0
+        elif GameWorld.IsCrossServer() and curServerID in self.__crossZoneCfgDict:
+            # 跨服服务器不适用 __zoneFamilyMgr 判断是因为如果出现某个服务器ID的所有公会都被删除了,重启服务器的时候从分区管理中可能找不到该服务器ID
+            # 所以使用已验证过的互通配置即可,互通配置已经验证过合理性,可以直接用
+            zoneDict = self.__crossZoneCfgDict[curServerID]
+            for zID, serverIDRangeList in zoneDict.items():
+                if GameWorld.CheckServerIDInList(serverID, serverIDRangeList):
+                    zoneID = zID
+                    break
+        return zoneID
+    
+    def GetZoneIDListThisServer(self): return self.__zoneFamilyMgrDict.keys() # 在本服数据中已存在的分区
+    
+    def GetFamilyZoneID(self, familyID): return self.__familyIDZoneIDDict.get(familyID, -1) # -1-未找到所属分区;>=0-所属分区
+    
+    def GetZoneFamilyMgrByFamilyID(self, familyID):
+        ## 获取公会ID在本服数据所属分区管理器
+        # @return: 可能返回None - 公会数据不在本服
+        zoneID = -1
+        if familyID in self.__familyIDZoneIDDict:
+            zoneID = self.__familyIDZoneIDDict[familyID]
+        zoneMgr = None
+        if zoneID >= 0:
+            zoneMgr = self.GetZoneFamilyMgr(zoneID)
+        return zoneMgr
+    
+    def GetZoneFamilyMgr(self, zoneID=0):
+        ## 获取某个分区的公会管理器
+        # @param zoneID: 未互通的服务器默认使用0,使用方法一致
+        zoneMgr = None
+        if zoneID in self.__zoneFamilyMgrDict:
+            zoneMgr = self.__zoneFamilyMgrDict[zoneID]
+        else:
+            zoneMgr = ZoneFamilyMgr(zoneID)
+            self.__zoneFamilyMgrDict[zoneID] = zoneMgr
+        return zoneMgr
+    
+#    def GetFamilyViewBase(self, familyID):
+#        ## 互通公会基本信息,本服跨服通用,实际的公会完整数据可能不在本服
+#        vBase = None
+#        if familyID in self.__familyViewBaseDict:
+#            vBase = self.__familyViewBaseDict[familyID]
+#        else:
+#            vBase = FamilyViewBase(familyID)
+#            self.__familyViewBaseDict[familyID] = vBase
+#        vBase.SetFamily(self.FindFamily(familyID))
+#        return vBase
+    
+    def GetCurCrossServerID(self):
+        ## 游戏服获取所属的跨服互通服务器ID,一个游戏服主服只允许一个互通分区,不同分区的不能合服
+        # @return: -2-传输数据中;-1-非游戏服或没有正确的跨服ID;0-未互通;>0-互通的目标跨服ID
+        serverType = GameWorld.GetServerType()
+        if serverType != ShareDefine.serverType_Main:
+            return -1
+        
+        if IsFamilyCrossInTransData():
+            return -2
+        
+        # 未互通
+        if not IsFamilyCross():
+            return 0
+        
+        if self.__curCrossServerID:
+            return self.__curCrossServerID
+        
+        curServerID = GameWorld.GetGameWorld().GetServerID()
+        for crossServerID, zoneDict in self.__crossZoneCfgDict.items():
+            for serverIDRangeList in zoneDict.values():
+                if GameWorld.CheckServerIDInList(curServerID, serverIDRangeList):
+                    return crossServerID
+                
+        return -1
+    
+    def SetCurCrossServerID(self, curCrossServerID): self.__curCrossServerID = curCrossServerID # 直接设置的游戏服专用
+    def GetCurZoneID(self): # 本游戏服主服所属互通分区ID
+        return 0 if not IsFamilyCross() else self.__curZoneID
+    def SetCurZoneID(self, curZoneID): self.__curZoneID = curZoneID # 直接设置的游戏服专用
+    def GetCurZoneServerIDList(self): return self.__curZoneServerIDList # 本游戏服主服实际已互通的服务器ID列表
+    def SetCurZoneServerIDList(self, curZoneServerIDList): self.__curZoneServerIDList = curZoneServerIDList # 直接设置的游戏服专用
+    
     # 保存数据 存数据库和realtimebackup
-    def GetSaveData(self):
+    def GetSaveData(self, cntDict=None):
         
         familyDataCnt, familySavaData = 0, ""
         membreDataCnt, memberSavaData = 0, ""
         actionDataCnt, actionSavaData = 0, ""
-        for family in self.__familyList:
+        
+        for family in self.__familyIDDict.values():
+            
             familyID = family.GetID()
             familySavaData += family.GetBuffer()
             familyDataCnt += 1
@@ -629,20 +981,20 @@
         
         saveData += CommFunc.WriteDWORD("", actionDataCnt) + actionSavaData
         GameWorld.Log("Save DBFamilyAction count :%s len=%s" % (actionDataCnt, len(actionSavaData)))
-        
+        if isinstance(cntDict, dict):
+            cntDict.update({"familyDataCnt":familyDataCnt, "membreDataCnt":membreDataCnt, "actionDataCnt":actionDataCnt})
         return saveData
     
     # 从数据库载入数据
-    def LoadPyGameData(self, datas, pos, dataslen):        
-        # 仙盟
+    def LoadPyGameData(self, datas, pos, dataslen):
+        # 公会
         cnt, pos = CommFunc.ReadDWORD(datas, pos)
         GameWorld.Log("Load DBFamily count :%s" % cnt)
         for _ in xrange(cnt):
             dbData = DBStruct.tagDBFamily()
             pos += dbData.readData(datas, pos, dataslen)
             self.InitFamilyInstance(dbData)
-        self.Sort()
-        
+            
         # 成员
         cnt, pos = CommFunc.ReadDWORD(datas, pos)
         GameWorld.Log("Load DBFamilyMem count :%s" % cnt)
@@ -665,29 +1017,425 @@
             
             familyID = dbData.FamilyID
             actionType = dbData.ActionType
+            
             family = self.FindFamily(familyID)
             if not family:
                 continue
             action = self.__actionMgr.GetFamilyAction(familyID, actionType)
             action.InitActionInstance(dbData)
             
+        self.__afterLoadDBFamilyData()
+        
         PyMongoMain.GetUserCtrlDB().OnFamilyIDInit(self.__familyIDDict.keys())
+        
+        serverType = GameWorld.GetServerType()
+        if serverType == ShareDefine.serverType_CrossCenter:
+            self.UpdCrossZoneCfgDict(LoadZoneCfg())
+        elif serverType == ShareDefine.serverType_Main:
+            self.__setFamilyToDefaultZone() # 游戏服本服的数据无论有没有跨服了都同意设置到默认分区
         return pos
     
-def OnMinute():
-    
-    familyMgr = DBDataMgr.GetFamilyMgr()
-    # 每分钟刷新下仙盟战力排序
-    isSort = False
-    for index in range(familyMgr.GetCount()):
-        family = familyMgr.GetAt(index)
-        if not family:
+def LoadZoneCfg(self):
+    crossZoneCfgDict = {}
+    appID = GameWorld.GetAppID()
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetFamilyCrossCount()):
+        ipyData = ipyDataMgr.GetFamilyCrossByIndex(index)
+        if ipyData.GetAppID() != appID:
             continue
-        if family.RefrshFightPowerTotal(True):
-            isSort = True
-    if isSort:
-        familyMgr.Sort()
+        crossServerID = ipyData.GetCrossServerID()
+        zoneID = ipyData.GetZoneID()
+        if crossServerID not in crossZoneCfgDict:
+            crossZoneCfgDict[crossServerID] = {}
+        zoneDict = crossZoneCfgDict[crossServerID]
+        zoneDict[zoneID] = [] + ipyData.GetServerIDList()
+    return crossZoneCfgDict
+
+def CheckCrossZoneCfg(curCrossZoneCfgDict, updCrossZoneCfgDict):
+    # 检查待更新的分区配置是否符合规则,不符合的话保留原配置,不更新,待扩展
+    
+    if curCrossZoneCfgDict == updCrossZoneCfgDict:
+        GameWorld.Log("跨服公会互通分区配置不变不处理")
+        return
+    
+    # 验证配置,是否有交叉、拆分,并邮件通知运维,待扩展,先开发功能
+    #GameWorld.SendGameErrorEx("FamilyCrossZoneCfgError", "noZoneServerIDList=%s" % noZoneServerIDList)
+    
+    return True
+
+def OnReloadConfig():
+    '''重读配置验证修改后的配置是否符合规定,不符合的话,还是使用旧配置的范围,并邮件通知运维
+    公会分区配置同步规则: 由跨服中心加载配置  -> 验证通过后发给所有跨服 -> 跨服验证通过后发给所管辖的分区所有游戏服务器
+    '''
+    
+    if GameWorld.IsCrossCenter():
+        crossZoneCfgDict = LoadZoneCfg()
+        if not crossZoneCfgDict or not DBDataMgr.GetFamilyMgr().UpdCrossZoneCfgDict(crossZoneCfgDict):
+            return
+        Sync_CenterToCross_FamilyCrossCfg()
         
     return
 
+def Sync_CenterToCross_FamilyInfo(serverType, serverID):
+    ## 跨服中心同步给跨服服务器
+    if serverType == ShareDefine.serverType_Cross:
+        Sync_CenterToCross_FamilyCrossCfg(serverID)
+    return
+
+def Sync_CenterToCross_FamilyCrossCfg(serverID=0):
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    crossZoneCfgDict = familyMgr.GetCrossZoneCfgDict()
+    if not crossZoneCfgDict:
+        GameWorld.Log("没有公会互通配置或没有验证正确的互通分区配置不通知!")
+        return
+    dataMsg = {"crossZoneCfgDict":crossZoneCfgDict}
+    serverIDList = [serverID] if serverID else crossZoneCfgDict.keys()
+    CrossMsg.SendToServer(ShareDefine.CC2C_FamilyCrossCfg, dataMsg, serverIDList, ShareDefine.dirType_Cross)
+    return
+
+def CC2C_FamilyCrossCfg(dataMsg, fromServerID, serverType):
+    # 跨服中心同步的分区配置,仅跨服服务器处理即可,游戏服以所属跨服处理后的最终数据为准
+    if serverType != ShareDefine.serverType_CrossCenter:
+        return
+    updCrossZoneCfgDict = dataMsg["crossZoneCfgDict"]
+    
+    if not updCrossZoneCfgDict:
+        return
+    
+    if GameWorld.GetServerType() != ShareDefine.serverType_Cross:
+        return
+    
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    if not familyMgr.UpdCrossZoneCfgDict(updCrossZoneCfgDict):
+        return
+    Sync_CrossToServer_FamilyInfo()
+    return
+
+def Sync_CrossToServer_FamilyInfo(toServerID=0, syncZoneID=0, syncFamilyIDList=[]):
+    ## 跨服服务器同步互通公会信息给游戏服
+    # @param toServerID: 有指定游戏服连上时只发给该服,没有的话一般是分区配置变更时由跨服主动同步所有相关游戏服
+    
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    crossZoneCfgDict = familyMgr.GetCrossZoneCfgDict() # 配置的互通
+    if not crossZoneCfgDict:
+        return
+    crossServerID = GameWorld.GetGameWorld().GetServerID()
+    if crossServerID not in crossZoneCfgDict:
+        return
+    zoneCfgDict = crossZoneCfgDict[crossServerID]
+    
+    for zoneID in familyMgr.GetZoneIDListThisServer():
+        if syncZoneID and syncZoneID != zoneID:
+            continue
+        if zoneID not in zoneCfgDict:
+            continue
+        cfgServerIDList = zoneCfgDict[zoneID] # 配置需要互通的服务器信息,需要同步给这些服务器
+        
+        if toServerID:
+            if not GameWorld.CheckServerIDInList(toServerID, cfgServerIDList):
+                # 非指定目标服务器所属分区不同步
+                continue
+            toServerIDList = [toServerID]
+        else:
+            toServerIDList = cfgServerIDList
+            
+        zoneMgr = familyMgr.GetZoneFamilyMgr(zoneID)
+        zoneServerIDList = zoneMgr.GetZoneServerIDList()
+        
+#        viewBaseDict = {}
+#        for index in range(zoneMgr.GetCount()):
+#            family = zoneMgr.GetAt(index)
+#            familyID = family.GetID()
+#            if syncFamilyIDList and familyID not in syncFamilyIDList:
+#                continue
+#            viewBase = familyMgr.GetFamilyViewBase(familyID)
+#            viewBaseDict[familyID] = viewBase.GetSyncData()
+            
+        # 只通知给已经互通的相关服务器即可
+        # 关于查看玩家
+        # 1. 查看玩家直接到玩家所在服务器查询即可,查看玩家需要公会的一些基本信息,如 公会名、徽章、旗帜、互通跨服ID 等
+        # 2. 玩家/查看玩家信息只需记录所属公会ID即可,公会相关基础信息通过 FamilyViewBase 获取,由互通所在跨服同步过来
+        
+        # 关于查看公会
+        # 1. 从查看玩家中查看公会,发送公会ID、所属互通跨服ID,直接去目标服务器查询即可
+        # 2. 从跨服活动中查看公会,活动相关公会记录所属互通跨服ID,同样直接去目标服务器查询即可
+        
+        dataMsg = {"crossZoneCfgDict":crossZoneCfgDict, "zoneID":zoneID, "zoneServerIDList":zoneServerIDList}
+        CrossMsg.SendToClientServer(ShareDefine.C2S_FamilyCrossInfo, dataMsg, toServerIDList)
+        
+    return
+
+def C2S_FamilyCrossInfo(dataMsg, fromServerID):
+    ## 游戏服收到互通跨服同步的公会互通信息,按分区同步
+    
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    familyMgr.SetCurCrossServerID(fromServerID) # 直接设置,哪个服同步过来的就是所属跨服ID
+    familyMgr.SetCurZoneID(dataMsg["zoneID"])
+    
+#    ## 本服更新跨服互通公会的基本信息
+#    if "viewBaseDict" in dataMsg:
+#        viewBaseDict = dataMsg["viewBaseDict"]
+#        for familyID, syncData in viewBaseDict.items():
+#            viewBase = familyMgr.GetFamilyViewBase(familyID)
+#            viewBase.UpdSyncData(syncData)
+            
+    # 互通配置
+    if "crossZoneCfgDict" in dataMsg:
+        # 游戏服不用验证了,直接设置,跨服中心、跟跨服数据服已经验证过了,只要验证互通条件传输数据逻辑即可
+        familyMgr.SetCrossZoneCfgDict(dataMsg["crossZoneCfgDict"])
+        CheckCrossFamilyTransData(fromServerID)
+        
+    # 实际已互通分区
+    if "zoneServerIDList" in dataMsg:
+        curZoneServerIDList = familyMgr.GetCurZoneServerIDList()
+        updZoneServerIDList = dataMsg["zoneServerIDList"]
+        familyMgr.SetCurZoneServerIDList(updZoneServerIDList)
+        if curZoneServerIDList != updZoneServerIDList:
+            Sync_FamilyCrossInfo()
+            
+    return
+
+def IsFamilyCross():
+    ## 本服公会是否已跨服
+    return DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_FamilyCrossState) == 1
+
+def IsFamilyCrossInTransData():
+    ## 本服公会首次跨服互通同步数据中
+    return DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_FamilyTransDataTime) > 0
+
+def CheckCrossFamilyTransData(connServerID=0, ignoreCD=False):
+    ## 检查跨服公会传输数据,服务器启动时、onday时检查,或GM等指定强制调用
+    
+    if IsFamilyCross():
+        GameWorld.DebugLog("本服公会已经跨服了!")
+        return
+    
+    NeedServerDay = IpyGameDataPY.GetFuncCfg("FamilyCross", 1)
+    serverDay = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_ServerDay) + 1
+    if serverDay < NeedServerDay:
+        GameWorld.DebugLog("本服公会互通所需开服天不足! serverDay=%s < %s" % (serverDay, NeedServerDay))
+        return
+    
+    # 如果合服也以主服为准,所有合服的服务器要求本身必须也已经是跨服公会的才能合服
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    crossZoneCfgDict = familyMgr.GetCrossZoneCfgDict()
+    
+    crossServerID = 0
+    serverID = GameWorld.GetGameWorld().GetServerID()
+    for cID, zoneDict in crossZoneCfgDict.items():
+        for zoneID, serverIDRangeList in zoneDict.items():
+            if GameWorld.CheckServerIDInList(serverID, serverIDRangeList):
+                crossServerID = cID
+                GameWorld.Log("本服公会所属跨服ID! serverID=%s,crossServerID=%s,zoneID=%s,serverIDRangeList=%s" % (serverID, crossServerID, zoneID, serverIDRangeList))
+                break
+        if crossServerID:
+            break
+    if not crossServerID:
+        GameWorld.Log("本服公会未分配互通分区! serverID=%s" % (serverID))
+        return
+    
+    if connServerID:
+        if connServerID != crossServerID:
+            GameWorld.Log("本服公会互通非目标跨服ID不处理! serverID=%s,crossServerID=%s != %s" % (serverID, crossServerID, connServerID))
+            return
+    else:
+        ssServer = CrossMgr.GetSSServerMgr().GetSSServer(crossServerID)
+        connState = ssServer.GetConnState()
+        if connState != ShareDefine.ssConn_Normal:
+            GameWorld.Log("本服公会互通目标跨服ID非连接状态! serverID=%s,crossServerID=%s,connState=%s" % (serverID, crossServerID, connState))
+            return
+        
+    transDataTime = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_FamilyTransDataTime)
+    if transDataTime and not ignoreCD:
+        curTime = int(time.time())
+        if curTime - transDataTime < 30 * 60: # 30分钟内不重复传输
+            GameWorld.Log("本服公会互通传输数据中! serverID=%s,crossServerID=%s,transDataTime=%s" % (serverID, crossServerID, GameWorld.ChangeTimeNumToStr(transDataTime)))
+            return
+        
+    GameWorld.Log("本服公会开启互通开始传输公会相关数据! serverID=%s,crossServerID=%s" % (serverID, crossServerID))
+    DBDataMgr.GetEventTrigMgr().SetValue(ShareDefine.Def_FamilyTransDataTime, int(time.time()))
+    
+    cntDict = {}
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    syncData = familyMgr.GetSaveData(cntDict)
+    familyIDList = familyMgr.GetFamilyIDList()
+    
+    CrossMsg.SendToCrossServer(ShareDefine.S2C_FamilyData, {"syncData":syncData, "familyIDList":familyIDList, "cntDict":cntDict}, [crossServerID])
+    return
+
+def S2C_FamilyData(dataMsg, fromServerID):
+    syncData = dataMsg["syncData"]
+    familyIDList = dataMsg["familyIDList"]
+    cntDict = dataMsg["cntDict"]
+    GameWorld.Log("收到游戏服同步的互通公会数据! fromServerID=%s,cntDict=%s,familyIDList=%s" % (fromServerID, cntDict, familyIDList))
+    
+    unpackRet = __unpackFamilyData(syncData, familyIDList, cntDict)
+    if not unpackRet:
+        errorMsg = "unknown"
+    else:
+        errorMsg = unpackRet[0]
+    if errorMsg:
+        GameWorld.SendGameErrorEx("S2C_FamilyDataError", "互通公会数据同步失败! fromServerID=%s,errorMsg=%s" % (fromServerID, errorMsg))
+        CrossMsg.SendToClientServer(ShareDefine.C2S_FamilyDataRet, {"isOK":False}, [fromServerID])
+        return
+    zoneID, familyDataList, memberDataList, actionDataList = unpackRet[1:]
+    
+    # 插入新数据,重名的会在加入分区后自动改名
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    zoneMgr = familyMgr.GetZoneFamilyMgr(zoneID)
+    actionMgr = familyMgr.GetFamilyActionMgr()
+    
+    syncFamilyIDList = []
+    for dbData in familyDataList:
+        dbData = DBStruct.tagDBFamily()
+        familyID = dbData.ID
+        familyMgr.DelFamily(familyID, False) # 每次都强制先删除,支持重复同步
+        zoneMgr.AddFamilyToZone(familyMgr.InitFamilyInstance(dbData))
+        syncFamilyIDList.append(familyID)
+        
+    # 成员
+    for dbData in memberDataList:
+        familyID = dbData.FamilyID
+        family = familyMgr.FindFamily(familyID)
+        if not family:
+            continue
+        family.InitMemberInstance(dbData)
+        
+    # 行为
+    for dbData in actionDataList:
+        familyID = dbData.FamilyID
+        
+        familyID = dbData.FamilyID
+        actionType = dbData.ActionType
+        
+        family = familyMgr.FindFamily(familyID)
+        if not family:
+            continue
+        action = actionMgr.GetFamilyAction(familyID, actionType)
+        action.InitActionInstance(dbData)
+        
+    # 同步给相同互通分区的服务器
+    Sync_CrossToServer_FamilyInfo(syncZoneID=zoneID, syncFamilyIDList=syncFamilyIDList)
+    
+    # 最后回复同步结果
+    CrossMsg.SendToClientServer(ShareDefine.C2S_FamilyDataRet, {"isOK":True}, [fromServerID])
+    return
+
+def __unpackFamilyData(syncData, familyIDList, cntDict):
+    ## 解包,验证数据
+    # @param cntDict: {"familyDataCnt":familyDataCnt, "membreDataCnt":membreDataCnt, "actionDataCnt":actionDataCnt}
+    
+    errorMsg = ""
+    datas, pos, dataslen = syncData, 0, len(syncData)
+    
+    zoneIDDict = {}
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    
+    # 公会
+    familyDataList = []
+    cnt, pos = CommFunc.ReadDWORD(datas, pos)
+    GameWorld.Log("Read DBFamily count :%s" % cnt)
+    for _ in xrange(cnt):
+        dbData = DBStruct.tagDBFamily()
+        pos += dbData.readData(datas, pos, dataslen)
+        familyDataList.append(dbData)
+        familyID = dbData.ID
+        if familyID not in familyIDList:
+            errorMsg = "同步的数据公会ID不匹配! familyID=%s not in %s" % (familyID, familyIDList)
+            return errorMsg
+        
+        familyServerID = dbData.ServerID
+        zoneID = familyMgr.GetZoneIDInThisServer(familyServerID)
+        if zoneID <= 0:
+            errorMsg = "同步的公会数据不属于本跨服! familyID=%s,familyServerID=%s,zoneID=%s" % (familyID, familyServerID, zoneID)
+            return errorMsg
+        zoneIDDict[zoneID] = familyServerID
+        
+    if len(zoneIDDict) != 1:
+        errorMsg = "同步的公会数据分区异常可能存在多个分区! zoneIDDict=%s" % zoneIDDict
+        return errorMsg
+    zoneID = zoneIDDict.keys()[0]
+    
+    uppackFamilyCnt = len(familyDataList)
+    familyDataCnt = cntDict.get("familyDataCnt", 0)
+    if uppackFamilyCnt != familyDataCnt:
+        errorMsg = "同步的公会个数不匹配! uppackFamilyCnt=%s != %s" % (uppackFamilyCnt, familyDataCnt)
+        return errorMsg
+    
+    # 成员
+    memberDataList = []
+    cnt, pos = CommFunc.ReadDWORD(datas, pos)
+    GameWorld.Log("Read DBFamilyMem count :%s" % cnt)
+    for _ in xrange(cnt):
+        dbData = DBStruct.tagDBFamilyMem()
+        pos += dbData.readData(datas, pos, dataslen)
+        memberDataList.append(dbData)
+        
+    uppackMemberCnt = len(memberDataList)
+    membreDataCnt = cntDict.get("membreDataCnt", 0)
+    if uppackMemberCnt != membreDataCnt:
+        errorMsg = "同步的成员个数不匹配! uppackMemberCnt=%s != %s" % (uppackMemberCnt, membreDataCnt)
+        return errorMsg
+    
+    # 行为
+    actionDataList = []
+    cnt, pos = CommFunc.ReadDWORD(datas, pos)
+    GameWorld.Log("Read DBFamilyAction count :%s" % cnt)
+    for _ in xrange(cnt):
+        dbData = DBStruct.tagDBFamilyAction()
+        pos += dbData.readData(datas, pos, dataslen)
+        actionDataList.append(dbData)
+        
+    uppackActionCnt = len(actionDataList)
+    actionDataCnt = cntDict.get("actionDataCnt", 0)
+    if uppackMemberCnt != membreDataCnt:
+        errorMsg = "同步的行为个数不匹配! uppackActionCnt=%s != %s" % (uppackActionCnt, actionDataCnt)
+        return errorMsg
+    
+    return errorMsg, zoneID, familyDataList, memberDataList, actionDataList
+
+def C2S_FamilyDataRet(dataMsg, fromServerID):
+    isOK = dataMsg["isOK"]
+    GameWorld.Log("收到互通公会数据同步结果! fromServerID=%s,isOK=%s" % (fromServerID, isOK))
+    # 重置传输数据状态
+    DBDataMgr.GetEventTrigMgr().SetValue(ShareDefine.Def_FamilyTransDataTime, 0)        
+    if not isOK:
+        # 失败,暂时还是使用本服公会,等Onday再触发,或排查问题后维护,后续再优化多次同步方案
+        # 运维邮件已在跨服发送,不服可不处理
+        return
+    
+    GameWorld.Log("互通公会数据同步成功,本服正式开启跨服公会互通! fromServerID=%s" % (fromServerID))
+    DBDataMgr.GetEventTrigMgr().SetValue(ShareDefine.Def_FamilyCrossState, 1)
+    ChPlayer.SyncOnlinePlayerToCross(fromServerID)        
+    return
+
+def OnMinute():
+    
+    if GameWorld.IsMainServer():
+        if IsFamilyCross():
+            # 游戏服公会已跨服不处理
+            return
+        
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    # 每分钟刷新下仙盟战力排序
+    for zoneID in familyMgr.GetZoneIDListThisServer():
+        zoneMgr = familyMgr.GetZoneFamilyMgr(zoneID)
+        zoneMgr.Sort(True)
+        
+    return
+
+def Sync_FamilyCrossInfo(curPlayer=None):
+    ## 同步本服公会互通信息
+    if not IsFamilyCross():
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    clientPack = ChPyNetSendPack.tagSCFamilyCrossInfo()
+    clientPack.ZoneID = familyMgr.GetCurZoneID()
+    clientPack.ServerIDList = familyMgr.GetCurZoneServerIDList()
+    clientPack.ServerCnt = len(clientPack.ServerIDList)
+    if curPlayer:
+        NetPackCommon.SendFakePack(curPlayer, clientPack)
+    else:
+        NetPackCommon.SendFackPackOnline(clientPack)
+    return
     
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventShell.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventShell.py
index e3a59b7..716838c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventShell.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventShell.py
@@ -97,6 +97,8 @@
 #@return 返回值无意义
 #@remarks C++触发封包重读所有事件
 def ReloadEvent(tick):
+    GameWorld.__ReloadScript() # 只调用一次,与后台重读脚本一致
+    
     scriptPath = ChConfig.GetAppPath() + "Script\\Event\\EventSrc"
     GameWorld.ReloadScript(scriptPath, "EventSrc")
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py
index 4ccd120..d5cecfa 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/EventReport.py
@@ -105,12 +105,8 @@
         playerInfo = "&%s" % urllib.urlencode(playerInfo) #UTF8 需要转成url编码才可用
         
     else:
-        # 合服情况,玩家取自己服发送,非玩家数据按指定平台配置发
-        sid = GameWorld.GetPlayerMainServerID(OperatorID)
-        if not sid:
-            GameWorld.ErrLog("GetPlayerMainServerID: %s-%s"%(OperatorID, sid))
-            return
-        RegionName = 's%s'%sid
+        serverID = GameWorld.GetGameWorld().GetServerID()
+        RegionName = 's%s'%serverID
 
     if eventParam:
         eventParam = "&%s"%eventParam
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
index bf69db3..087b9c0 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
@@ -4,12 +4,12 @@
 #
 ##@package GM.Commands.CreateFamily
 #
-# @todo:创建假仙盟
+# @todo:创建假公会
 # @author hxp
 # @date 2025-05-09
 # @version 1.0
 #
-# 详细描述: 创建假仙盟
+# 详细描述: 创建假公会
 #
 #-------------------------------------------------------------------------------
 #"""Version = 2025-05-09 12:20"""
@@ -20,31 +20,41 @@
 import PlayerViewCache
 import IPY_PlayerDefine
 import PlayerFamily
+import CrossPlayer
 import DBDataMgr
 import random
 
-## 执行逻辑
-#  @param curPlayer 当前玩家
-#  @param gmList []
-#  @return None
+def GetGMServerIDList(curPlayer):
+    ## 获取命令额外发送到其他服务器,如跨服
+    crossServerID = DBDataMgr.GetFamilyMgr().GetCurCrossServerID()
+    #GameWorld.DebugAnswer(curPlayer, "GetGMServerIDList: %s" % crossServerID)
+    if crossServerID:
+        return [crossServerID]
+    return []
+
+def OnExecCross(crossPlayer, gmList):
+    ## 跨服执行命令
+    GameWorld.DebugLog("OnExecCross %s" % gmList, crossPlayer.GetPlayerID())
+    return
+
 def OnExec(curPlayer, gmList):
+    ## 游戏服执行命令
     
     if not gmList:
-        #GameWorld.DebugAnswer(curPlayer, "创建跨服假仙盟: CreatFamily c 个数 [总战力 ServerID 等级 成员数]")
-        #GameWorld.DebugAnswer(curPlayer, "删除跨服假仙盟: CreatFamily c 0")
-        GameWorld.DebugAnswer(curPlayer, "建本服假仙盟: CreatFamily 个数 [总战力 ServerID 等级 成员数  是否审核 官职限制]")
-        GameWorld.DebugAnswer(curPlayer, "删本服假仙盟: CreatFamily 0")
-        GameWorld.DebugAnswer(curPlayer, "输出仙盟列表: CreatFamily pl [条数 从第x名]")
-        GameWorld.DebugAnswer(curPlayer, "输出仙盟明细: CreatFamily pf 仙盟ID")
-        GameWorld.DebugAnswer(curPlayer, "添加假申请人: CreatFamily j [申请数 仙盟ID]")
-        GameWorld.DebugAnswer(curPlayer, "添加本盟成员: CreatFamily m 人数 [仙盟ID]")
+        GameWorld.DebugAnswer(curPlayer, "创建假人公会: CreatFamily 个数 [总战力 ServerID 等级 成员数  是否审核 官职限制]")
+        GameWorld.DebugAnswer(curPlayer, "删除假人公会: CreatFamily 0")
+        GameWorld.DebugAnswer(curPlayer, "输出公会列表: CreatFamily pl [条数 从第x名]")
+        GameWorld.DebugAnswer(curPlayer, "输出公会明细: CreatFamily pf 公会ID")
+        GameWorld.DebugAnswer(curPlayer, "添加假申请人: CreatFamily sq [申请数 公会ID]")
+        GameWorld.DebugAnswer(curPlayer, "添加公会成员: CreatFamily m 人数 [公会ID]")
+        return
+    
+    crossPlayer = CrossPlayer.GetCrossPlayerMgr().FindCrossPlayer(curPlayer.GetPlayerID())
+    if not crossPlayer:
+        #GameWorld.DebugAnswer(curPlayer, "找不到crossPlayer")
         return
     
     value1 = gmList[0]
-    if value1 == "c":
-        # 跨服命令
-        return
-    
     if value1 == "pl":
         __printFamilyList(curPlayer, gmList)
         return
@@ -53,12 +63,12 @@
         __printFamilyInfo(curPlayer, gmList)
         return
     
-    if value1 == "j":
+    if value1 == "sq":
         __addFackRequestJoin(curPlayer, gmList)
         return
     
     if value1 == "m":
-        __addFackMember(curPlayer, gmList)
+        __addFackMember(curPlayer, gmList, crossPlayer)
         return
     
     creatCount = value1
@@ -68,14 +78,14 @@
     __createFackFamily(curPlayer, gmList)
     return
 
-def __addFackMember(curPlayer, gmList):
+def __addFackMember(curPlayer, gmList, crossPlayer):
     memCnt = gmList[1] if len(gmList) > 1 else 1
     familyID = gmList[2] if len(gmList) > 2 else curPlayer.GetFamilyID()
     
     familyMgr = DBDataMgr.GetFamilyMgr()
     curFamily = familyMgr.FindFamily(familyID)
     if not curFamily:
-        GameWorld.DebugAnswer(curPlayer, "没有该仙盟: %s" % familyID)
+        GameWorld.DebugAnswer(curPlayer, "没有该公会: %s" % familyID)
         return
     
     MemberMax = PlayerFamily.GetFamilySetting(curFamily.GetLV(), "MemberMax")
@@ -84,15 +94,21 @@
         return
     memCnt = min(memCnt, MemberMax - curFamily.GetCount())
     
+    curZoneMgr = familyMgr.GetZoneFamilyMgrByFamilyID(familyID)
+    if not curZoneMgr:
+        return
+    
     fackIDStart = 0
-    for i in range(0, familyMgr.GetCount()):
-        family = familyMgr.GetAt(i)
-        for index in xrange(family.GetCount()):
-            member = family.GetAt(index)
-            memID = member.GetPlayerID()
-            if memID > ShareDefine.FackPlayerIDMax:
-                continue
-            fackIDStart = max(memID, fackIDStart)
+    for zoneID in familyMgr.GetZoneIDListThisServer():
+        zoneMgr = familyMgr.GetZoneFamilyMgr(zoneID)
+        for i in range(0, zoneMgr.GetCount()):
+            family = zoneMgr.GetAt(i)
+            for index in xrange(family.GetCount()):
+                member = family.GetAt(index)
+                memID = member.GetPlayerID()
+                if memID > ShareDefine.FackPlayerIDMax:
+                    continue
+                fackIDStart = max(memID, fackIDStart)
             
     addCnt = 0
     for i in range(memCnt):
@@ -102,8 +118,8 @@
         PlayerFamily.DoPlayerJionFamily(curFamily, fackID, None, broadcastFamilyChange=False)
         addCnt += 1
         
-    familyMgr.Sort()
-    PlayerFamily.Sync_FamilyInfo(curPlayer)
+    curZoneMgr.Sort()
+    PlayerFamily.Sync_FamilyInfo(crossPlayer)
     GameWorld.DebugAnswer(curPlayer, "增加成员数:%s, 总成员:%s" % (addCnt, curFamily.GetCount()))
     return
 
@@ -114,7 +130,7 @@
     familyMgr = DBDataMgr.GetFamilyMgr()
     family = familyMgr.FindFamily(familyID)
     if not family:
-        GameWorld.DebugAnswer(curPlayer, "没有该仙盟: %s" % familyID)
+        GameWorld.DebugAnswer(curPlayer, "没有该公会: %s" % familyID)
         return
     
     reqCnt = min(reqCnt, 100)
@@ -125,37 +141,41 @@
     for fackID in fackIDList:
         if fackID in reqDict:
             continue
+        if familyMgr.GetPlayerFamilyID(fackID):
+            continue
         family.AddReqJoinPlayerID(fackID)
         addCnt += 1
         if addCnt >= reqCnt:
             break
     # 广播给有招人权限的
-    clientPack = PlayerFamily.GetPack_FamilyReqJoinInfo(familyID)
-    PlayerFamily.Broadcast_FamilyPack(familyID, clientPack, PlayerFamily.FamilyPowerID_Call)
+    PlayerFamily.SendFamilyReqJoinInfo(familyID)
     GameWorld.DebugAnswer(curPlayer, "增加申请数:%s, 总申请:%s" % (addCnt, len(family.GetReqJoinPlayerInfo())))
     return
 
 def __printFamilyList(curPlayer, gmList):
-    printCnt = gmList[1] if len(gmList) > 1 else 100
+    printCnt = gmList[1] if len(gmList) > 1 else 20
     fromIndex = gmList[2] if len(gmList) > 2 else 0
     
     printAnswerCnt = 0
     familyMgr = DBDataMgr.GetFamilyMgr()
-    familyMgr.Sort()
-    familyCnt = familyMgr.GetCount()
-    GameWorld.DebugAnswer(curPlayer, "----- 仙盟总数: %s -----" % (familyCnt))
-    for index in range(fromIndex, fromIndex + printCnt):
-        if index >= familyCnt:
-            break
-        family = familyMgr.GetAt(index)
-        rank = index + 1
-        
-        text = "%s,ID:%s,LV:%s,战:%s,成:%s,审:%s,官:%s" % (rank, family.GetID(), family.GetLV(), family.GetFightPowerTotal(), family.GetCount(), family.GetJoinReview(), family.GetJoinLVMin())
-        printAnswerCnt += 1
-        if printAnswerCnt <= 100:
-            GameWorld.DebugAnswer(curPlayer, text)
-        else:
-            GameWorld.DebugLog(text)
+    zoneIDList = familyMgr.GetZoneIDListThisServer()
+    for zoneID in zoneIDList:
+        zoneMgr = familyMgr.GetZoneFamilyMgr(zoneID)
+        zoneMgr.Sort()
+        familyCnt = zoneMgr.GetCount()
+        GameWorld.DebugAnswer(curPlayer, "----- 【分区%s】公会总数: %s -----" % (zoneID, familyCnt))
+        for index in range(fromIndex, fromIndex + printCnt):
+            if index >= familyCnt:
+                break
+            family = zoneMgr.GetAt(index)
+            rank = index + 1
+            
+            text = "%s,ID:%s,LV:%s,战:%s,成:%s,审:%s,官:%s" % (rank, family.GetID(), family.GetLV(), family.GetFightPowerTotal(), family.GetCount(), family.GetJoinReview(), family.GetJoinLVMin())
+            printAnswerCnt += 1
+            if printAnswerCnt <= 100:
+                GameWorld.DebugAnswer(curPlayer, text)
+            else:
+                GameWorld.DebugLog(text)
             
     return
 
@@ -165,11 +185,12 @@
     familyMgr = DBDataMgr.GetFamilyMgr()
     family = familyMgr.FindFamily(familyID)
     if not family:
-        GameWorld.DebugAnswer(curPlayer, "仙盟不存在: %s" % familyID)
+        GameWorld.DebugAnswer(curPlayer, "公会不存在: %s" % familyID)
         return
     
+    zoneID = familyMgr.GetFamilyZoneID(familyID)
     GameWorld.DebugAnswer(curPlayer, "----- 【%s】 -----" % (GameWorld.CodeToGbk(family.GetName())))
-    GameWorld.DebugAnswer(curPlayer, "仙盟ID:%s, ServerID:%s" % (familyID, family.GetServerID()))
+    GameWorld.DebugAnswer(curPlayer, "公会ID:%s, ServerID:%s, 分区:%s" % (familyID, family.GetServerID(), zoneID))
     GameWorld.DebugAnswer(curPlayer, "LV:%s, Exp:%s" % (family.GetLV(), family.GetExp()))
     GameWorld.DebugAnswer(curPlayer, "审核:%s, 官职条件:%s, 申请数:%s" % (family.GetJoinReview(), family.GetJoinLVMin(), len(family.GetReqJoinPlayerInfo())))
     GameWorld.DebugAnswer(curPlayer, "战旗:%s, 旗号【%s】" % (family.GetEmblemID(), GameWorld.CodeToGbk(family.GetEmblemWord())))
@@ -187,17 +208,14 @@
     
     delCnt = 0
     familyMgr = DBDataMgr.GetFamilyMgr()
-    for index in range(familyMgr.GetCount())[::-1]:
-        family = familyMgr.GetAt(index)
-        familyID = family.GetID()
+    for familyID in familyMgr.GetFamilyIDList():
         if familyID > ShareDefine.FackFamilyIDMax:
             continue
-        familyMgr.DelFamily(family.GetID())
+        delCnt += 1
+        familyMgr.DelFamily(familyID)
         
-    if curPlayer:
-        GameWorld.DebugAnswer(curPlayer, "删除假仙盟数: %s,剩余:%s" % (delCnt, familyMgr.GetCount()))
-    elif GameWorld.IsCrossServer():
-        GameWorld.DebugAnswer(None, "删除跨服假仙盟: %s,剩余:%s" % (delCnt, familyMgr.GetCount()))
+    remainCnt = len(familyMgr.GetFamilyIDList())
+    GameWorld.DebugAnswer(curPlayer, "删除假公会数: %s,剩余:%s" % (delCnt, remainCnt))
     return
 
 def __createFackFamily(curPlayer, gmList):
@@ -205,7 +223,7 @@
     
     creatCount = gmList[0] if len(gmList) > 0 else 1 # 默认1个
     familyFightPower = gmList[1] if len(gmList) > 1 else 10000000
-    serverID = gmList[2] if len(gmList) > 2 else random.randint(1, 200)
+    serverID = gmList[2] if len(gmList) > 2 else GameWorld.GetGameWorld().GetServerID() #random.randint(1, 200)
     familyLV = gmList[3] if len(gmList) > 3 else 1 # 默认1级
     memberCnt = gmList[4] if len(gmList) > 4 else random.randint(1, 10)
     joinReview = gmList[5] if len(gmList) > 5 else 1
@@ -248,7 +266,7 @@
         fackFamily.SetJoinReview(joinReview) # 设置需要审核
         fackFamily.SetJoinLVMin(joinLVMin) # 官职
         
-        GameWorld.DebugLog("创建假仙盟: fackFamilyID=%s,serverID=%s,familyFightPower=%s,memberCnt=%s" 
+        GameWorld.DebugLog("创建假公会: fackFamilyID=%s,serverID=%s,familyFightPower=%s,memberCnt=%s" 
                            % (fackFamilyID, serverID, familyFightPower, memberCnt))
         for _ in range(memberCnt):
             
@@ -283,15 +301,11 @@
                 memFightPowerTotal -= memFightPower
             viewCache = PlayerViewCache.FindViewCache(memID)
             viewCache.SetFightPowerTotal(memFightPower)
-            GameWorld.DebugLog("    仙盟成员: memID=%s,memFightPower=%s,fmLV=%s" % (memID, memFightPower, fmLV))
+            GameWorld.DebugLog("    公会成员: memID=%s,memFightPower=%s,fmLV=%s" % (memID, memFightPower, fmLV))
             member.RefreshMemberByID(memID)
             
         createOKCnt += 1
         familyFightPower += 10000
         
-    familyMgr.Sort()
-    if curPlayer:
-        GameWorld.DebugAnswer(curPlayer, "成功创建假仙盟: %s,剩余:%s" % (creatCount, familyMgr.GetCount()))
-    elif GameWorld.IsCrossServer():
-        GameWorld.DebugAnswer(None, "成功创建跨服假仙盟: %s,总:%s" % (creatCount, familyMgr.GetCount()))
+    GameWorld.DebugAnswer(curPlayer, "成功创建假公会: %s,总:%s" % (creatCount, len(familyMgr.GetFamilyIDList())))
     return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Family.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Family.py
index 9d504b5..6ddd0c0 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Family.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Family.py
@@ -19,21 +19,41 @@
 import CreateFamily
 import IpyGameDataPY
 import PlayerFamilyEmblem
-import PlayerFamily
-import DBDataMgr
 import PlayerControl
+import PlayerFamily
+import CrossPlayer
+import DBDataMgr
 import time
 
+def GetGMServerIDList(curPlayer):
+    ## 获取命令额外发送到其他服务器,如跨服
+    crossServerID = DBDataMgr.GetFamilyMgr().GetCurCrossServerID()
+    GameWorld.DebugAnswer(curPlayer, "GetGMServerIDList: %s" % crossServerID)
+    if crossServerID:
+        return [crossServerID]
+    return []
+
+def OnExecCross(crossPlayer, msgList):
+    ## 跨服执行命令
+    GameWorld.DebugLog("OnExecCross %s" % msgList, crossPlayer.GetPlayerID())
+    return
+
 def OnExec(curPlayer, msgList):
+    ## 游戏服执行命令
     
     if not msgList:
         GameWorld.DebugAnswer(curPlayer, "设置等级: Family lv 等级 经验")
         GameWorld.DebugAnswer(curPlayer, "设置徽章: Family e 徽章ID [剩余时间秒]")
         GameWorld.DebugAnswer(curPlayer, "设置贡献: Family c 今日贡献 累计贡献 [成员ID]")
         GameWorld.DebugAnswer(curPlayer, "设置离开: Family l 主动离开次数 被踢次数 上次是否主动  离开多久了")
-        GameWorld.DebugAnswer(curPlayer, "添加成员: Family m 人数 [仙盟ID]")
+        GameWorld.DebugAnswer(curPlayer, "添加成员: Family m 人数 [公会ID]")
         GameWorld.DebugAnswer(curPlayer, "成员离线: Family ml 成员ID 离线分钟数")
-        GameWorld.DebugAnswer(curPlayer, "创建仙盟相关使用命令: CreateFamily")
+        GameWorld.DebugAnswer(curPlayer, "重置改名: Family n")
+        GameWorld.DebugAnswer(curPlayer, "创建公会相关使用命令: CreateFamily")
+        return
+    
+    crossPlayer = CrossPlayer.GetCrossPlayerMgr().FindCrossPlayer(curPlayer.GetPlayerID())
+    if not crossPlayer:
         return
     
     value = msgList[0]
@@ -80,6 +100,10 @@
         CreateFamily.OnExec(curPlayer, msgList)
         return
     
+    elif value == "n":
+        PlayerFamily.SetRenameTime(curFamily, 0)
+        GameWorld.DebugAnswer(curPlayer, "重置改名CD")
+        
     elif value == "c":
         contribDay = msgList[1] if len(msgList) > 1 else 0
         contribTotal = msgList[2] if len(msgList) > 2 else 0
@@ -102,5 +126,5 @@
         member.SetOffTime(int(time.time()) - logoutMinutes * 60)
         GameWorld.DebugAnswer(curPlayer, "成员ID:%s,离线时间:%s" % (memID, GameWorld.ChangeTimeNumToStr(member.GetOffTime())))
         
-    PlayerFamily.Sync_FamilyInfo(curPlayer)
+    PlayerFamily.Sync_FamilyInfo(crossPlayer)
     return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py
index 6bb58c2..37ffade 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py
@@ -32,9 +32,9 @@
 def OnExec(curPlayer, msgList):
     
     if not msgList:
-        GameWorld.DebugAnswer(curPlayer, "重置仙盟珍宝阁: Zhenbaoge 0")
+        GameWorld.DebugAnswer(curPlayer, "重置公会珍宝阁: Zhenbaoge 0")
         GameWorld.DebugAnswer(curPlayer, "重置今日状态值: Zhenbaoge d")
-        GameWorld.DebugAnswer(curPlayer, "设置退仙盟时间: Zhenbaoge ft x分钟前")
+        GameWorld.DebugAnswer(curPlayer, "设置退公会时间: Zhenbaoge ft x分钟前")
         GameWorld.DebugAnswer(curPlayer, "新增假砍价数据: Zhenbaoge 次数 [随机A值 至B值]")
         GameWorld.DebugAnswer(curPlayer, "AB值没有填则按常规砍价价格计算")
         return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/GMShell.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/GMShell.py
index fa2c200..c2d6f9b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/GMShell.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/GMShell.py
@@ -30,6 +30,9 @@
 import traceback
 import FBLogic
 import GameObj
+import CrossMsg
+import ShareDefine
+import CrossPlayer
 #---------------------------------------------------------------------
 
 #---------------------------------------------------------------------
@@ -96,20 +99,26 @@
         elif not CheckGMLV(curPlayer , callFunName):
             GameWorld.DebugAnswer(curPlayer, 'GM等级不足!')
             return
+        
+        #把剩余参数转换为整型
+        for i in range(1, len(inputList)):
+            value = GameWorld.ToNumDef(inputList[i], None)
+            if value == None:
+                #GameWorld.DebugAnswer(curPlayer, "参数错误, 必须为纯数字!")
+                continue
+            inputList[i] = value
             
+        if GameWorld.IsMainServer():
+            callFunc = GameWorld.GetExecFunc(Commands, "%s.%s"%(callFunName, "GetGMServerIDList"))
+            if callFunc != None:
+                gmServerIDList = callFunc(curPlayer)
+                if gmServerIDList:
+                    CrossMsg.SendToCrossServer(ShareDefine.S2C_GMCMD, {"CMD":inputList}, gmServerIDList, curPlayer.GetPlayerID())
+                    
         callFunc = GameWorld.GetExecFunc(Commands, "%s.%s"%(callFunName, "OnExec"))
         if callFunc:
-            #删除命令,只将参数传入
-            del inputList[0]
-            #把剩余参数转换为整型
-            for i in range(0, len(inputList)):
-                value = GameWorld.ToNumDef(inputList[i], None)
-                if value == None:
-                    #GameWorld.DebugAnswer(curPlayer, "参数错误, 必须为纯数字!")
-                    continue
-                inputList[i] = value
-                
-            callFunc(curPlayer, inputList)
+            #删除命令,只将参数传入            
+            callFunc(curPlayer, inputList[1:])
             DR_UseGMCMD(curPlayer, inputStr)
             return
         
@@ -196,6 +205,24 @@
         #    raise Exception(errorMsg)
     return
 
+def S2C_GMCMD(dataMsg, fromServerID, playerID):
+    cmdList = dataMsg["CMD"]
+    
+    callName = "%s.%s" % (cmdList[0], "OnExecCross")
+    callFunc = GameWorld.GetExecFunc(Commands, callName)
+    if callFunc == None:
+        GameWorld.ErrLog("找不到此GM命令处理函数%s" % callName)
+        return
+    GameWorld.Log("跨服执行GM命令:%s" % cmdList)
+    
+    crossPlayer = CrossPlayer.GetCrossPlayerMgr().FindCrossPlayer(playerID)
+    if not crossPlayer:
+        crossPlayer = CrossPlayer.GetCrossPlayerMgr().RegistPlayer(playerID)
+        
+    #只将实际参数传入
+    callFunc(crossPlayer, cmdList[1:])
+    return
+
 ## 使用GM命令流向
 #  @param curPlayer: 玩家实例
 #  @return: None
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
index 652b5f1..37590a0 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
@@ -95,23 +95,23 @@
 # @return 返回值无意义
 # @remarks 重新加载脚本
 def ReloadScript(scriptPath, importDir):
-    gameWorld = GetGameWorld()
-    tick = gameWorld.GetTick()
-    
-    #未到刷新间隔
-    if tick - gameWorld.GetTickByType(ChConfig.TYPE_Map_Tick_ReloadScript) < \
-                ChConfig.TYPE_Map_Tick_Time[ChConfig.TYPE_Map_Tick_ReloadScript]:
-        return
-    
-    gameWorld.SetTickByType(ChConfig.TYPE_Map_Tick_ReloadScript, tick)
-    
-    if __GetPsycoIsOpen():
-        #Psyco开启
-        PsycoReload(tick)
-        return
+#    gameWorld = GetGameWorld()
+#    tick = gameWorld.GetTick()
+#    
+#    #未到刷新间隔
+#    if tick - gameWorld.GetTickByType(ChConfig.TYPE_Map_Tick_ReloadScript) < \
+#                ChConfig.TYPE_Map_Tick_Time[ChConfig.TYPE_Map_Tick_ReloadScript]:
+#        return
+#    
+#    gameWorld.SetTickByType(ChConfig.TYPE_Map_Tick_ReloadScript, tick)
+#    
+#    if __GetPsycoIsOpen():
+#        #Psyco开启
+#        PsycoReload(tick)
+#        return
 
     #Psyco关闭
-    __ReloadScript()
+    #__ReloadScript() 不再调用,c++会触发多个Reload,py默认只在 ReloadEvent 调用一次
     return
 
 #---------------------------------------------------------------------
@@ -121,6 +121,7 @@
 # @remarks 
 def __ReloadScript():
     #重新加载已经预存的脚本
+    Log("=============================== ReloadScript Begin ===============================")
     for name, reloadPath in sys.modules.items():
         try:
             pathStr = str(reloadPath)
@@ -136,7 +137,8 @@
         
     import DataRecordPack
     DataRecordPack.DR_Reload("script")
-    Log("Reload Begin : time = %s"%GetCurrentDataTimeStr())
+    Log("=============================== ReloadScript End ===============================")
+    ReadChConfig.OnReloadConfig()
     return
 
 #---------------------------------------------------------------------
@@ -617,8 +619,8 @@
         return False
     #if not curPlayer.GetInitOK():
     #    return False
-    if IsMirrorPlayer(curPlayer):
-        return False
+    #if IsMirrorPlayer(curPlayer):
+    #    return False
     return True
 
 #---------------------------------------------------------------------
@@ -1325,7 +1327,7 @@
         msg = logFormat % args[:-1]
         playerID = args[-1]
     LogUI.Msg('%s\t%s\tPyDebug:%s'%(par, playerID, msg))
-    return
+    return True
 
 #---------------------------------------------------------------------
 ##获得当前服务器跨服ID
@@ -1361,52 +1363,66 @@
 def GetServerVersion():
     return GetGameWorld().GetServerVersion()
 
+def IsCrossServer():
+    ## 是否跨服服务器,跨服中心跟常规跨服都算跨服
+    return GetServerType() in [ShareDefine.serverType_Cross, ShareDefine.serverType_CrossCenter]
+
+def IsCrossCenter():
+    ## 是否跨服中心服务器
+    return GetServerType() == ShareDefine.serverType_CrossCenter
+
+def IsMainServer():
+    ## 是否游戏服
+    return GetServerType() == ShareDefine.serverType_Main
+
 def IsBattleServer():
     ## 是否战斗服务器
-    return ToIntDef(ReadChConfig.GetPyMongoConfig("platform", "BattleServer"), 0) == 1
+    return GetServerType() == ShareDefine.serverType_Battle
+
+def GetServerType():
+    ## 本服服务器类型
+    ServerType = IpyGameDataPY.GetConfigEx("ServerType")
+    if ServerType == None:
+        ServerType = 0
+        serverDict = ReadChConfig.GetServerConfigDict()
+        serverID = GetGameWorld().GetServerID()
+        if serverID in serverDict:
+            serverInfo = serverDict[serverID]
+            ServerType = serverInfo[ShareDefine.serverCfgIndex_ServerType]
+            DebugLog("加载本服服务器类型: serverID=%s,ServerType=%s,serverInfo=%s" % (serverID, ServerType, serverInfo))
+        IpyGameDataPY.SetConfigEx("ServerType", ServerType)
+    return ServerType
 
 def GetServerGroupName():
     ## 服务器组名,取 ServersRoute 中的配置
     return ReadChConfig.GetServersRouteConfig("platform", "GroupName")
 
-def GetServerGroupID():
-    ## 服务器组ID,必须唯一,代表这台物理服务器
-    return ToIntDef(ReadChConfig.GetPyMongoConfig("platform", "GroupID"), 0)
+def GetMixServerDict():
+    ## 获取合服信息
+    # @return: {主服ID:[主服ID, 子服ID, ...], ...}
+    return # 待处理,以后有合服需要再写
+    #MixServerDict = IpyGameDataPY.GetConfigEx("MixServerDict")
+    #if MixServerDict == None:
+    #    MixServerDict = {}
+    #    MainServerDict = {} # 所属主服ID {子服ID:主服ID, ...}
+    #    groupName = GetServerGroupName()
+    #    serverDict = ReadChConfig.GetServerConfigDict()
+    #    for serverInfo in serverDict:
+    #        groupName = serverInfo[ShareDefine.serverCfgIndex_GroupName]
+    #        serverMapID = serverInfo[ShareDefine.serverCfgIndex_MapID]
+    #        serverType = serverInfo[ShareDefine.serverCfgIndex_ServerType]
+    #    IpyGameDataPY.SetConfigEx("MixServerDict", MixServerDict)
+    #    IpyGameDataPY.SetConfigEx("MainServerDict", MainServerDict)
+    #return MixServerDict
 
 def GetMainServerID(serverID):
     ## 获取服务器ID所属主服ID
-    ServerIDMainServerDict = IpyGameDataPY.GetConfigEx("ServerIDMainServerDict")
-    if ServerIDMainServerDict == None:
-        filePath = ChConfig.GetServerConfigPath() + ("\\MixServerMap_%s.json" % GetPlatform())
-        if not os.path.isfile(filePath):
-            SendGameErrorEx("GetMainServerIDError", "file can not found. %s" % filePath)
-        else:
-            fileObj = open(filePath, 'rb')
-            content = fileObj.read()
-            fileObj.close()
-            MixServerMapDict = eval(content)
-            
-            ServerIDMainServerDict = {}
-            for mainServerIDStr, serverIDList in MixServerMapDict.items():
-                mainServerID = int(mainServerIDStr)
-                for sID in serverIDList:
-                    ServerIDMainServerDict[sID] = mainServerID
-            IpyGameDataPY.SetConfigEx("ServerIDMainServerDict", ServerIDMainServerDict)
-            Log("加载 ServerIDMainServerDict=%s" % ServerIDMainServerDict)
-            
-    if not ServerIDMainServerDict:
-        return serverID
-    return ServerIDMainServerDict.get(serverID, serverID)
-
-def GetPlatformServerNum(platform):
-    # 获取服务器的平台编号
-    platformNumDict = ReadChConfig.GetDBEvalChConfig("DBPlatformNum")
-    #===========================================================================
-    # if platform not in platformNumDict:
-    #    ErrLog("DBPlatformNum没有配置该服务器平台所对应的编号!platfrom=%s" % platform)
-    #    raise Exception("DBPlatformNum没有配置该服务器平台所对应的编号!platfrom=%s" % platform)
-    #===========================================================================
-    return platformNumDict.get(platform, 0)
+    return serverID
+    #GetMixServerDict()
+    #MainServerDict = IpyGameDataPY.GetConfigEx("MainServerDict")
+    #if not MainServerDict or serverID not in MainServerDict:
+    #    return serverID
+    #return MainServerDict[serverID]
 
 ##获得当前服务器平台
 # @param 无
@@ -1414,21 +1430,11 @@
 def GetPlatform():
     return ReadChConfig.GetPyMongoConfig("platform", "PlatformName")
 
+def GetAppID():
+    ## 获取渠道ID
+    return ReadChConfig.GetPyMongoConfig("platform", "AppID")
+
 def IsTestPlatform(platform): return platform in ["test", "yun"]
-
-#===============================================================================
-# ##获得当前服务器ID
-# # @param 无
-# # @return
-# def GetServerID():
-#    return ToIntDef(GetServerSID()[1:], 0)
-#===============================================================================
-
-#===============================================================================
-# def GetServerSID():
-#    ##获得当前服务器ID, 带s的
-#    return ReadChConfig.GetPyMongoConfig("platform", "ServerID")
-#===============================================================================
 
 def GetCreateRoleDays(curPlayer):
     # 获取创角第几天
@@ -1453,17 +1459,20 @@
     infoList = accID.split(Def_AccID_Split_Sign)
     return "" if len(infoList) < 3 else infoList[-1]
 
-def GetPlayerMainServerID(accIDPlatform):
-    # 玩家合服后所属主服ID
-    # @param accIDPlatform: 玩家账号所属的平台
-    mainServerID = ToIntDef(ReadChConfig.GetPyMongoConfig("platform", "%sMainServerID" % accIDPlatform), None)
-    if mainServerID != None:
-        return mainServerID
-    return 0
-
 def GetDBPlayerAccIDByID(playerID):
     ## 获取玩家表账号ID - 根据玩家ID, 可用于判断是否本服玩家
     return PyGameData.g_dbPlayerIDMap.get(playerID, "")
+
+def CheckServerIDInList(serverID, serverIDList):
+    if serverIDList == None:
+        return False
+    if not serverIDList:
+        return True
+    for serverIDInfo in serverIDList:
+        if (isinstance(serverIDInfo, (list, tuple)) and len(serverIDInfo) == 2 and serverIDInfo[0] <= serverID <= serverIDInfo[1]) \
+            or (isinstance(serverIDInfo, int) and serverIDInfo == serverID):
+            return True
+    return False
 
 #===============================================================================
 # 平台ID = appid
@@ -1983,27 +1992,6 @@
     
     return inputText
 
-def IsCrossServer():
-    ## 是否跨服服务器
-    return ToIntDef(ReadChConfig.GetPyMongoConfig("Merge", "IsMergeServer"), 0)
-
-def GetCrossZoneName():
-    ## 跨服服务器分区名,标记一起跨服分区的名字,配置在跨服服务器,子服不用配置,由跨服服务器同步
-    if IsCrossServer():
-        return ReadChConfig.GetPyMongoConfig("Merge", "CrossZoneName")
-    return PyGameData.g_crossZoneName
-
-def GetCrossServerTimeStr():
-    ## 跨服服务器时间
-    if IsCrossServer():
-        return GetCurrentDataTimeStr()
-    lastCrossServerTime, lastServerTime = PyGameData.g_crossServerTimeInfo
-    if not lastCrossServerTime:
-        return GetCurrentDataTimeStr()
-    curTime = int(time.time())
-    crossServerTime = lastCrossServerTime + (curTime - lastServerTime)
-    return ChangeTimeNumToStr(crossServerTime)
-
 ## 时间格式转换成数值时间,可参考datetime.datetime.fromtimestamp(102645645)
 #  @param timeNum
 #  @return 时间数值 1970年起
@@ -2490,9 +2478,9 @@
     @param msgInfo: 错误信息,可选
     '''
     getUrl = ReadChConfig.GetPyMongoConfig("EventReport", "OpenStateUrl")
-    groupID = ReadChConfig.GetPyMongoConfig("platform", "GroupID")
+    groupName = GetServerGroupName()
     userDBName = ReadChConfig.GetPyMongoConfig("connect", "USER_DB_NAME")
-    getUrl = getUrl + "?Type=%s&groupID=%s&userDBName=%s&mapID=%s"%(errType, groupID, userDBName, GetMap().GetMapID())
+    getUrl = getUrl + "?Type=%s&groupID=%s&userDBName=%s&mapID=%s"%(errType, groupName, userDBName, GetMap().GetMapID())
     if msgInfo:
         getUrl = getUrl + "&MsgInfo=%s" % urllib.quote_plus(msgInfo)
     GetGameWorld().EventReport_EventReport("", "", "", "", 0, getUrl)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/CrossMgr.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/CrossMgr.py
new file mode 100644
index 0000000..bd46703
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/CrossMgr.py
@@ -0,0 +1,331 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GameWorldLogic.CrossMgr
+#
+# @todo:跨服管理器
+# @author hxp
+# @date 2026-02-04
+# @version 1.0
+#
+# 详细描述: 跨服管理器
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2026-02-04 19:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PyGameData
+import GameWorldEvent
+import ChServerToServerPyPack
+import NetPackCommon
+import ShareDefine
+import DBDataMgr
+import DBFamily
+import ChPlayer
+
+import time
+
+'''跨服通讯
+前提: 各物理机 ServersRoute 与 中心 ServersRoute 连接正常
+1. 服务器各自启动,启动完毕后,g_serverInitOK = True
+2. 跨服服务器启动完毕后开始定时广播心跳包给其他服务器,包含其他跨服服务器 // C2 01 跨服服务器心跳包 #tagSSHeart
+3. 其他服务器收到心跳且本服启动完毕,回复告知目标服务器连接成功  // C2 02 服务器连接跨服成功 #tagSSServerConnOK
+4. 跨服服务器收到连接成功时回应
+    4.1 跨服中心额外回复事件值C2 03 + 互通公会分区信息 + 跨服活动信息,这些统一由跨服中心管理
+    4.2 跨服功能数据
+5. 其他服收到回应后处理对应的跨服中心事件值,及跨服功能数据
+
+[注] 服务器间的信息通讯及接受处理,仅限制 g_serverInitOK 是否启动成功,功能如无特殊需求不需要处理连接状态,仅处理发送及接受处理逻辑即可
+
+[维护]
+游戏服务器与跨服服务器均可单独维护,启动,不用关心其他服务器
+如: 
+跨服中心维护:
+    跨服事件、公会分区、跨服活动等管理不会再触发
+    
+跨服服务器维护: 
+    则不会再广播心跳包,本服收不到跨服心跳视为跨服维护了,功能可针对跨服服务器状态进行相应处理
+    跨服维护完毕后,重新广播心跳,本服重新收到心跳,视为重连跨服,如需要可对重连做差异处理
+    
+本服服务器维护:则跨服广播的信息不会再收到,维护完毕后,重新与跨服服务器连接上
+
+所以无论哪台服务器维护,维护后本服与跨服都重新走 1~5 的连接流程,包含网络异常的断连,都会重新走该流程,验证事件,重新同步跨服功能所需的数据
+
+'''
+
+HeartBreat = 10 # 心跳间隔,秒
+DisconnectedTime = HeartBreat * 3 # 多久没收到心跳视为断开,秒
+
+class SSServer():
+    ''' 其他服务器对象,可以是跨服服务器、其他游戏服等
+    '''
+    
+    def __init__(self, serverID):
+        self._serverID = serverID
+        self._serverType = 0
+        self._connState = 0 # 连接状态 0-未知,1-已连接,2-已断开
+        self._heartCurTime = 0 # 上次收到该服心跳时的本服时间戳
+        return
+    
+    def GetServerID(self): return self._serverID
+    def GetServerType(self): return self._serverType
+    def SetServerType(self, serverType): self._serverType = serverType
+    def GetConnState(self): return self._connState
+    def SetConnState(self, connState): self._connState = connState
+    def GetHeartCurTime(self): return self._heartCurTime # 上次收到该服心跳时的本服时间戳
+    def SetHeartCurTime(self, curTime): self._heartCurTime = curTime
+    
+class SSServerMgr():
+    ## 其他服务器管理器,所有服务器通用
+    
+    def __init__(self):
+        self._ssServerDict = {} # 其他服务器 {serverID:SSServer, ...}
+        self._heartTime = 0 # 心跳时间戳,定时广播给其他需要的服务器,目前仅跨服服务器需要广播心跳
+        self._disconnectedCheckTime = 0 # 上次检查其他服是否还有心跳时间
+        self._crossServerIDList = [] # 跨服服务器ID列表
+        
+        # 跨服中心
+        self._crossCenterID = 0 # 跨服中心服务器ID,有且仅允许有一台,用于管理统一的跨服时间、跨服活动配置、公会互通配置等
+        self._crossTime = 0 # 跨服中心时间戳
+        self._crossTimeCurTime = 0 # 设置跨服中心时间时,本服的时间戳
+        return
+    
+    def GetSSServer(self, serverID):
+        if serverID in self._ssServerDict:
+            ssServer = self._ssServerDict[serverID]
+        else:
+            ssServer = SSServer(serverID)
+            self._ssServerDict[serverID] = ssServer
+        return ssServer
+    
+    def DoHeartbeat(self, curTime):
+        ## 心跳广播给其他服
+        
+        # 时间回调时也立刻同步心跳
+        if self._heartTime and curTime >= self._heartTime and curTime - self._heartTime < HeartBreat:
+            return
+        self._heartTime = curTime
+        
+        if not GameWorld.IsCrossServer():
+            # 目前仅跨服服务器需要处理心跳,其他暂时不用
+            return
+        
+        pack = ChServerToServerPyPack.tagSSHeart()
+        pack.ServerID = GameWorld.GetGameWorld().GetServerID()
+        pack.ServerType = GameWorld.GetServerType()
+        pack.ServerTime = curTime
+        
+        # 广播给所有服务器,包含跨服
+        NetPackCommon.SendCrossServerToServerPack(pack, dirType=ShareDefine.dirType_MainAndCross)
+        return
+    
+    def OnServerHeart(self, serverID, serverType, serverTime):
+        ## 收到心跳
+        
+        curTime = int(time.time())
+        
+        ssServer = self.GetSSServer(serverID)
+        
+        befConnState = ssServer.GetConnState()
+        
+        ssServer.SetServerType(serverType)
+        ssServer.SetConnState(ShareDefine.ssConn_Normal)
+        ssServer.SetHeartCurTime(curTime)
+        
+        isReconn = True if befConnState == ShareDefine.ssConn_Disconnected else False
+        
+        # 跨服服务器
+        if serverType == ShareDefine.serverType_CrossCenter:
+            GameWorld.Log("连上跨服中心服务器: crossServerID=%s,isReconn=%s,crossServerTime=%s" % (serverID, isReconn, GameWorld.ChangeTimeNumToStr(serverTime)))
+            if not self._crossCenterID:
+                self._crossCenterID = serverID
+            if serverID not in self._crossServerIDList:
+                self._crossServerIDList.append(serverID)
+                
+            lastCrossTime = self.GetCrossTime()
+            self.SetCrossTime(serverTime, curTime)
+            
+            # 时间回调或误差过大立即同步给前端
+            if serverTime < lastCrossTime or (serverTime - lastCrossTime) >= 30:
+                ChPlayer.Sync_PyServerDataTimeToClient()
+                
+        elif serverType == ShareDefine.serverType_Cross:
+            GameWorld.Log("连上跨服服务器: crossServerID=%s,isReconn=%s" % (serverID, isReconn))
+            if serverID not in self._crossServerIDList:
+                self._crossServerIDList.append(serverID)
+                
+        else:
+            GameWorld.Log("连上其他服务器: serverID=%s,serverType=%s,isReconn=%s" % (serverID, serverType, isReconn))
+            return
+        
+        OnConnCrossServer(serverType, serverID, isReconn)
+        return
+    
+    def GetCrossTime(self):
+        ## 获取跨服服务器时间 - 以跨服中心服务器为准,如果没有默认取本服时间
+        curTime = int(time.time())
+        if not self._crossTime:
+            return curTime
+        self._crossTime += max(0, curTime - self._crossTimeCurTime)
+        self._crossTimeCurTime = curTime
+        return self._crossTime
+    
+    def SetCrossTime(self, serverTime, curTime=0):
+        ## 设置跨服服务器时间 - 以跨服中心服务器为准
+        self._crossTime = serverTime
+        self._crossTimeCurTime = curTime if curTime else int(time.time())
+        return serverTime
+    
+    def GetCrossServerIDList(self): return self._crossServerIDList
+    
+    def CheckSSServerDisconnected(self, curTime):
+        ## 检查其他服是否断开连接
+        
+        if not self._disconnectedCheckTime or curTime < self._disconnectedCheckTime:
+            self._disconnectedCheckTime = curTime
+            return
+        
+        if curTime - self._disconnectedCheckTime < 10:
+            # 每10秒检查一次
+            return
+        self._disconnectedCheckTime = curTime
+        
+        for ssServer in self._ssServerDict.values():
+            if ssServer.GetConnState() != ShareDefine.ssConn_Normal:
+                continue
+            lastHeartTime = ssServer.GetHeartCurTime()
+            if not lastHeartTime:
+                # 不需要心跳的不处理
+                continue
+            if lastHeartTime > curTime:
+                # 本服时间回调了暂不处理
+                continue
+            if curTime - lastHeartTime <= DisconnectedTime:
+                continue
+            ssServer.SetConnState(ShareDefine.ssConn_Disconnected)
+            
+            serverID = ssServer.GetServerID()
+            serverType = ssServer.GetServerType()
+            if serverType == ShareDefine.serverType_Cross:
+                GameWorld.Log("与跨服服务器断开: serverID=%s,serverType=%s" % (serverID, serverType))
+            else:
+                GameWorld.Log("与其他服务器断开: serverID=%s,serverType=%s" % (serverID, serverType))
+                
+        return
+
+def GetSSServerMgr():
+    ssMgr = PyGameData.g_ssServerMgr
+    if not ssMgr:
+        ssMgr = SSServerMgr()
+        PyGameData.g_ssServerMgr = ssMgr
+    return ssMgr
+
+def OnSecondProcess(tick, curTime):
+    
+    ssMgr = GetSSServerMgr()
+    ssMgr.CheckSSServerDisconnected(curTime)
+    ssMgr.DoHeartbeat(curTime)
+    return
+
+#// C2 01 跨服服务器心跳包 #tagSSHeart
+#
+#struct    tagSSHeart
+#{
+#    tagHead        Head;
+#    DWORD        ServerID;    
+#    BYTE        ServerType;    //服务器类型
+#    DWORD        ServerTime;    //服务器时间戳
+#};
+def OnServerHeart(netPack):
+    serverID = netPack.ServerID
+    serverType = netPack.ServerType
+    serverTime = netPack.ServerTime
+    #GameWorld.DebugLog("收到其他服务器心跳: serverID=%s,serverType=%s,serverTime=%s" % (serverID, serverType, GameWorld.ChangeTimeNumToStr(serverTime)))
+    if serverID == GameWorld.GetGameWorld().GetServerID():
+        return
+    if not PyGameData.g_serverInitOK:
+        return
+    GetSSServerMgr().OnServerHeart(serverID, serverType, serverTime)
+    return
+
+def OnConnCrossServer(serverType, serverID, isReconn):
+    ## 连上跨服服务器
+    
+    curServerType = GameWorld.GetServerType()
+    
+    # 通知连上目标服务器
+    pack = ChServerToServerPyPack.tagSSServerConnOK()
+    pack.ServerID = GameWorld.GetGameWorld().GetServerID()
+    pack.ServerType = curServerType
+    pack.IsReconn = isReconn
+    NetPackCommon.SendCrossServerToServerPack(pack, [serverID], serverType=serverType)
+    
+    # 游戏服
+    if GameWorld.IsMainServer():
+        ChPlayer.SyncOnlinePlayerToCross(serverID)
+    return
+
+#// C2 02 服务器连接跨服成功 #tagSSServerConnOK
+#
+#struct    tagSSServerConnOK
+#{
+#    tagHead        Head;
+#    DWORD        ServerID;    
+#    BYTE        ServerType;    //服务器类型
+#    BYTE        IsReconn;    //是否重连的
+#};
+def OnServerConnOK(netPack):
+    serverID = netPack.ServerID
+    serverType = netPack.ServerType
+    isReconn = netPack.IsReconn
+    
+    curServerType = GameWorld.GetServerType()
+    GameWorld.Log("收到服务器连接成功: serverID=%s,serverType=%s,isReconn=%s,curServerType=%s" % (serverID, serverType, isReconn, curServerType))
+    # 连接成功回应:
+    
+    # 任意服务器    【连上】    跨服中心: 额外同步跨服事件、公会互通、跨服活动等
+    if curServerType == ShareDefine.serverType_CrossCenter:
+        # 同步事件值
+        SendCrossServerEvent([serverID], dirType=NetPackCommon.GetSSPackDirType(serverType))
+        
+        # 同步公会互通分区配置
+        DBFamily.Sync_CenterToCross_FamilyInfo(serverType, serverID)
+        
+        # 同步跨服活动信息
+        
+        
+    # 游戏服    【连上】    跨服
+    if serverType == ShareDefine.serverType_Main and curServerType in [ShareDefine.serverType_CrossCenter, ShareDefine.serverType_Cross]:
+        DBFamily.Sync_CrossToServer_FamilyInfo(serverID)
+        
+    return
+
+def SendCrossServerEvent(serverIDList=None, dirType=ShareDefine.dirType_MainAndCross):
+    ## 同步跨服中心服务器事件值
+    pack = ChServerToServerPyPack.tagSSCrossCenterEvent()
+    pack.ServerID = GameWorld.GetGameWorld().GetServerID()
+    pack.ServerType = GameWorld.GetServerType()
+    pack.EventValue = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_CrossCenterEvent)
+    NetPackCommon.SendCrossServerToServerPack(pack, serverIDList, dirType)
+    return
+
+#// C2 03 跨服中心事件同步 #tagSSCrossCenterEvent
+#
+#struct    tagSSCrossCenterEvent
+#{
+#    tagHead        Head;
+#    DWORD        ServerID;    
+#    BYTE        ServerType;    //服务器类型
+#    DWORD        EventValue;    //事件值,yyyyMMddhh用于判断过天等
+#};
+def OnCrossCenterEvent(netPack):
+    serverID = netPack.ServerID
+    serverType = netPack.ServerType
+    eventValue = netPack.EventValue
+    GameWorld.Log("收到服务器事件变更同步: serverID=%s,serverType=%s,eventValue=%s" % (serverID, serverType, eventValue))
+    if serverType != ShareDefine.serverType_CrossCenter:
+        return
+    GameWorldEvent.DoLogic_CrossCenterEvent(eventValue, serverID)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/CrossMsg.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/CrossMsg.py
new file mode 100644
index 0000000..8d16fc5
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/CrossMsg.py
@@ -0,0 +1,201 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GameWorldLogic.CrossMsg
+#
+# @todo:跨服通讯信息
+# @author hxp
+# @date 2026-02-04
+# @version 1.0
+#
+# 详细描述: 跨服通讯信息
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2026-02-04 19:00"""
+#-------------------------------------------------------------------------------
+
+import DBFamily
+import GameWorld
+import PlayerMail
+import ShareDefine
+import NetPackCommon
+import ChServerToServerPyPack
+from GM import GMShell
+import PlayerFamily
+import CrossPlayer
+import TurnAttack
+import PyGameData
+import ChPlayer
+
+import traceback
+import cPickle
+import time
+
+def SendToCrossServer(msgType, dataMsg, serverIDList=None, playerID=0):
+    ## 游戏服发送信息到跨服服务器
+    if GameWorld.IsCrossServer():
+        return
+    #if not dataMsg:
+    #    return
+    logData = "" if msgType in ShareDefine.NoLogDataSSMsgTypes else dataMsg
+    GameWorld.Log("SendToCrossServer => %s, %s, %s" % (msgType, serverIDList, logData), playerID)
+    SendToServer(msgType, dataMsg, serverIDList, ShareDefine.dirType_Cross, playerID, isLog=False)
+    return
+
+def SendToClientServer(msgType, dataMsg, serverIDList=None, playerID=0):
+    ''' 跨服发送信息到子游戏服务器
+        @param serverGroupIDList: 发送指定的服务器组ID列表,内部已经针对列表中组ID去重,
+        所以外部逻辑可直接添加,不用考虑组ID重复问题,没有指定服务器组ID时,默认广播所有子服
+    '''
+    if not GameWorld.IsCrossServer():
+        return
+    #if not dataMsg:
+    #    return
+    logData = "" if msgType in ShareDefine.NoLogDataSSMsgTypes else dataMsg
+    GameWorld.Log("SendToClientServer => %s, %s, %s" % (msgType, serverIDList, logData), playerID)
+    SendToServer(msgType, dataMsg, serverIDList, ShareDefine.dirType_Main, playerID, isLog=False) # 默认发给主服即可
+    return
+
+def SendBackServer(msgType, dataMsg, serverID, serverType, playerID=0):
+    ## 用于服务器一对一回包
+    SendToServer(msgType, dataMsg, [serverID], NetPackCommon.GetSSPackDirType(serverType), playerID)
+    return
+
+def SendBattleRequest(dataMsg, guid, mapID, funcLineID, reqPlayerID=0):
+    msgType = ShareDefine.S2B_BattleRequest
+    GameWorld.Log("SendToBattleServer => %s, funcMapID=%s,funcLineID=%s,%s,%s" % (msgType, mapID, funcLineID, guid, time.time()), reqPlayerID)
+    SendToServer(msgType, dataMsg, dirType=ShareDefine.dirType_Battle, playerID=reqPlayerID, isLog=False)
+    return
+
+def SendBattleResult(retInfo, fromServerID, guid, mapID, funcLineID, reqPlayerID=0):
+    msgType = ShareDefine.B2S_BattleResult
+    GameWorld.Log("SendToFromServer => %s, fromServerID=%s,funcMapID=%s,funcLineID=%s,%s,%s" 
+                  % (msgType, fromServerID, mapID, funcLineID, guid, time.time()), reqPlayerID)
+    SendToServer(msgType, retInfo, [fromServerID], ShareDefine.dirType_Main, reqPlayerID, isLog=False)
+    return
+
+def SendToServer(msgType, dataMsg, serverIDList=None, dirType=ShareDefine.dirType_Main, playerID=0, isLog=True):
+    '''发送给其他服务器
+    @param msgType: 功能信息类型字符定义
+    @param dataMsg: 发送的数据,任意格式,由功能自行决定
+    @param serverIDList: 指定目标服务器ID 或   服务器ID列表
+    '''
+    if not PyGameData.g_serverInitOK:
+        GameWorld.Log("服务器未启动好!不允许与其他服务器通讯! msgType=%s" % msgType)
+        return
+    
+    if isinstance(serverIDList, int):
+        serverIDList = [serverIDList]
+    elif not isinstance(serverIDList, list):
+        serverIDList = []
+    #else:
+    #    serverIDList = list(set(serverIDList)) # 去重
+        
+    if isLog:
+        logData = "" if msgType in ShareDefine.NoLogDataSSMsgTypes else dataMsg
+        GameWorld.Log("SendToServer => %s, %s, %s" % (msgType, serverIDList, logData), playerID)
+        
+    # 协议要用最高级2,可减少长度
+    sendMsg = cPickle.dumps(dataMsg, 2)
+    
+    pack = ChServerToServerPyPack.tagSSCommMsg()
+    pack.FromServerID = GameWorld.GetGameWorld().GetServerID()
+    pack.ServerType = GameWorld.GetServerType()
+    pack.PlayerID = playerID
+    pack.ServerTime = int(time.time())
+    pack.MsgType = msgType
+    pack.TypeLen = len(pack.MsgType)
+    pack.Data = sendMsg
+    pack.Len = len(pack.Data)
+    NetPackCommon.SendCrossServerToServerPack(pack, serverIDList, dirType)
+    return
+
+#// C2 10 跨服通用信息包 #tagSSCommMsg
+#
+#struct    tagSSCommMsg
+#{
+#    tagHead        Head;
+#    DWORD        FromServerID;    //哪个服发的
+#    BYTE        ServerType;    //服务器类型
+#    DWORD        PlayerID;        //哪个玩家触发发送的
+#    BYTE        TypeLen;
+#    char        MsgType[TypeLen];
+#    DWORD        Len;
+#    char        Data[Len];    
+#};
+def OnSSCommMsg(netPack):
+    ## 收到其他服务器发来的消息
+    fromServerID = netPack.FromServerID
+    serverType = netPack.ServerType
+    playerID = netPack.PlayerID
+    msgType = netPack.MsgType
+    recvMsg = netPack.Data
+    
+    if not PyGameData.g_serverInitOK:
+        GameWorld.Log("服务器未启动好,不处理其他服务器信息! %s, fromServerID=%s" % (msgType, fromServerID))
+        return
+    
+    if fromServerID == GameWorld.GetGameWorld().GetServerID():
+        # 不处理给自己发的消息
+        return
+    
+    try:
+        dataMsg = cPickle.loads(recvMsg)
+        
+        logData = "" if msgType in ShareDefine.NoLogDataSSMsgTypes else str(dataMsg)
+        GameWorld.Log("OnSSRecvMsg => %s, fromServerID=%s, %s,time=%s" % (msgType, fromServerID, logData, time.time()), playerID)
+        
+        # 所有类型服务器均可能收到的信息
+        if msgType == ShareDefine.S2B_BattleRequest: # 请求战斗
+            TurnAttack.S2B_BattleRequest(dataMsg, fromServerID, msgType)      
+        elif msgType == ShareDefine.B2S_BattleResult: # 战斗结果
+            TurnAttack.B2S_BattleResult(dataMsg, fromServerID, msgType)
+            
+        else:
+            curServerType = GameWorld.GetServerType()
+            ## 按服务器类型归类处理需要处理的信息类型,进一步防止信息误发误处理导致的数据问题
+            
+            # 跨服服务器要处理的消息
+            if curServerType in [ShareDefine.serverType_CrossCenter, ShareDefine.serverType_Cross]:
+                if msgType == ShareDefine.CC2C_FamilyCrossCfg: # 公会分区配置
+                    DBFamily.CC2C_FamilyCrossCfg(dataMsg, fromServerID, serverType)
+                elif msgType == ShareDefine.S2C_PlayerBaseInfo:
+                    ChPlayer.S2C_PlayerBaseInfo(dataMsg, fromServerID, playerID)
+                elif msgType == ShareDefine.S2C_OnlineState: # 玩家在线状态
+                    ChPlayer.S2C_OnlineState(dataMsg, fromServerID, playerID)
+                elif msgType == ShareDefine.S2C_FamilyData: # 首次同步公会互通数据
+                    DBFamily.S2C_FamilyData(dataMsg, fromServerID)
+                elif msgType == ShareDefine.S2C_FamilyPyPack: # 公会功能玩家请求py包转发
+                    PlayerFamily.S2C_FamilyPyPack(dataMsg, fromServerID, playerID)
+                elif msgType == ShareDefine.S2C_GMCMD:
+                    GMShell.S2C_GMCMD(dataMsg, fromServerID, playerID)
+                    
+            # 游戏服务器要处理的消息
+            elif curServerType == ShareDefine.serverType_Main:
+                if msgType == ShareDefine.C2S_FamilyCrossInfo:
+                    DBFamily.C2S_FamilyCrossInfo(dataMsg, fromServerID)
+                elif msgType == ShareDefine.C2S_FamilyDataRet: # 同步公会互通数据结果回复
+                    DBFamily.C2S_FamilyDataRet(dataMsg, fromServerID)
+                #elif msgType == ShareDefine.C2S_PlayerLoginOK:
+                #    ChPlayer.C2S_PlayerLoginOK(playerID)
+                elif msgType == ShareDefine.C2S_FamilyMapPlayer:
+                    PlayerFamily.C2S_FamilyMapPlayer(dataMsg, playerID)
+                elif msgType == ShareDefine.C2S_FamilyPyPackRet:
+                    PlayerFamily.C2S_FamilyPyPackRet(dataMsg, playerID)
+                elif msgType == ShareDefine.C2S_NotifyCode:
+                    CrossPlayer.C2S_NotifyCode(dataMsg, playerID)
+                elif msgType == ShareDefine.C2S_SendFakePack:
+                    CrossPlayer.C2S_SendFakePack(dataMsg)
+                elif msgType == ShareDefine.C2S_CostPlayerResources:
+                    CrossPlayer.C2S_CostPlayerResources(dataMsg, playerID)
+                elif msgType == ShareDefine.C2S_GivePlayerResources:
+                    CrossPlayer.C2S_GivePlayerResources(dataMsg, playerID)
+                elif msgType == ShareDefine.C2S_SetPlayerNomalDict:
+                    CrossPlayer.C2S_SetPlayerNomalDict(dataMsg, playerID)
+                elif msgType == ShareDefine.C2S_SendPlayerMail:
+                    PlayerMail.C2S_SendPlayerMail(dataMsg, playerID)
+                    
+    except:
+        GameWorld.RaiseException("服务器接收信息处理报错 \r\n%s" % str(traceback.format_exc()))
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py
index 20d42e0..e366e5e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py
@@ -15,6 +15,8 @@
 #"""Version = 2025-05-15 10:35"""
 #-------------------------------------------------------------------------------
 
+import CrossMgr
+import ChConfig
 import DBDataMgr
 import GameWorld
 import PyMongoMain
@@ -29,7 +31,6 @@
 import PlayerOnline
 import ShareDefine
 import PyGameData
-import ItemCommon
 import BattleObj
 import ChPlayer
 import ObjPool
@@ -80,16 +81,21 @@
 
 def InitGameWorld(tick):
     ## GameWorld初始化
-    if PyGameData.g_initGameTime:
+    if PyGameData.g_initGameWorldOK:
         return
     serverID = GameWorld.GetGameWorld().GetServerID()
-    GameWorld.Log("服务器启动初始化InitGameWorld: serverID=%s" % serverID)
+    serverType = GameWorld.GetServerType()
+    GameWorld.Log("服务器启动初始化InitGameWorld: serverID=%s,serverType=%s" % (serverID, serverType))
     DBDataMgr.OnServerStart() # 优先加载公共数据
     #ItemCommon.InitPyItem() # 改为放 InitItem 加载
     LoadDBPlayer()
     PlayerViewCache.LoadRobot()
     PyGameData.g_initGameTime = int(time.time()) # 放到加载数据之后
     
+    if DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_FamilyTransDataTime):
+        DBDataMgr.GetEventTrigMgr().SetValue(ShareDefine.Def_FamilyTransDataTime, 0)
+        GameWorld.Log("启动服务器时重置跨服公会传输数据状态!")
+        
     #初始话开服时间、星期几
     initOpenServerTime = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_InitOpenServerTime)
     openServerWeekday = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_OpenServerWeekday)
@@ -103,22 +109,43 @@
     # 其他功能初始化
     
     
+    # 最后触发检查是否完全启动成功
+    PyGameData.g_initGameWorldOK = True
+    OnServerInitOK()
+    return
+
+def OnServerInitOK():
+    '''服务器完全启动初始化成功后的处理,如db数据加载及静态物品数据等都加载完毕了
+    如跨服间相关逻辑通讯需要等服务器完全启动完毕后才可进行
+    '''
+    if not PyGameData.g_initGameWorldOK or not PyGameData.g_initPyItem:
+        return
+    if PyGameData.g_serverInitOK:
+        return
+    PyGameData.g_serverInitOK = True
+    
+    tick = GameWorld.GetGameWorld().GetTick()
+    serverID = GameWorld.GetGameWorld().GetServerID()
+    
     OnHighProcess(tick) # 主动触发一次高精度的调用,确保服务器启动后一些功能活动等的数据会被加载
     OnMinute(tick)
     
     GameWorld.Log("=============================== 服务器启动成功 ===================================")
+    serverType = GameWorld.GetServerType()
     isCrossServer = GameWorld.IsCrossServer()
     if isCrossServer:
-        pass
+        GameWorld.Log("跨服服务器启动成功: serverType=%s,serverID=%s" % (serverType, serverID))
     else:
-        serverGroupID = GameWorld.GetServerGroupID()
         serverDay = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_ServerDay) + 1
         isMixServer = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_IsMixServer)
         mixServerDay = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_MixServerDay) + 1
-        GameWorld.Log("服务器启动成功: ServerGroupID=%s,serverID=%s,serverDay=%s,isMixServer=%s,mixServerDay=%s" 
-                      % (serverGroupID, serverID, serverDay, isMixServer, mixServerDay))
-    PyGameData.g_serverInitOK = True
+        GameWorld.Log("游戏服务器启动成功: serverType=%s,serverID=%s,serverDay=%s,isMixServer=%s,mixServerDay=%s" 
+                      % (serverType, serverID, serverDay, isMixServer, mixServerDay))
+        
     DataRecordPack.DR_Reload("restart")
+    
+    # ---------- 以下处理服务器完全启动好后的逻辑 ----------
+    
     return
 
 def AllMapServerInitOK(tick):
@@ -243,7 +270,7 @@
 
 def OnHighProcess(tick):
     ## 每秒分钟执行一次
-    if not PyGameData.g_initGameTime:
+    if not PyGameData.g_serverInitOK:
         return
     curTime = int(time.time())
     if not PyGameData.g_highProcessTime:
@@ -268,6 +295,7 @@
         return
     
     PyMongoMain.GetUserCtrlDB().onSecondProcess()
+    CrossMgr.OnSecondProcess(tick, curTime)
     
     OnMinute(tick)
     
@@ -340,6 +368,18 @@
     return
 
 def DoLogic_GameWorldEvenByTime(tick):
+    '''跨服事件由跨服中心服务器驱动,游戏服使用原方式
+    跨服中心OnEvent -> 其他服务器OnEvent (包含个常规跨服服务器及游戏服,不保证谁先执行)
+        个别功能如果需要确保跨服先执行Event,再处理游戏服Event,可以由功能驱动跨服先执行,再同步游戏服执行
+    '''
+    if GameWorld.IsCrossServer():
+        if not GameWorld.IsCrossCenter():
+            return
+        eventValue = GameWorld.ToIntDef(GameWorld.ChangeTimeNumToStr(int(time.time()), ChConfig.TYPE_Time_Format_YmdH))
+        if DoLogic_CrossCenterEvent(eventValue):
+            CrossMgr.SendCrossServerEvent()
+        return  
+      
     #-----------服务器当前时间
     curTime = datetime.datetime.today()
     curTimeHour = curTime.hour
@@ -417,6 +457,62 @@
     PlayerEventCounter.DoLogic_OnYear(tick)
     return
 
+def DoLogic_CrossCenterEvent(centerEventValue, centerServerID=0):
+    ## 收到跨服中心事件同步,如OnDay等
+    serverEventValue = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_CrossCenterEvent)
+    if not serverEventValue:
+        serverEventValue = centerEventValue
+        DBDataMgr.GetEventTrigMgr().SetValue(ShareDefine.Def_CrossCenterEvent, centerEventValue)
+        
+    if centerServerID:
+        GameWorld.Log("处理跨服中心事件值! serverEventValue=%s,centerEventValue=%s,centerServerID=%s" % (serverEventValue, centerEventValue, centerServerID))
+        
+    if serverEventValue == centerEventValue:
+        GameWorld.DebugLog("跨服中心事件值不变! serverEventValue=%s,centerEventValue=%s,centerServerID=%s" % (serverEventValue, centerEventValue, centerServerID))
+        return
+    
+    serverEventTime = GameWorld.ChangeStrToDatetime("%s:%02d:%02d" % serverEventValue, ChConfig.TYPE_Time_Format_YmdHMS)
+    centerEventTime = GameWorld.ChangeStrToDatetime("%s:%02d:%02d" % centerEventValue, ChConfig.TYPE_Time_Format_YmdHMS)
+    
+    serverHour = serverEventTime.hour
+    serverDay = serverEventTime.day
+    #serverWeek = datetime.datetime.isocalendar(serverEventTime)[1]
+    serverMonth = serverEventTime.month
+    serverYear = serverEventTime.year
+    
+    centerHour = centerEventTime.hour
+    centerDay = centerEventTime.day
+    #centerWeek = datetime.datetime.isocalendar(centerEventTime)[1]
+    centerMonth = centerEventTime.month
+    centerYear = centerEventTime.year
+    
+    DBDataMgr.GetEventTrigMgr().SetValue(ShareDefine.Def_CrossCenterEvent, centerEventValue)
+    
+    isEvent = False
+    
+    #OnHour事件
+    if (serverHour != centerHour or serverDay != centerDay or serverMonth != centerMonth or serverYear != centerYear):
+        isEvent = True
+        PlayerEventCounter.DoLogic_CrossCenterOnHour(centerEventValue)
+        
+    #OnDay事件
+    if (serverDay != centerDay or serverMonth != centerMonth or serverYear != centerYear):
+        isEvent = True
+        PlayerEventCounter.DoLogic_CrossCenterOnDay(centerEventValue)
+        
+    #OnWeek事件
+    #if (serverWeek != curTimeWeek):
+    #    OnWeek(tick)
+        
+    #OnMonth事件
+    #if (serverMonth != curTimeMonth or serverYear != curTimeYear):
+    #    OnMonth(tick)
+        
+    #OnYear事件
+    #if serverYear != curTimeYear:
+    #    OnYear(tick)
+    
+    return isEvent
 
 def __CheckIpyDataRecycle(timeNow):
     ## 检查IpyData数据回收
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 1cbd2e2..1aa6ea4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -2123,6 +2123,13 @@
                         ("dict", "Attr", 0),
                         ),
 
+                "FamilyCross":(
+                        ("char", "AppID", 1),
+                        ("WORD", "ZoneID", 1),
+                        ("DWORD", "CrossServerID", 0),
+                        ("list", "ServerIDList", 0),
+                        ),
+
                 "Family":(
                         ("BYTE", "FamilyLV", 1),
                         ("BYTE", "MemberMax", 0),
@@ -5433,7 +5440,19 @@
     def GetCostItem(self): return self.attrTuple[3] # 消耗材料 dict
     def GetAttr(self): return self.attrTuple[4] # 属性 dict
 
-# 仙盟等级表
+# 跨服公会表
+class IPY_FamilyCross():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetAppID(self): return self.attrTuple[0] # AppID char
+    def GetZoneID(self): return self.attrTuple[1] # 分区ID WORD
+    def GetCrossServerID(self): return self.attrTuple[2] # 跨服服务器ID DWORD
+    def GetServerIDList(self): return self.attrTuple[3] # 互通服务器ID列表 list
+
+# 公会等级表
 class IPY_Family():
     
     def __init__(self):
@@ -5447,7 +5466,7 @@
     def GetNeedExp(self): return self.attrTuple[4] # 升级所需经验 DWORD
     def GetZhenbaogeWeights(self): return self.attrTuple[5] # 珍宝阁总权重 DWORD
 
-# 仙盟徽章表
+# 公会徽章表
 class IPY_FamilyEmblem():
     
     def __init__(self):
@@ -5459,7 +5478,7 @@
     def GetExpireMinutes(self): return self.attrTuple[2] # 有效时长,分钟 DWORD
     def GetCustomFamilyID(self): return self.attrTuple[3] # 定制仙盟ID DWORD
 
-# 仙盟捐献表
+# 公会捐献表
 class IPY_FamilyDonate():
     
     def __init__(self):
@@ -5472,7 +5491,7 @@
     def GetMoneyValue(self): return self.attrTuple[3] # 消耗货币值 DWORD
     def GetAwardItemList(self): return self.attrTuple[4] # 获得奖励列表[[物品ID,个数], ...] list
 
-# 仙盟珍宝阁砍价表
+# 公会珍宝阁砍价表
 class IPY_FamilyZhenbaogeCut():
     
     def __init__(self):
@@ -5484,7 +5503,7 @@
     def GetMinRatio(self): return self.attrTuple[2] # 保底比值 float
     def GetRandRatio(self): return self.attrTuple[3] # 随机比值 float
 
-# 仙盟珍宝阁物品表
+# 公会珍宝阁物品表
 class IPY_FamilyZhenbaogeItem():
     
     def __init__(self):
@@ -6001,6 +6020,7 @@
         self.__LoadFileData("EquipShenEvolve", onlyCheck)
         self.__LoadFileData("EquipStarUp", onlyCheck)
         self.__LoadFileData("EquipPlusEvolve", onlyCheck)
+        self.__LoadFileData("FamilyCross", onlyCheck)
         self.__LoadFileData("Family", onlyCheck)
         self.__LoadFileData("FamilyEmblem", onlyCheck)
         self.__LoadFileData("FamilyDonate", onlyCheck)
@@ -7700,6 +7720,13 @@
         self.CheckLoadData("EquipPlusEvolve")
         return self.ipyEquipPlusEvolveCache[index]
 
+    def GetFamilyCrossCount(self):
+        self.CheckLoadData("FamilyCross")
+        return self.ipyFamilyCrossLen
+    def GetFamilyCrossByIndex(self, index):
+        self.CheckLoadData("FamilyCross")
+        return self.ipyFamilyCrossCache[index]
+
     def GetFamilyCount(self):
         self.CheckLoadData("Family")
         return self.ipyFamilyLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
index 95fef53..19e6d2b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
@@ -30,6 +30,7 @@
 import ChItem
 import IpyGameDataPY
 import ChPyNetSendPack
+import GameWorldEvent
 import NetPackCommon
 import PyGameData
 import ChEquip
@@ -51,7 +52,7 @@
 
 #---------------------------------------------------------------------
 def InitPyItem():
-    if PyGameData.InitPyItem:
+    if PyGameData.g_initPyItem:
         return
     GameWorld.Log("加载物品数据...")
     
@@ -96,7 +97,8 @@
     GameWorld.Log("货币类型1个数量对应物品ID: %s" % PyGameData.MoneyItemIDDict)
     if not PyGameData.MoneyItemIDDict:
         GameWorld.SendGameErrorEx("InitPyItemError", "启动加载物品数据异常! itemCount=%s" % gameData.GetItemCount())
-    PyGameData.InitPyItem = True
+    PyGameData.g_initPyItem = True
+    GameWorldEvent.OnServerInitOK()
     return
 
 def GetMoneyItemID(moneyType):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
index cedcfe7..fcd8663 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -186,7 +186,7 @@
     #存一个满足要求的所有的物品的列表 然后从当中随机选一个
     #注: 阶、颜色、套装ID、职业、部位,这5个条件可确认唯一一件装备
     
-    if not PyGameData.InitPyItem:
+    if not PyGameData.g_initPyItem:
         GameWorld.ErrLog("地图还未启动好载物品!")
         return []
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NetPackCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NetPackCommon.py
index 834ad62..2150f31 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NetPackCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NetPackCommon.py
@@ -18,7 +18,7 @@
 # @change: "2014-12-09 17:30" xmnathan 修改玩家M->S自定义封包发送
 # @change: "2014-12-19 19:30" hxp Debug下封包错误抛出异常
 #-------------------------------------------------------------------------------
-"""Version = 2014-12-19 19:30"""
+#"""Version = 2014-12-19 19:30"""
 #-------------------------------------------------------------------------------
 #---导入---
 import IPY_GameWorld
@@ -33,6 +33,10 @@
 from PyMongoDB.DBCommon import CommonDefine
 import ChServerToServerPyPack
 from PyMongoDB.Protocol import MergeServerRecvProtocol
+import ShareDefine
+import CrossPlayer
+import DBDataMgr
+import CrossMsg
 #-------------------------------------------------------------------------------
 #---全局变量---
 
@@ -155,6 +159,28 @@
     return SendPackDict[head]
 
 #-------------------------------------------------------------------------------
+
+def ReadRecPyPackData(packBuff):
+    ## 根据收到的py包buff读取对应的包结构实例
+    try:
+        if len(packBuff) <= 1:
+            return
+        headData = packBuff[1] + packBuff[0]
+        curPackHead = CommFunc.ReadWORD(headData, 0)[0]
+        clientPack = RecievePackDict.get(curPackHead)
+        if not clientPack:
+            return
+        clientPack.ReadData(packBuff)
+        # 截断字符串
+        for key in dir(clientPack):
+            value = getattr(clientPack, key)
+            if isinstance(value, str):
+                setattr(clientPack, key, value.rstrip(chr(0x0)))
+        return clientPack
+    except Exception:
+        GameWorld.RaiseException("!!!python自定义封包解包失败\r\n%s" % traceback.format_exc())
+        return
+    
 ## 接收万能封包
 #  @param index 玩家索引
 #  @param tick 时间戳
@@ -383,23 +409,39 @@
         
     except Exception:
         GameWorld.RaiseException("!!!python自定义跨服封包解析失败\r\n%s" % traceback.format_exc())
-        return 
+        return
     
-    
-## 发送跨服包:服务器与服务器间的通信
-#  @param DirType  0全广播,1通知主服务器排除合服子服,2通知服务器包含合服子服, 3通知跨服服务器 
-#  @param serverList 服务器列表 格式如 [(1,10),50,(55,100)] 约定内部必须用元组 同其他跨服配表规则一致
-#  @param packBuffer 自定义封包字节字符串
-def SendCrossServerToServerPack(dirType, serverList, packBuffer):
+def GetSSPackDirType(serverType):
+    ## 根据服务器类型获取发送的目标类型
+    if serverType in [ShareDefine.serverType_Cross, ShareDefine.serverType_CrossCenter]:
+        return ShareDefine.dirType_Cross
+    if serverType in [ShareDefine.serverType_Main, ShareDefine.serverType_Child]:
+        return ShareDefine.dirType_Main
+    if serverType == ShareDefine.serverType_Battle:
+        return ShareDefine.dirType_Battle
+    return ShareDefine.dirType_All
+
+def SendCrossServerToServerPack(pack, serverList=None, dirType=None, serverType=None):
+    '''发送跨服包:服务器与服务器间的通信
+    @param pack 自定义封包实例
+    @param serverList 服务器列表 格式如 [(1,10),50,(55,100)] 约定内部必须用元组 同其他跨服配表规则一致
+    @param DirType  0全广播,1通知主服务器排除合服子服,2通知服务器包含合服子服, 3通知跨服服务器 
+    @param serverType  可只传入来源的服务器类型,适用于一对一通讯的回包
+    '''
+    if dirType == None and serverType == None:
+        return
+    if dirType == None:
+        dirType = GetSSPackDirType(serverType)
+    if serverList == None:
+        serverList = []
     recvPack = MergeServerRecvProtocol.tagLPStringData()
     recvPack.Type = CommonDefine.gstCrossServerToServerPack
     recvPack.DirType = dirType
     recvPack.ServerList = str(serverList)
     recvPack.ServerLen = len(recvPack.ServerList)
-    recvPack.Data = packBuffer
-    recvPack.DataLen = len(packBuffer)
-
+    recvPack.Data = pack.GetBuffer()
+    recvPack.DataLen = len(recvPack.Data)
     SendPyPackToServersRoute(recvPack.GetBuffer(), recvPack.GetLength())
-
+    return
 
 
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 9f92601..a523967 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -120,9 +120,11 @@
 import PlayerActTask
 import PlayerMail
 import DBDataMgr
+import PlayerViewCache
 import UpdatePlayerName
 import GameServerRefresh
 import IPY_ServerDefine
+import IPY_PlayerDefine
 import CommFunc
 from PyMongoDB import RecvPackToMapDB
 import GMT_BroadCast
@@ -136,6 +138,10 @@
 import PlayerMingge
 import TurnAttack
 import PlayerHJG
+import DBFamily
+import CrossPlayer
+import CrossMsg
+import CrossMgr
 import ChEquip
 
 import datetime
@@ -409,6 +415,7 @@
 def DoPlayerLogin(curPlayer, tick):
     #这里只做初始化逻辑
     curPlayer.SetDict(ChConfig.Def_PlayerKey_LoadMapIsLogin, 1)
+    CrossPlayer.GetCrossPlayerMgr().RegistPlayer(curPlayer.GetPlayerID())
     
     #通知时间
     Sync_PyServerDataTimeToClient(curPlayer)
@@ -471,9 +478,7 @@
     SyncGuideState(curPlayer)
     
     #上线检查一次装备属性
-    ItemControler.OnPlayerLogin(curPlayer)  
-    #更新服务器组ID
-    PlayerControl.UpdPlayerServerGroupID(curPlayer)
+    ItemControler.OnPlayerLogin(curPlayer)
     
     #上线学习技能
     #SkillCommon.PlayerLoginCheckLearnSkill(curPlayer)
@@ -737,16 +742,27 @@
         PlayerMingge.OnPlayerLogin(curPlayer)
         OpenServerActivity.OnPlayerLogin(curPlayer)
         PlayerPreset.OnPlayerLogin(curPlayer)
+        CrossPlayer.OnPlayerLogin(curPlayer)
         
         __OnFixVersion(curPlayer) # 修正线上玩家数据用,暂时放最后
         # 上线查询一次充值订单
         # curPlayer.SendDBQueryRecharge() 不查了,由在线轮询触发即可
+        SyncOnlineStateToCross(curPlayer, 1)
         
     # 通知GameServer地图最终登录成功了
     isMixServerFirstLogin = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_MixServerFirstLogin)
     msg = str([isMixServerFirstLogin])
     GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, "PlayerRealLoginOK", msg, len(msg))
     return
+
+#def C2S_PlayerLoginOK(playerID):
+#    ## 跨服登录成功后续处理
+#    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+#    if not curPlayer:
+#        return
+#    
+#    PlayerFamily.CrossServer_PlayerLogin(curPlayer)
+#    return
 
 def __OnFixVersion(curPlayer):
     ''' 修正线上玩家数据内容
@@ -781,6 +797,163 @@
     
     # 最终强制设置为最新版本号
     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FixVersion, sysFixVersion)
+    return
+
+def GetSyncCrossServerIDAndFuncInfo():
+    ## 获取需要同步给的目标跨服服务器ID及相关额外的功能信息
+    dataEx = {}
+    serverIDList = []
+    
+    # 公会
+    if DBFamily.IsFamilyCross():
+        crossFamilyServerID = DBDataMgr.GetFamilyMgr().GetCurCrossServerID()
+        if crossFamilyServerID > 0:
+            dataEx["crossFamilyServerID"] = crossFamilyServerID
+            if crossFamilyServerID not in serverIDList:
+                serverIDList.append(crossFamilyServerID)
+                
+    # 其他跨服功能
+    
+    return serverIDList, dataEx
+
+def OnPlayerBaseInfoChange(curPlayer, refreshType=0):
+    '''玩家基础信息变更同步更新其他功能,可以视为同步到以前的GameServer
+    除了相关基础值变化同步外,上下线状态变更也会附带基础信息的同步
+    '''
+    
+    playerID = curPlayer.GetPlayerID()
+    crossPlayerMgr = CrossPlayer.GetCrossPlayerMgr()
+    crossPlayer = crossPlayerMgr.FindCrossPlayer(playerID)
+    if not crossPlayer:
+        return
+    
+    # 公会成员
+    PlayerFamily.RefreshFamilyMember(crossPlayer)
+    
+    # 相关排行榜
+    if refreshType == IPY_PlayerDefine.CDBPlayerRefresh_PlayerName:
+        PlayerBillboard.UpdatePlayerBillboardName(curPlayer)
+        
+    # 社交名待更新
+    
+    # --------------------------------------------------------------
+    
+    # 同步给相关跨服
+    tick = GameWorld.GetGameWorld().GetTick()
+    lastSyncTick = curPlayer.GetDictByKey("S2C_PlayerBaseInfo")
+    if lastSyncTick and (tick - lastSyncTick) <= 2000:
+        # 短时间内只同步一次
+        return
+    curPlayer.SetDict("S2C_PlayerBaseInfo", tick)
+    
+    if refreshType == IPY_PlayerDefine.CDBPlayerRefresh_LV:
+        if curPlayer.GetLV() < 20:
+            return
+        
+    serverIDList = GetSyncCrossServerIDAndFuncInfo()[0]
+    if not serverIDList:
+        return
+    
+    playerID = curPlayer.GetPlayerID()
+    baseInfo = PlayerViewCache.GetPlayerBaseViewInfo(playerID, curPlayer)
+    dataMsg = {"baseInfo":baseInfo}
+    CrossMsg.SendToCrossServer(ShareDefine.S2C_PlayerBaseInfo, dataMsg, serverIDList, playerID)
+    return
+
+def S2C_PlayerBaseInfo(dataMsg, fromServerID, playerID):
+    isOnline = True
+    baseInfo = dataMsg["baseInfo"]
+    UpdCrossPlayerFromMainServer(fromServerID, playerID, baseInfo, isOnline)
+    return
+
+def UpdCrossPlayerFromMainServer(fromServerID, playerID, baseInfo, isOnline):
+    ## 更新CrossPlayer根据游戏服同步的信息
+    # @return: crossPlayer
+    crossPlayerMgr = CrossPlayer.GetCrossPlayerMgr()
+    crossPlayer = crossPlayerMgr.FindCrossPlayer(playerID)
+    if not crossPlayer:
+        crossPlayer = crossPlayerMgr.RegistPlayer(playerID) # 跨服不存在该玩家信息,直接注册,不用管是否在线
+        
+    # 信息更新
+    curCache = PlayerViewCache.UpdPlayerBaseViewInfo(playerID, baseInfo, not isOnline)
+    crossPlayer.UpdByViewCache(curCache, fromServerID)
+    
+    # 公会成员更新
+    PlayerFamily.RefreshFamilyMember(crossPlayer)
+    
+    # 如果是离线的处理
+    if not isOnline:
+        PlayerViewCache.OnCrossPlayerLogout(crossPlayer)
+        crossPlayerMgr.DeletePlayer(playerID)
+        
+    return crossPlayer
+
+def SyncOnlinePlayerToCross(toCrossServerID):
+    ## 重新同步在线玩家,确保目标服务器有跨服玩家基础数据,一般用于重连跨服、或某些跨服功能开启时重新同步确保目标服务器有本服在线玩家基本数据信息
+    playerManager = GameWorld.GetPlayerManager()
+    for i in xrange(playerManager.OnlineCount()):
+        curPlayer = playerManager.OnlineAt(i)
+        if not GameWorld.IsNormalPlayer(curPlayer):
+            continue
+        SyncOnlineStateToCross(curPlayer, 1, False, toCrossServerID)
+    return
+
+def SyncOnlineStateToCross(curPlayer, isOnline, isLoginout=True, toCrossServerID=0):
+    ## 同步玩家在线状态给相关跨服
+    # @param isLoginout: 是否上下线的,重新连上跨服时也会重新同步
+    
+    playerID = curPlayer.GetPlayerID()
+    
+    # 游戏服、跨服通用,当做以前GameServer的Player处理
+    crossPlayerMgr = CrossPlayer.GetCrossPlayerMgr()
+    # 离线直接清除
+    if not isOnline:
+        crossPlayerMgr.DeletePlayer(playerID)
+        
+    serverIDList, dataEx = GetSyncCrossServerIDAndFuncInfo()
+    if not serverIDList:
+        # 没有需要同步的跨服不处理
+        return
+    
+    if toCrossServerID:
+        if toCrossServerID not in serverIDList:
+            return
+        serverIDList = [toCrossServerID] # 如果有指定,指同步给该服
+        
+    baseInfo = PlayerViewCache.GetPlayerBaseViewInfo(playerID, curPlayer)
+    dataMsg = {"isOnline":isOnline, "isLoginout":isLoginout, "baseInfo":baseInfo}
+    dataMsg.update(dataEx)
+    CrossMsg.SendToCrossServer(ShareDefine.S2C_OnlineState, dataMsg, serverIDList, playerID)
+    return
+
+def S2C_OnlineState(dataMsg, fromServerID, playerID):
+    ## 收到游戏服玩家在线状态同步
+    isOnline = dataMsg["isOnline"]
+    isLoginout = dataMsg["isLoginout"]
+    baseInfo = dataMsg["baseInfo"]
+    
+    crossPlayer = UpdCrossPlayerFromMainServer(fromServerID, playerID, baseInfo, isOnline)
+    
+    # 其他跨服功能处理,暂时仅上下线时处理
+    curServerID = GameWorld.GetGameWorld().GetServerID()
+    if isLoginout:
+        # 公会
+        if "crossFamilyServerID" in dataMsg:
+            crossFamilyServerID = dataMsg["crossFamilyServerID"]
+            if curServerID == crossFamilyServerID:
+                if isOnline:
+                    PlayerFamily.OnCrossPlayerLogin(crossPlayer)
+                else:
+                    PlayerFamily.OnCrossPlayerLogout(crossPlayer)
+                    
+        # 最后处理缓存,先放在更新中处理删除,有问题再放后面
+        #if not isOnline:
+        #    PlayerViewCache.OnCrossPlayerLogout(crossPlayer)
+        #    CrossPlayer.GetCrossPlayerMgr().DeletePlayer(playerID)
+            
+    # 最后同步处理跨服登录成功
+    #if isLoginout and isOnline:
+    #    CrossMsg.SendToClientServer(ShareDefine.C2S_PlayerLoginOK, {}, [fromServerID], playerID)
     return
 
 ## 玩家扩展信息同步
@@ -1062,9 +1235,6 @@
     
     #检查更新总战斗力
     #PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer, True)
-    
-    #清除在本地图离线记录信息
-    PlayerControl.RemoveLeaveServerPlayerInfo(curPlayer.GetPlayerID())
     
     PyGameData.g_needRefreshMapServerState = True # 有玩家登录地图时设置需要刷新
     return
@@ -2135,6 +2305,8 @@
     #离线session
     EventReport.WriteEvent_session(curPlayer)
     
+    #最后同步跨服服务器
+    SyncOnlineStateToCross(curPlayer, 0)
     #需放最后
     PlayerOnline.OnPlayerLogoff(curPlayer)
     return
@@ -3740,7 +3912,7 @@
 #  @param curPlayer 
 #  @param tick 时间戳
 #  @return None
-def Sync_PyServerDataTimeToClient(curPlayer):
+def Sync_PyServerDataTimeToClient(curPlayer=None):
     # 服务器时间
     serverTime = GameWorld.GetCurrentTime()
     if not serverTime:
@@ -3755,10 +3927,13 @@
     serverDateTime.Minute = serverTime.minute
     serverDateTime.Second = serverTime.second
     serverDateTime.MicSecond = serverTime.microsecond
-    serverDateTime.CrossServerTime = GameWorld.GetCrossServerTimeStr()
+    serverDateTime.CrossServerTime = GameWorld.ChangeTimeNumToStr(CrossMgr.GetSSServerMgr().GetCrossTime())
     
     # 通知客户端同步时间
-    NetPackCommon.SendFakePack(curPlayer, serverDateTime)
+    if curPlayer:
+        NetPackCommon.SendFakePack(curPlayer, serverDateTime)
+    else:
+        NetPackCommon.SendFackPackOnline(serverDateTime)
     return
 
 ## 通知开服天数
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayer.py
new file mode 100644
index 0000000..e683567
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayer.py
@@ -0,0 +1,438 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.CrossPlayer
+#
+# @todo:跨服玩家
+# @author hxp
+# @date 2026-02-04
+# @version 1.0
+#
+# 详细描述: 跨服玩家,可视为以前GameServer的Player
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2026-02-04 19:00"""
+#-------------------------------------------------------------------------------
+
+import DBDataMgr
+import GameWorld
+import PyGameData
+import NetPackCommon
+import PlayerControl
+import PlayerOfflineSupport
+import ItemControler
+import ShareDefine
+import IPY_GameObj
+import CrossMsg
+import ChConfig
+
+class CrossPlayerObj():
+    ## 跨服在线玩家实例,不入库,由游戏服玩家登录同步,当做以前GameServer的Player处理,跨服及游戏服本服通用,方便统一逻辑
+    
+    def __init__(self, playerID):
+        self.__curPlayer = None # 仅游戏服在线时有值
+        self.__playerID = playerID
+        self.__playerName = ""
+        self.__serverID = 0
+        self.__mainServerID = 0
+        self.__familyID = 0
+        self.__realmLV = 0
+        return
+    
+    def SetPlayer(self, curPlayer):
+        self.__curPlayer = curPlayer
+        if curPlayer:
+            self.__serverID = GameWorld.GetPlayerServerID(curPlayer)
+            self.__mainServerID = GameWorld.GetGameWorld().GetServerID()
+            self.__familyID = curPlayer.GetFamilyID()
+        return
+    
+    def UpdByViewCache(self, curCache, fromServerID):
+        ## 收到同步信息时同步更新
+        self.SetPlayerName(curCache.GetPlayerName())
+        self.SetServerID(curCache.GetServerID())
+        self.SetMainServerID(fromServerID)
+        self.SetRealmLV(curCache.GetRealmLV())
+        # familyID 由公会模块管理
+        return
+    
+    def GetPlayer(self): return self.__curPlayer
+    def GetPlayerID(self): return self.__playerID
+    def GetServerID(self): return self.__serverID
+    def SetServerID(self, serverID): self.__serverID = serverID
+    def GetMainServerID(self): return self.__mainServerID
+    def SetMainServerID(self, mainServerID): self.__mainServerID = mainServerID
+    def GetFamilyID(self): return self.__familyID # 仅自身游戏服及公会所在跨服取得到值,其他服务器暂时无法取到
+    def SetFamilyID(self, familyID): self.__familyID = familyID
+    # 游戏服变更变更需要同步跨服以下值
+    def GetPlayerName(self): return self.__playerName if self.__playerName else (self.__curPlayer.GetPlayerName() if self.__curPlayer else "")
+    def SetPlayerName(self, playerName): self.__playerName = playerName
+    def GetRealmLV(self): return self.__realmLV if self.__realmLV else (self.__curPlayer.GetOfficialRank() if self.__curPlayer else 0)
+    def SetRealmLV(self, realmLV): self.__realmLV = realmLV
+    
+class CrossPlayerMgr():
+    ## 跨服玩家管理
+    
+    def __init__(self):
+        self.__crossPlayerDict = {} # 跨服在线玩家信息 {playerID:CrossPlayerObj, ...}
+        return
+    
+    def RegistPlayer(self, playerID):
+        cPlayer = None
+        if playerID in self.__crossPlayerDict:
+            cPlayer = self.__crossPlayerDict[playerID]
+        else:
+            cPlayer = CrossPlayerObj(playerID)
+            self.__crossPlayerDict[playerID] = cPlayer
+        cPlayer.SetPlayer(GameWorld.GetPlayerManager().FindPlayerByID(playerID))
+        return cPlayer
+    
+    def FindCrossPlayer(self, playerID):
+        cPlayer = None
+        if playerID in self.__crossPlayerDict:
+            cPlayer = self.__crossPlayerDict[playerID]
+        elif False: # 不在线不创建,不存在视为离线
+            cPlayer = CrossPlayerObj(playerID)
+        return cPlayer
+    
+    def DeletePlayer(self, playerID):
+        self.__crossPlayerDict.pop(playerID, None)
+        return
+    
+def GetCrossPlayerMgr():
+    mgr = PyGameData.g_crossPlayerMgr
+    if mgr == None:
+        mgr = CrossPlayerMgr()
+        PyGameData.g_crossPlayerMgr = mgr
+    return mgr
+
+def __checkCrossPlayer(crossPlayer):
+    ## 检查 crossPlayer 是否合法,防止误传入 IPY_Player 导致报错
+    if not crossPlayer:
+        return
+    if isinstance(crossPlayer, IPY_GameObj.IPY_Player):
+        GameWorld.ErrLog("__checkCrossPlayer isinstance IPY_Player")
+        return
+    return True
+
+def SendFakePackByFamily(familyID, clientPack, excludeIDList=None, parseFunc=None, *args):
+    if not clientPack:
+        return
+    family = DBDataMgr.GetFamilyMgr().FindFamily(familyID)
+    if not family:
+        return
+    
+    isCrossServer = GameWorld.IsCrossServer()
+    crossPlayerList = []
+    crossPlayerMgr = GetCrossPlayerMgr()
+    for index in range(family.GetCount()):
+        member = family.GetAt(index)
+        playerID = member.GetPlayerID()
+        if excludeIDList and playerID in excludeIDList:
+            continue
+        crossPlayer = crossPlayerMgr.FindCrossPlayer(playerID)
+        if not crossPlayer:
+            continue
+        if parseFunc and not parseFunc(member, *args):
+            continue
+        curPlayer = crossPlayer.GetPlayer()
+        if curPlayer: # 有玩家,一般只有游戏服有,可视为游戏服在线,直接发送
+            curPlayer.SendFakePack(clientPack.GetBuffer(), clientPack.GetLength())
+            continue
+        if isCrossServer:
+            crossPlayerList.append(crossPlayer)
+    if crossPlayerList:
+        SendFakePackToPlayerList(crossPlayerList, clientPack)
+    return
+
+def SendFakePackToPlayerList(crossPlayerList, clientPack):
+    '''给crossPlayer玩家发送封包,适用于接受的玩家封包数据一致的,跨服、游戏服通用
+    '''
+    if not clientPack:
+        return
+    
+    if not crossPlayerList:
+        return
+    
+    curServerID = GameWorld.GetGameWorld().GetServerID()
+    
+    crossServerPlayerDict = {}
+    for crossPlayer in crossPlayerList:
+        curPlayer = crossPlayer.GetPlayer()
+        if curPlayer: # 有玩家,一般只有游戏服有,可视为游戏服在线,直接发送
+            NetPackCommon.SendFakePack(curPlayer, clientPack)
+            continue
+        playerID = crossPlayer.GetPlayerID()
+        mainServerID = crossPlayer.GetMainServerID()
+        if mainServerID == curServerID:
+            #本游戏服又没有玩家的不处理
+            continue
+        if mainServerID not in crossServerPlayerDict:
+            crossServerPlayerDict[mainServerID] = []
+        playerIDList = crossServerPlayerDict[mainServerID]
+        if playerID not in playerIDList:
+            playerIDList.append(playerID)
+            
+    if not crossServerPlayerDict:
+        return
+    
+    packBuff, packLen = clientPack.GetBuffer(), clientPack.GetLength()
+    for mainServerID, playerIDList in crossServerPlayerDict.items():
+        dataMsg = {"playerIDList":playerIDList, "packBuff":packBuff, "packLen":packLen}
+        playerID = playerIDList[0]
+        CrossMsg.SendToClientServer(ShareDefine.C2S_SendFakePack, dataMsg, [mainServerID], playerID)
+        
+    return
+
+def SendFakePack(crossPlayer, clientPack):
+    if not clientPack:
+        return
+    if not __checkCrossPlayer(crossPlayer):
+        return
+    curPlayer = crossPlayer.GetPlayer()
+    if curPlayer: # 有玩家,一般只有游戏服有,可视为游戏服在线,直接发送
+        NetPackCommon.SendFakePack(curPlayer, clientPack)
+        return
+    
+    mainServerID = crossPlayer.GetMainServerID()
+    if mainServerID == GameWorld.GetGameWorld().GetServerID():
+        #本游戏服又没有玩家的不处理
+        return
+    
+    playerID = crossPlayer.GetPlayerID()
+    packBuff, packLen = clientPack.GetBuffer(), clientPack.GetLength()
+    dataMsg = {"playerIDList":[playerID], "packBuff":packBuff, "packLen":packLen}
+    CrossMsg.SendToClientServer(ShareDefine.C2S_SendFakePack, dataMsg, [mainServerID], playerID)
+    return
+
+def C2S_SendFakePack(dataMsg):
+    ## 游戏服收到跨服直接发送给玩家的封包
+    playerIDList = dataMsg["playerIDList"]
+    packBuff = dataMsg["packBuff"]
+    packLen = dataMsg["packLen"]
+    
+    playerManager = GameWorld.GetPlayerManager()
+    for playerID in playerIDList:
+        curPlayer = playerManager.FindPlayerByID(playerID)
+        if curPlayer == None:
+            continue
+        curPlayer.SendFakePack(packBuff, packLen)
+    return
+
+def NotifyCode(crossPlayer, msgMark, msgParamList=[]):
+    if not __checkCrossPlayer(crossPlayer):
+        return
+    curPlayer = crossPlayer.GetPlayer()
+    if curPlayer:
+        PlayerControl.NotifyCode(curPlayer, msgMark, msgParamList)
+        return
+    mainServerID = crossPlayer.GetMainServerID()
+    if mainServerID == GameWorld.GetGameWorld().GetServerID():
+        #本游戏服又没有玩家的不处理
+        return
+    playerID = crossPlayer.GetPlayerID()
+    dataMsg = {"msgMark":msgMark, "msgParamList":msgParamList}
+    CrossMsg.SendToClientServer(ShareDefine.C2S_NotifyCode, dataMsg, [mainServerID], playerID)
+    return
+
+def C2S_NotifyCode(dataMsg, playerID):
+    msgMark = dataMsg["msgMark"]
+    msgParamList = dataMsg["msgParamList"]
+    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+    if curPlayer:
+        PlayerControl.NotifyCode(curPlayer, msgMark, msgParamList)
+    return
+
+def OnPlayerLogin(curPlayer):
+    PlayerOfflineSupport.DoOfflineUnprocessed(curPlayer, "CostPlayerResources", __doCostPlayerResources)
+    PlayerOfflineSupport.DoOfflineUnprocessed(curPlayer, "GivePlayerResources", __doGivePlayerResources)
+    PlayerOfflineSupport.DoOfflineUnprocessed(curPlayer, "SetPlayerNomalDict", __doSetPlayerNomalDict)
+    return
+
+def CostPlayerResources(crossPlayer, eventName, costMoneyDict=None, costItemDict=None, drDict=None):
+    '''扣除跨服玩家资源
+    @param eventName: 消耗事件值
+    @param costMoneyDict: 扣除货币 {货币类型:消耗值, ...}
+    @param costItemDict: 扣除物品 {物品ID:个数, ...},暂不支持,有需要再扩展
+    @param drDict: 记录流向信息
+    '''
+    if not __checkCrossPlayer(crossPlayer):
+        return
+    
+    dataMsg = {"eventName":eventName}
+    if costMoneyDict:
+        dataMsg["costMoneyDict"] = costMoneyDict
+    if costItemDict:
+        dataMsg["costItemDict"] = costItemDict
+    if drDict:
+        dataMsg["drDict"] = drDict
+        
+    playerID = crossPlayer.GetPlayerID()
+    curPlayer = crossPlayer.GetPlayer()
+    if curPlayer:
+        __doCostPlayerResources(curPlayer, None, "CostPlayerResources", dataMsg)
+        return
+    mainServerID = crossPlayer.GetMainServerID()
+    if mainServerID == GameWorld.GetGameWorld().GetServerID():
+        #本游戏服又没有玩家的不处理
+        return
+    
+    CrossMsg.SendToClientServer(ShareDefine.C2S_CostPlayerResources, dataMsg, [mainServerID], playerID)
+    return
+
+def C2S_CostPlayerResources(dataMsg, playerID):
+    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+    if not curPlayer:
+        PlayerOfflineSupport.AddOfflineUnprocessed(playerID, "CostPlayerResources", dataMsg, outtimeDays=0)
+        return
+    __doCostPlayerResources(curPlayer, None, "CostPlayerResources", dataMsg)
+    return
+
+def __doCostPlayerResources(curPlayer, recData, eventName, eventData):
+    # recData 此功能中为None,不要用
+    playerID = curPlayer.GetPlayerID()
+    eventName = eventData["eventName"]
+    costMoneyDict = eventData.get("costMoneyDict")
+    costItemDict = eventData.get("costItemDict")
+    drDict = eventData.get("drDict", {})
+    
+    if costMoneyDict:
+        for moneyType, costMoney in costMoneyDict.items():
+            if not PlayerControl.PayMoney(curPlayer, moneyType, costMoney, eventName, drDict):
+                GameWorld.ErrLog("__doCostPlayerResources error! eventName=%s,moneyType=%s,costMoney=%s" 
+                                 % (eventName, moneyType, costMoney), playerID)
+                
+    if costItemDict:
+        pass # 待扩展
+    
+    return
+
+def GivePlayerResources(crossPlayer, awardItemList=None, moneyDict=None, eventName="", drDict=None):
+    '''给玩家资源
+    @param awardItemList: 给物品列表 [[itemID,itemCnt], ...]
+    @param moneyDict: 给货币 {货币类型:消耗值, ...}
+    '''
+    if not __checkCrossPlayer(crossPlayer):
+        return
+    
+    dataMsg = {"eventName":eventName}
+    if awardItemList:
+        dataMsg["awardItemList"] = awardItemList
+    if moneyDict:
+        dataMsg["moneyDict"] = moneyDict
+    if drDict:
+        dataMsg["drDict"] = drDict
+        
+    playerID = crossPlayer.GetPlayerID()
+    curPlayer = crossPlayer.GetPlayer()
+    if curPlayer:
+        __doGivePlayerResources(curPlayer, None, "GivePlayerResources", dataMsg)
+        return
+    mainServerID = crossPlayer.GetMainServerID()
+    if mainServerID == GameWorld.GetGameWorld().GetServerID():
+        #本游戏服又没有玩家的不处理
+        return
+    
+    CrossMsg.SendToClientServer(ShareDefine.C2S_GivePlayerResources, dataMsg, [mainServerID], playerID)
+    return
+
+def C2S_GivePlayerResources(dataMsg, playerID):
+    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+    if not curPlayer:
+        PlayerOfflineSupport.AddOfflineUnprocessed(playerID, "GivePlayerResources", dataMsg, outtimeDays=0)
+        return
+    __doGivePlayerResources(curPlayer, None, "GivePlayerResources", dataMsg)
+    return
+
+def __doGivePlayerResources(curPlayer, recData, eventName, eventData):
+    # recData 此功能中为None,不要用
+    #playerID = curPlayer.GetPlayerID()
+    GameWorld.DebugLog("__doGivePlayerResources %s, %s" % (eventName, eventData))
+    eventName = eventData["eventName"]
+    awardItemList = eventData.get("awardItemList", [])
+    moneyDict = eventData.get("moneyDict", {})
+    drDict = eventData.get("drDict", {})
+    
+    GameWorld.DebugLog("awardItemList=%s" % awardItemList)
+    if awardItemList:
+        itemDRDict = {}
+        itemDRDict.update(drDict)
+        ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=[eventName, False, itemDRDict], isNotifyAward=False)
+        
+    if moneyDict:
+        moneyRDict = {}
+        moneyRDict.update(drDict)
+        for moneyType, moneyValue in moneyDict.items():
+            PlayerControl.GiveMoney(curPlayer, moneyType, moneyValue, eventName, moneyRDict)
+            
+    ItemControler.NotifyGiveAwardInfo(curPlayer, awardItemList, eventName, moneyInfo=moneyDict)
+    return
+
+def SetPlayerNomalDict(crossPlayer, setDict, isDayReset=False):
+    '''扣除跨服玩家资源
+    @param setDict: 要设置的NomalDictSetProperty对应key:value {key:value, ...}
+    @param isDayReset: 字典是否每日重置的
+    '''
+    if not __checkCrossPlayer(crossPlayer):
+        return
+    playerID = crossPlayer.GetPlayerID()
+    curPlayer = crossPlayer.GetPlayer()
+    dataMsg = {"setDict":setDict}
+    if curPlayer:
+        # 游戏服curPlayer在线的直接当做永久的处理,直接设置
+        __doSetPlayerNomalDict(curPlayer, None, "SetPlayerNomalDict", dataMsg)
+        return
+    mainServerID = crossPlayer.GetMainServerID()
+    if mainServerID == GameWorld.GetGameWorld().GetServerID():
+        GameWorld.ErrLog("CrossPlayer设置字典时本服玩家不存在! setDict=%s" % setDict, playerID)
+        return
+    
+    resetType = ""
+    if isDayReset:
+        resetType = "Day"
+    if resetType != "":
+        centerEventValue = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_CrossCenterEvent)
+        dataMsg.update({"resetType":resetType, "centerEventValue":centerEventValue})
+    CrossMsg.SendToClientServer(ShareDefine.C2S_SetPlayerNomalDict, dataMsg, [mainServerID], playerID)
+    return
+
+def C2S_SetPlayerNomalDict(dataMsg, playerID):
+    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+    if not curPlayer:
+        PlayerOfflineSupport.AddOfflineUnprocessed(playerID, "SetPlayerNomalDict", dataMsg, outtimeDays=0)
+        return
+    __doSetPlayerNomalDict(curPlayer, None, "SetPlayerNomalDict", dataMsg)
+    return
+
+def __doSetPlayerNomalDict(curPlayer, recData, eventName, eventData):
+    # recData 此功能中为None,不要用
+    playerID = curPlayer.GetPlayerID()
+    setDict = eventData["setDict"]
+    resetType = eventData.get("resetType", "")
+    # 非永久设置的,验证时效性
+    if resetType != "":
+        centerEventValue = eventData.get("centerEventValue", 0)
+        playerEventValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_OnCrossEvent)
+        centerEventTime = GameWorld.ChangeStrToDatetime("%s:%02d:%02d" % centerEventValue, ChConfig.TYPE_Time_Format_YmdHMS)
+        playerEventTime = GameWorld.ChangeStrToDatetime("%s:%02d:%02d" % playerEventValue, ChConfig.TYPE_Time_Format_YmdHMS)
+        
+        center_Day = centerEventTime.day
+        center_Month = centerEventTime.month
+        center_Year = centerEventTime.year
+        
+        player_Day = playerEventTime.day
+        player_Month = playerEventTime.month
+        player_Year = playerEventTime.year
+        
+        # 每日重置的,验证是否同一天
+        if resetType == "Day":
+            if (center_Day != player_Day or center_Month != player_Month or center_Year != player_Year):
+                GameWorld.Log("非同一天了不再设置玩家该key值! setDict=%s" % setDict, playerID)
+                return
+            
+    for key, value in setDict.items():
+        PlayerControl.NomalDictSetProperty(curPlayer, key, value)
+        
+    return
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py
index ca7ce8a..5bcb5c8 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py
@@ -61,7 +61,7 @@
 def GetCrossZoneIpyDataByServerGroupID(mapID, serverGroupID):
     ## 获取跨服分区
     zoneTypeName = ChConfig.Def_CrossZoneTypeName.get(mapID, "CrossZoneComm")
-    crossZoneName = GameWorld.GetCrossZoneName()
+    crossZoneName = "" #GameWorld.GetCrossZoneName()
     ipyDataList = IpyGameDataPY.GetIpyGameDataByCondition(zoneTypeName, {"CrossZoneName":crossZoneName}, True)
     if not ipyDataList:
         return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
index b4a2a29..62fadad 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
@@ -26,13 +26,20 @@
 
 import time
 
-def OnDay():
+def OnDay(centerEventValue=0):
+    # @param centerEventValue: 跨服中心事件值,不为0时代表是跨服中心同步的事件,只处理跨服功能需要处理的逻辑
     
     drBillboardTypeList = []
-    if GameWorld.IsCrossServer():
+    if centerEventValue:
+        if not GameWorld.IsCrossServer():
+            # 跨服事件只跨服服务器处理
+            return
         drBillboardTypeList = ShareDefine.CrossBillboardTypeList
+        eventName = "OnDay%s" % centerEventValue
+        
     else:
         drBillboardTypeList = IpyGameDataPY.GetFuncEvalCfg("BillboardSet", 1)
+        eventName = "OnDay"
         
     billboardMgr = DBDataMgr.GetBillboardMgr()
     for billboardType in drBillboardTypeList:
@@ -41,7 +48,7 @@
         groupList = billboardMgr.GetBillboardGroupList(billboardType)
         for billboardType, groupValue1, groupValue2 in groupList:
             billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2)
-            billboardObj.SaveDRData("OnDay")
+            billboardObj.SaveDRData(eventName)
             
     return
 
@@ -91,10 +98,6 @@
 
 def UpdatePyPetBillboard(curPlayer, isForceUpdate=False, isUpdateTotal=True):
     ## 更新宠物排行榜
-    return
-
-def UpdateRealmBillboard(curPlayer):
-    ##境界榜
     return
 
 #def __CanPlayerBillboardComm(curPlayer):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index 7e95c2f..aa3d385 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -31,6 +31,7 @@
 import PlayerViewCache
 import PlayerBillboard
 import GameServerRefresh
+import IPY_PlayerDefine
 import IPY_GameWorld
 import ChPyNetSendPack
 import NetPackCommon
@@ -233,7 +234,7 @@
 #  @remarks 
 def FamilyNotify(familyID, msgMark, msgParamList=[]):
     #GameWorld.GetPlayerManager().BroadcastCountry_NotifyCode(0, familyID, msgMark, __GetNotifyCodeList(msgParamList))
-    PlayerFamily.NotifyAllFamilyMemberMsg(familyID, msgMark, msgParamList)
+    #PlayerFamily.NotifyAllFamilyMemberMsg(familyID, msgMark, msgParamList)
     return
 
 #---------------------------------------------------------------------
@@ -1140,40 +1141,8 @@
     #召唤兽死亡
     KillPlayerSummonNPC(curPlayer)
     #更新从本地图离线信息
-    PyGameData.g_disconnectPlayer[curPlayer.GetPlayerID()] = [tick, curPlayer.GetPosX(), curPlayer.GetPosY()]
-    GameWorld.DebugLog("玩家从本地图离线: %s" % PyGameData.g_disconnectPlayer, curPlayer.GetPlayerID())
+    GameWorld.DebugLog("玩家从本地图离线", curPlayer.GetPlayerID())
     return
-
-def GetPlayerLeaveServerTick(playerID):
-    # 获取玩家从本地图中离线时的tick, 最大支持1小时, 如果有需要大于1小时的请调整超时限制
-    # 注: 返回值为0时,只能代表玩家不是在本地图离线1小时内,并不能代表玩家当前是否在线状态,可能在其他地图
-    if playerID not in PyGameData.g_disconnectPlayer:
-        return 0
-    return PyGameData.g_disconnectPlayer[playerID][0]
-
-def GetPlayerLeaveServerPos(playerID):
-    # 获取玩家从本地图中离线时的坐标
-    # 注:使用本函数时,一定要先使用函数 GetPlayerLeaveServerTick 确保是从本地图中离线的才可使用
-    # @return: posX, posY
-    if playerID not in PyGameData.g_disconnectPlayer:
-        return 0, 0
-    return PyGameData.g_disconnectPlayer[playerID][1:3]
-
-def RemoveTimeoutLeaveServerPlayerInfo(tick):
-    # 暂定每天凌晨5点执行一次
-    for playerID, leaveInfo in PyGameData.g_disconnectPlayer.items():
-        leaveTick = leaveInfo[0]
-        if tick - leaveTick > 3600000: # 清除超时1小时的记录
-            PyGameData.g_disconnectPlayer.pop(playerID)
-    return
-
-def RemoveLeaveServerPlayerInfo(playerID):
-    # 上线移除在本地图下线的记录
-    if playerID in PyGameData.g_disconnectPlayer:
-        PyGameData.g_disconnectPlayer.pop(playerID)
-        GameWorld.DebugLog("进入本地图,移除上次在本地图离线记录!", playerID)
-    return
-
 
 ##清除回收战
 # @param None
@@ -3422,6 +3391,7 @@
                 curPlayer.SetLV(aftLV, False) # 这里不再通知GameServer
                 #PlayerTongTianLing.AddTongTianTaskValue(curPlayer, ChConfig.TTLTaskType_LVUp, aftLV - befLV)
                 PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_LV)
+                ChPlayer.OnPlayerBaseInfoChange(curPlayer, IPY_PlayerDefine.CDBPlayerRefresh_LV) # 等级
                 
             #if aftFreePoint > befFreePoint:
             #    curPlayer.SetFreePoint(aftFreePoint)
@@ -4337,7 +4307,7 @@
 def GetTitleID(curPlayer): return curPlayer.GetExAttr3()
 def SetTitleID(curPlayer, titleID):
     curPlayer.SetExAttr3(titleID, False, False)
-    PlayerFamily.RefreshFamilyMember(curPlayer)
+    ChPlayer.OnPlayerBaseInfoChange(curPlayer, IPY_PlayerDefine.CDBPlayerRefresh_ExAttr3) # 称号
     return
 
 ## 协助目标玩家ID
@@ -4419,19 +4389,7 @@
     return
 
 ## 玩家所属服务器组ID
-def GetPlayerServerGroupID(curPlayer): return curPlayer.GetExAttr13()
-def UpdPlayerServerGroupID(curPlayer):
-    # 更新自己的服务器组ID, 跨服服务器不处理
-    if GameWorld.IsCrossServer():
-        return
-    serverGroupID = GameWorld.GetServerGroupID()
-    if not serverGroupID:
-        return
-    playerServerGroupID = curPlayer.GetExAttr13()
-    if playerServerGroupID != serverGroupID:
-        curPlayer.SetExAttr13(serverGroupID, False, True)
-        GameWorld.DebugLog("更新玩家所属服务器组ID: serverGroupID=%s" % serverGroupID)
-    return
+def GetPlayerServerGroupID(curPlayer): return 0
 
 # 境界难度等级
 def GetRealmDifficulty(curPlayer): return 0
@@ -4477,6 +4435,7 @@
     #PlayerBillboard.UpdatePlayerFPTotalBillboard(curPlayer)
     #if beforeFightPower != totalFightPower:
     #    CrossPlayerData.OnPlayerFightPowerChange(curPlayer)
+    ChPlayer.OnPlayerBaseInfoChange(curPlayer, IPY_PlayerDefine.CDBPlayerRefresh_FightPower) # 战力
     return
 
 ## 设置模块战斗力,支持超过20E = 模块公式战力 + 技能附加战力 + 其他附加战力
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py
index d4335a8..d2a64f0 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCrossRealmPK.py
@@ -86,7 +86,7 @@
 
 def GetCrossPKDanAwardIpyData(seasonID, awardDanLV, isLog):
     ## 获取跨服段位奖励配置信息
-    crossZoneName = GameWorld.GetCrossZoneName()
+    crossZoneName = "" #GameWorld.GetCrossZoneName()
     danLVAwardIpyData = IpyGameDataPY.GetIpyGameDataNotLog("CrossRealmPKDanAward", crossZoneName, seasonID, awardDanLV)
     if not danLVAwardIpyData:
         danLVAwardIpyData = IpyGameDataPY.GetIpyGameDataNotLog("CrossRealmPKDanAward", "", seasonID, awardDanLV)
@@ -681,7 +681,7 @@
                                                       "order":order, "danLV":danLV, "mapSeasonID":mapSeasonID}
     if order > 0:
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CrossPK_SeasonOrder % seasonID, order)
-        crossZoneName = GameWorld.GetCrossZoneName()
+        crossZoneName = "" #GameWorld.GetCrossZoneName()
         seasonOrderAwardIpyData = IpyGameDataPY.GetIpyGameDataNotLog("CrossRealmPKOrderAward", crossZoneName, seasonID)
         if not seasonOrderAwardIpyData:
             seasonOrderAwardIpyData = IpyGameDataPY.GetIpyGameData("CrossRealmPKOrderAward", "", seasonID)
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 cc22c03..1da98ec 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -90,16 +90,36 @@
 import PlayerHero
 import PlayerTree
 import PlayerLLMJ
+import DBDataMgr
 
 import datetime
 import time
 
-## 原GameServer通知的
-def GameServer_OnDay(index, tick): return
-def GameServer_OnHour(index, tick): return
-def GameServer_OnWeek(index, tick): return
-def GameServer_OnMonth(index, tick): return
-def GameServer_OnYear(index, tick): return
+def DoLogic_CrossCenterOnDay(centerEventValue):
+    '''收到跨服中心同步的onday事件,注意这里本服的触发跨服中心onday事件
+    事件由跨服中心统一管理,跨服中心onday后,会广播同步给所有服务器,包含其他跨服服务器及游戏服
+    由于是由跨服中心统一调度的,所以其他服务器可以各自处理各自跨服功能本服的跨服onday逻辑
+    【注】常规处理可以无视功能所在跨服与游戏服的onday触发先后顺序,各自处理各自的逻辑即可
+    如功能所在跨服管理功能的公共跨服数据onday,游戏服管理玩家自身的onday
+    如果个别功能需要先处理公共数据再处理玩家自身数据的,则由功能自己管理,公共数据处理完毕后再同步给对应的游戏服
+    '''
+    GameWorld.Log("CrossCenterOnDay -> centerEventValue=%s" % centerEventValue)      
+    
+    PlayerFamily.FamilyCrossCenterOnDay()
+    
+    # 其他跨服功能
+    
+    # 游戏服额外处理玩家
+    if GameWorld.IsMainServer():
+        playerManager = GameWorld.GetPlayerManager()
+        for i in xrange(playerManager.OnlineCount()):
+            curPlayer = playerManager.OnlineAt(i)
+            if not GameWorld.IsNormalPlayer(curPlayer):
+                continue
+            PlayerOnCrossCenterEvent(curPlayer, centerEventValue)
+            
+    PlayerBillboard.OnDay(centerEventValue)
+    return
 
 def DoLogic_OnDay(tick):
     GameWorld.Log("MapServer -> OnDay!")
@@ -123,9 +143,14 @@
         PlayerOnDay(curPlayer)
         
     PlayerMail.OnDayEx()
-    PlayerControl.RemoveTimeoutLeaveServerPlayerInfo(tick)
     PlayerBillboard.OnDay()
     PlayerViewCache.OnDay()
+    return
+
+def DoLogic_CrossCenterOnHour(centerEventValue):
+    GameWorld.Log("CrossCenterOnHour -> centerEventValue=%s" % centerEventValue)      
+    
+    PlayerFamily.FamilyCrossCenterOnHour()
     return
 
 def DoLogic_OnHour(tick):
@@ -221,6 +246,45 @@
     return
 
 #--------------------------------------------------------
+def PlayerOnCrossCenterEvent(curPlayer, centerEventValue=0):
+    ## 跨服中心过天
+    if not centerEventValue:
+        centerEventValue = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_CrossCenterEvent)
+    playerEventValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_OnCrossEvent)
+    if not playerEventValue:
+        playerEventValue = centerEventValue
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_OnCrossEvent, centerEventValue)
+        
+    if playerEventValue == centerEventValue:
+        return
+    
+    centerEventTime = GameWorld.ChangeStrToDatetime("%s:%02d:%02d" % centerEventValue, ChConfig.TYPE_Time_Format_YmdHMS)
+    playerEventTime = GameWorld.ChangeStrToDatetime("%s:%02d:%02d" % playerEventValue, ChConfig.TYPE_Time_Format_YmdHMS)
+    
+    center_Day = centerEventTime.day
+    center_Month = centerEventTime.month
+    center_Year = centerEventTime.year
+    
+    player_Day = playerEventTime.day
+    player_Month = playerEventTime.month
+    player_Year = playerEventTime.year
+    
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_OnCrossEvent, centerEventValue)
+    
+    if (center_Day != player_Day or center_Month != player_Month or center_Year != player_Year):
+        PlayerCrossCenterOnDay(curPlayer, centerEventValue)
+        
+    return
+
+def PlayerCrossCenterOnDay(curPlayer, centerEventValue):
+    playerID = curPlayer.GetPlayerID()
+    GameWorld.Log("PlayerCrossCenterOnDay! centerEventValue=%s" % (centerEventValue), playerID)
+    
+    PlayerFamily.PlayerCrossCenterOnDay(curPlayer)
+    
+    GameWorld.Log("PlayerOnDayCross OK!", playerID)
+    return
+
 def PlayerOnDay(curPlayer):
     #记录玩家字典值,待初始化后执行
     if not curPlayer.GetGameServerInitOK():
@@ -239,7 +303,6 @@
     ChPlayer.Sync_OpenServerDay(curPlayer)
     
     __DoPlayerOnDay(curPlayer, ShareDefine.Def_OnEventType)
-    __DoPlayerOnDay(curPlayer, ShareDefine.Def_OnEventTypeEx)
     
     GameWorld.Log("PlayerOnDay OK!", playerID)
     return
@@ -250,60 +313,60 @@
         return
     
     # 常规过天
-    if onEventType == ShareDefine.Def_OnEventType:
-        GameFuncComm.DoFuncOpenLogic(curPlayer)
-        #清空每日事件奖励
-        curPlayer.SetDayProcessGameEventCount(0)
-        
-        #OnDay时清除每日签到的信息
-        PlayerSignDay.SignDayOnDay(curPlayer)
-        # 累计登陆礼包登陆次数刷新
-        PlayerLoginDayAward.NotePlayerLoginDayCnt(curPlayer)
-        
-        #------------------------------------------------------------------------------ 
-        
-        PlayerCoin.OnDay(curPlayer)
-        PlayerTree.PlayerOnDay(curPlayer)
-        #投资
-        PlayerGoldInvest.OnDay(curPlayer)
-        #战令
-        PlayerZhanling.OnDay(curPlayer)
-        #寻宝
-        PlayerTreasure.OnDay(curPlayer)
-        PlayerGoldGift.OnDay(curPlayer)
-        #转盘
-        PlayerActTurntable.PlayerOnDay(curPlayer)
-        #情缘
-        PlayerLove.DoPlayerOnDay(curPlayer)
-        #仙宫
-        PlayerXiangong.PlayerOnDay(curPlayer)
-        PlayerControl.PlayerOnDay(curPlayer)
-        ChPlayer.PlayerOnDay(curPlayer)
-        PlayerActivity.OnDay(curPlayer)
-        PlayerLLMJ.PlayerOnDay(curPlayer)
-        FunctionNPCCommon.ShopItemOnDay(curPlayer)
-        OpenServerActivity.PlayerOnDay(curPlayer)
-        
+    #if onEventType == ShareDefine.Def_OnEventType:
+    GameFuncComm.DoFuncOpenLogic(curPlayer)
+    #清空每日事件奖励
+    curPlayer.SetDayProcessGameEventCount(0)
+    
+    #OnDay时清除每日签到的信息
+    PlayerSignDay.SignDayOnDay(curPlayer)
+    # 累计登陆礼包登陆次数刷新
+    PlayerLoginDayAward.NotePlayerLoginDayCnt(curPlayer)
+    
+    #------------------------------------------------------------------------------ 
+    
+    PlayerCoin.OnDay(curPlayer)
+    PlayerTree.PlayerOnDay(curPlayer)
+    #投资
+    PlayerGoldInvest.OnDay(curPlayer)
+    #战令
+    PlayerZhanling.OnDay(curPlayer)
+    #寻宝
+    PlayerTreasure.OnDay(curPlayer)
+    PlayerGoldGift.OnDay(curPlayer)
+    #转盘
+    PlayerActTurntable.PlayerOnDay(curPlayer)
+    #情缘
+    PlayerLove.DoPlayerOnDay(curPlayer)
+    #仙宫
+    PlayerXiangong.PlayerOnDay(curPlayer)
+    PlayerControl.PlayerOnDay(curPlayer)
+    ChPlayer.PlayerOnDay(curPlayer)
+    PlayerActivity.OnDay(curPlayer)
+    PlayerLLMJ.PlayerOnDay(curPlayer)
+    FunctionNPCCommon.ShopItemOnDay(curPlayer)
+    OpenServerActivity.PlayerOnDay(curPlayer)
+    
     # 特殊时间点X点过天
-    elif onEventType == ShareDefine.Def_OnEventTypeEx:
-        PlayerHero.PlayerOnDay(curPlayer)
-        # 仙盟过天
-        PlayerFamily.PlayerOnDay(curPlayer)
-        # 重置物品每日使用次数
-        ChItem.ResetItemUseCntToday(curPlayer)
-        # 极品白拿
-        PlayerFreeGoods.OnDay(curPlayer)
-        #采集次数重置
-        NPCCommon.PlayerOnDay(curPlayer)
-        #跨服竞技场
-        PlayerCrossRealmPK.DoPlayerOnDay(curPlayer)
-        #跨服排位
-        PlayerCrossChampionship.DoPlayerOnDay(curPlayer)
-        #竞技场
-        PlayerArena.OnDayEx(curPlayer)
-        #特殊时间点过天的,一般是游戏功能,此时立即同步一次跨服玩家数据
-        CrossPlayerData.SendMergePlayerDataNow(curPlayer)
-        
+    #elif onEventType == ShareDefine.Def_OnEventTypeEx:
+    PlayerHero.PlayerOnDay(curPlayer)
+    # 仙盟过天
+    PlayerFamily.PlayerOnDay(curPlayer)
+    # 重置物品每日使用次数
+    ChItem.ResetItemUseCntToday(curPlayer)
+    # 极品白拿
+    PlayerFreeGoods.OnDay(curPlayer)
+    #采集次数重置
+    NPCCommon.PlayerOnDay(curPlayer)
+    #跨服竞技场
+    PlayerCrossRealmPK.DoPlayerOnDay(curPlayer)
+    #跨服排位
+    PlayerCrossChampionship.DoPlayerOnDay(curPlayer)
+    #竞技场
+    PlayerArena.OnDayEx(curPlayer)
+    #特殊时间点过天的,一般是游戏功能,此时立即同步一次跨服玩家数据
+    CrossPlayerData.SendMergePlayerDataNow(curPlayer)
+    
     # 以下为支持两种重置模式切换配置的
     FBCommon.FBOnDay(curPlayer, onEventType)
     #许愿池
@@ -402,7 +465,6 @@
     elif onEventType == ShareDefine.Def_OnEventTypeEx:
         #竞技场
         PlayerArena.OnWeekEx(curPlayer)
-        PlayerFamily.OnWeekEx(curPlayer)
         
     # 以下为支持两种重置模式切换配置的
     FBCommon.FBOnWeek(curPlayer, onEventType)
@@ -692,6 +754,9 @@
     #OnYear事件
     if __Get_Can_OnYear(curPlayer):
         PlayerOnYear(curPlayer)
+        
+    # 跨服事件检查
+    PlayerOnCrossCenterEvent(curPlayer)
     return
 
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py
index 9f7e597..c125f37 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFace.py
@@ -16,9 +16,10 @@
 #-------------------------------------------------------------------------------
 
 import GameWorld
-import PlayerFamily
+import ChPlayer
 import PlayerControl
 import IPY_GameWorld
+import IPY_PlayerDefine
 import ChPyNetSendPack
 import IpyGameDataPY
 import NetPackCommon
@@ -148,7 +149,7 @@
         randFace = random.choice(defaultFaceIDList) if defaultFaceIDList else 0
         curPlayer.SetFace(randFace)
         GameWorld.DebugLog("玩家佩戴的头像被删除,随机重置默认头像! randFace=%s" % randFace, playerID)
-        PlayerFamily.RefreshFamilyMember(curPlayer)
+        ChPlayer.OnPlayerBaseInfoChange(curPlayer, IPY_PlayerDefine.CDBPlayerRefresh_Face) # 头像到期重置
         
     if isRefreshAttr:
         RefreshFaceAttr(curPlayer)
@@ -199,7 +200,7 @@
         return    
     GameWorld.DebugLog("头像幻化! faceID=%s" % (faceID), playerID)
     curPlayer.SetFace(faceID)
-    PlayerFamily.RefreshFamilyMember(curPlayer)
+    ChPlayer.OnPlayerBaseInfoChange(curPlayer, IPY_PlayerDefine.CDBPlayerRefresh_Face) # 修改头像
     return
 
 def OnFaceStarUP(curPlayer, faceID):
@@ -353,7 +354,7 @@
         randFacePic = random.choice(defaultFacePicIDList) if defaultFacePicIDList else 0
         curPlayer.SetFacePic(randFacePic)
         GameWorld.DebugLog("玩家佩戴的头像框过期,随机重置默认头像框! randFacePic=%s" % randFacePic, playerID)
-        PlayerFamily.RefreshFamilyMember(curPlayer)
+        ChPlayer.OnPlayerBaseInfoChange(curPlayer, IPY_PlayerDefine.CDBPlayerRefresh_HairColor) # 头像框到期重置
         
     if isRefreshAttr:
         RefreshFacePicAttr(curPlayer)
@@ -399,7 +400,7 @@
         return    
     GameWorld.DebugLog("头像框幻化! facePicID=%s" % (facePicID), playerID)
     curPlayer.SetFacePic(facePicID)
-    PlayerFamily.RefreshFamilyMember(curPlayer)
+    ChPlayer.OnPlayerBaseInfoChange(curPlayer, IPY_PlayerDefine.CDBPlayerRefresh_HairColor) # 修改头像框
     return
 
 def OnFacePicStarUP(curPlayer, facePicID):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
index 9b03311..e8e095a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
@@ -28,12 +28,13 @@
 import IPY_PlayerDefine
 import IpyGameDataPY
 import IPY_GameWorld
-import ItemControler
-import GameFuncComm
 import PlayerMail
 import PlayerTask
-import DBDataMgr
+import CrossPlayer
 import DirtyList
+import DBDataMgr
+import DBFamily
+import CrossMsg
 
 import random
 import time
@@ -42,24 +43,7 @@
 
 Def_CreatFamily_MaxStr = 33
 
-#仙盟变更类型
-FamilyChangeTypes = (
-FamilyChangeType_None,
-FamilyChangeType_MemJoin, # 成员加入 1
-FamilyChangeType_MemLeave, # 成员退出 2
-FamilyChangeType_JoinSet, # 收人设置修改 3
-FamilyChangeType_Broadcast, # 公告修改 4
-FamilyChangeType_EChange, # 徽章修改 5
-FamilyChangeType_LeaderChange, # 盟主变更 6
-FamilyChangeType_MemFmlvChange, # 成员职位变更 7
-FamilyChangeType_MemLogin, # 成员上线 8
-FamilyChangeType_MemLogout, # 成员离线9
-FamilyChangeType_FamilyLVExp, # 仙盟等级经验变更 10
-FamilyChangeType_MemContrib, # 成员贡献变更 11
-FamilyChangeType_OnDay, # 过天 12
-) = range(13)
-
-#仙盟权限
+#公会权限
 (
 FamilyPowerID_Call,         #招人 1
 FamilyPowerID_ChangeFmlv,   #变更职位 2
@@ -67,68 +51,133 @@
 FamilyPowerID_Kick,         #踢人 4
 ) = range(1, 1 + 4)
 
-#仙盟职位对应人数设置属性名
+#公会职位对应人数设置属性名
 Def_FmlSetAttrName = {
                       IPY_PlayerDefine.fmlMember:"MemberMax",
                       IPY_PlayerDefine.fmlCounsellor:"EliteMax",
                       IPY_PlayerDefine.fmlViceLeader:"DeputyLeaderMax",
                       }
 
-def FamilyOnDay():
+def GetRenameTime(family): return family.GetExtra1()
+def SetRenameTime(family, renameTime): return family.SetExtra1(renameTime)
+
+def OnMinute():
+    #战力刷新在DBFamily.OnMinute
     if GameWorld.IsCrossServer():
+        pass
+    elif not GameWorld.IsMainServer() or DBFamily.IsFamilyCross():
         return
-    
-    familyManager = DBDataMgr.GetFamilyMgr()
-    for i in range(0, familyManager.GetCount()):
-        family = familyManager.GetAt(i)
-        familyID = family.GetID()
-        
-        PlayerFamilyZhenbaoge.OnDay(family)
-        PlayerFamilyTaofa.OnDay(family)
-        
-        for index in xrange(family.GetCount()):
-            member = family.GetAt(index)
-            # 重置成员日信息
-            member.SetContribDay(0)
-            member.SetDonateCntDay(0)
-            
-        Broadcast_FamilyChange(familyID, FamilyChangeType_OnDay)
-        
+    PlayerFamilyEmblem.CheckExpireEmblem()
+    return
+
+def FamilyCrossCenterOnHour():
+    if GameWorld.IsCrossServer():
+        __doFamilyOnHour()
     return
 
 def FamilyOnHour():
+    if not GameWorld.IsMainServer() or DBFamily.IsFamilyCross():
+        # 非游戏服或本服已跨服互通了不处理
+        return
+    __doFamilyOnHour()
+    return
+
+def __doFamilyOnHour():
+    familyManager = DBDataMgr.GetFamilyMgr()
+    for zoneID in familyManager.GetZoneIDListThisServer():
+        zoneMgr = familyManager.GetZoneFamilyMgr(zoneID)
+        for i in range(0, zoneMgr.GetCount()):
+            family = zoneMgr.GetAt(i)
+            #自动传位
+            __AutoChangeLeader(family)
+    return
+
+def FamilyCrossCenterOnDay():
     if GameWorld.IsCrossServer():
+        __doFamilyOnDay()
+    return
+
+def FamilyOnDay():
+    ## 本服时间自己触发的onday逻辑
+    
+    if not GameWorld.IsMainServer() or DBFamily.IsFamilyCross():
+        # 非游戏服或本服已跨服互通了不处理
         return
     
+    __doFamilyOnDay()
+    DBFamily.CheckCrossFamilyTransData()
+    return
+
+def __doFamilyOnDay():
     familyManager = DBDataMgr.GetFamilyMgr()
-    for i in range(0, familyManager.GetCount()):
-        family = familyManager.GetAt(i)
-        #自动传位
-        __AutoChangeLeader(family)
-        
+    for zoneID in familyManager.GetZoneIDListThisServer():
+        zoneMgr = familyManager.GetZoneFamilyMgr(zoneID)
+        for i in range(0, zoneMgr.GetCount()):
+            family = zoneMgr.GetAt(i)
+            familyID = family.GetID()
+            
+            PlayerFamilyZhenbaoge.OnDay(family)
+            PlayerFamilyTaofa.OnDay(family)
+            
+            for index in xrange(family.GetCount()):
+                member = family.GetAt(index)
+                # 重置成员日信息
+                member.SetContribDay(0)
+                member.SetDonateCntDay(0)
+                
+            Broadcast_FamilyInfo(familyID)
+    return
+
+def PlayerCrossCenterOnDay(curPlayer):
+    ## 处理跨服中心同步的onday玩家事件
+    if not DBFamily.IsFamilyCross():
+        GameWorld.DebugLog("公会还属于本服,不处理成员跨服过天", curPlayer.GetPlayerID())
+        return
+    __doPlayerOnDay(curPlayer)
     return
 
 def PlayerOnDay(curPlayer):
-    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
+    ## 本服时间的onday玩家事件
+    if DBFamily.IsFamilyCross():
+        GameWorld.DebugLog("公会已经跨服了,不处理成员本服过天", curPlayer.GetPlayerID())
         return
-    ResetDailyDonateCnt(curPlayer)
+    __doPlayerOnDay(curPlayer)
+    return
+
+def __doPlayerOnDay(curPlayer):
     PlayerFamilyZhenbaoge.PlayerOnDay(curPlayer)
     PlayerFamilyTaofa.PlayerOnDay(curPlayer)
+    Do_MapServer_PlayerOnDay(curPlayer)
     return
 
 def OnPlayerLogin(curPlayer, tick):
-    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
+    Do_MapServer_PlayerLogin(curPlayer)
+    if DBFamily.IsFamilyCross():
+        #公会已跨服不处理,由所属跨服服务器处理成员登录逻辑
         return
-    PlayerLoginRefreshFamily(curPlayer, tick)
-    Sync_RequestAddFamilyInfo(curPlayer, False)
-    SyncDonateCntInfo(curPlayer)
-    PlayerFamilyZhenbaoge.OnPlayerLogin(curPlayer)
-    PlayerFamilyTaofa.OnPlayerLogin(curPlayer)
+    crossPlayer = CrossPlayer.GetCrossPlayerMgr().FindCrossPlayer(curPlayer.GetPlayerID())
+    OnCrossPlayerLogin(crossPlayer)
+    return
+
+def OnCrossPlayerLogin(crossPlayer):
+    ## 玩家上线,游戏服跨服通用,流程上当做以前GameServer处理公会一样,处理后再通知地图(现在的游戏服)
+    PlayerLoginRefreshFamily(crossPlayer)
+    Sync_RequestAddFamilyInfo(crossPlayer, False)
+    #PlayerFamilyTaofa.OnPlayerLogin(curPlayer) 讨伐待修改
     return
 
 def OnPlayerLogout(curPlayer):
-    playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
+    if DBFamily.IsFamilyCross():
+        #公会已跨服不处理,由所属跨服服务器处理成员登录逻辑
+        return
+    crossPlayer = CrossPlayer.GetCrossPlayerMgr().FindCrossPlayer(curPlayer.GetPlayerID())
+    OnCrossPlayerLogout(crossPlayer)
+    return
+
+def OnCrossPlayerLogout(crossPlayer):
+    ## 玩家下线,游戏服跨服通用,流程上当做以前GameServer处理公会一样,处理后再通知地图(现在的游戏服)
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
     if not familyID:
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
@@ -139,24 +188,62 @@
     if not curMember:
         return
     curMember.SetOffTime(int(time.time()))
-    #XW_JZ_LeaguerLeaveline  <n color="0,190,255">{%S1%}</n><n color="255,255,0">下线了!</n>    25  -   -
-    #NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaguerLeaveline", [curPlayer.GetPlayerName()])
-    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLogout, excludeIDList=[playerID])
+    
+    # 通知成员下线
+    Broadcast_FamilyInfo(familyID, changeMemIDList=[playerID])
     return
 
-def OnWeekEx(curPlayer):
-    #重置
+def SendToFamilyMapPlayer(crossPlayer, doType, doData):
+    playerID = crossPlayer.GetPlayerID()
+    dataMsg = {"doType":doType, "doData":doData}
+    if GameWorld.IsCrossServer():
+        CrossMsg.SendToClientServer(ShareDefine.C2S_FamilyMapPlayer, dataMsg, [crossPlayer.GetMainServerID()], playerID)
+    else:
+        C2S_FamilyMapPlayer(dataMsg, playerID)
     return
 
-def PlayerLoginRefreshFamily(curPlayer, tick):
+def MapServer_FamilyRefresh(crossPlayer, familyID, isVoluntarily=0):
+    ''' 相当于GameServer调用 curPlayer.MapServer_FamilyRefresh()
+    '''
+    playerID = crossPlayer.GetPlayerID()
+    FmLV = 0 # 职位
+    FamilyLV = 0 # 公会等级
+    FamilyName = ""
+    EmblemID, EmblemWord = 0, ""
+    if familyID:
+        familyMgr = DBDataMgr.GetFamilyMgr()
+        curFamily = familyMgr.FindFamily(familyID)
+        if curFamily:
+            FamilyLV = curFamily.GetLV()
+            FamilyName = curFamily.GetName()
+            EmblemID = curFamily.GetEmblemID()
+            EmblemWord = curFamily.GetEmblemWord()
+            member = curFamily.FindMember(playerID)
+            if member:
+                FmLV = member.GetFmLV()
+        else:
+            familyID = 0
+                    
+    crossPlayer.SetFamilyID(familyID)
+    
+    doData = {"FamilyID":familyID}
+    if familyID:
+        doData.update({"FmLV":FmLV, "FamilyLV":FamilyLV, "FamilyName":FamilyName, "EmblemID":EmblemID, "EmblemWord":EmblemWord})
+    if isVoluntarily:
+        doData["isVoluntarily"] = 1
+    SendToFamilyMapPlayer(crossPlayer, "FamilyRefresh", doData)
+    return
+
+def PlayerLoginRefreshFamily(crossPlayer):
     ## 玩家登录时刷新家族
     
-    playerID = curPlayer.GetPlayerID()
+    playerID = crossPlayer.GetPlayerID()
     familyMgr = DBDataMgr.GetFamilyMgr()
     refreshFamilyID = familyMgr.GetPlayerFamilyID(playerID)
-    MapServer_FamilyRefresh(curPlayer, refreshFamilyID)
-    
-    familyID = curPlayer.GetFamilyID()
+    GameWorld.DebugLog("PlayerLoginRefreshFamily playerID=%s,refreshFamilyID=%s" % (playerID, refreshFamilyID))
+    crossPlayer.SetFamilyID(refreshFamilyID)
+    MapServer_FamilyRefresh(crossPlayer, refreshFamilyID)
+    familyID = refreshFamilyID
     if not familyID:
         return
     
@@ -167,55 +254,163 @@
     if not curMember:
         return
     curMember.SetOffTime(0) # 在线0,脱机1,>1离线时间
-    curMember.RefreshMember(curPlayer)
-    Sync_FamilyInfo(curPlayer)
-    SendFamilyActionInfo(curPlayer, familyID, ShareDefine.Def_ActionType_FamilyData)
+    curMember.RefreshMemberByID(playerID)
+    
+    Sync_FamilyInfo(crossPlayer) # 给自己同步完整的
+    # 广播成员在线
+    Broadcast_FamilyInfo(familyID, changeMemIDList=[playerID], excludeIDList=[playerID])
     
     #通知招人
     if GetFamilyMemberHasPow(curMember, FamilyPowerID_Call):
-        NetPackCommon.SendFakePack(curPlayer, GetPack_FamilyReqJoinInfo(familyID))
-            
-    #XW_JZ_LeaguerOnline <n color="0,190,255">{%S1%}</n><n color="255,255,0">上线了!</n>    25  -   -
-    #NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaguerOnline", [curPlayer.GetName()], [playerID])
-    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLogin, excludeIDList=[playerID])
-    
+        CrossPlayer.SendFakePack(crossPlayer, GetPack_FamilyReqJoinInfo(familyID))
+        
     # 盟主上线处理
-    if curMember.GetFmLV() == IPY_PlayerDefine.fmlLeader:
-        OnFamilyLeaderLogin(curPlayer)
+    #if curMember.GetFmLV() == IPY_PlayerDefine.fmlLeader:
+    #    OnFamilyLeaderLogin(curPlayer)
     return
 
-def OnFamilyLeaderLogin(curPlayer):
-    ## 盟主登录额外处理
-    
-    return
-
-def OnMinute():
-    #战力刷新在DBFamily.OnMinute
-    PlayerFamilyEmblem.CheckExpireEmblem()
-    return
-
-def RefreshFamilyMember(curPlayer):
+def RefreshFamilyMember(crossPlayer):
     ## 玩家成员相关属性变更时同步更新家族成员信息
-    familyID = curPlayer.GetFamilyID()
+    if GameWorld.IsCrossServer():
+        pass
+    elif not GameWorld.IsMainServer() or DBFamily.IsFamilyCross():
+        return
+    familyID = crossPlayer.GetFamilyID()
     if not familyID:
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
     family = familyMgr.FindFamily(familyID)
     if not family:
         return
-    playerID = curPlayer.GetPlayerID()
+    playerID = crossPlayer.GetPlayerID()
     member = family.FindMember(playerID)
     if not member:
         return
-    member.RefreshMember(curPlayer)
+    member.RefreshMemberByID(playerID)
     return
 
-def GetRenameTime(dataAction): return dataAction.GetValue1()
-def SetRenameTime(dataAction, setTime): dataAction.SetValue1(setTime)
-def GetFamilyDataAction(familyID):
-    ## 家族额外数据存储的行为数据,可以视为Family公共数据的一个扩展
-    action = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, ShareDefine.Def_ActionType_FamilyData)
-    return action.GetOneAction(True)
+def FamilyPyPackForwarding(curPlayer, clientData, tick, funcName, needResult=False, reqCD=0.5, reqDataEx=None):
+    ## 玩家请求公会功能包转发处理
+    # @needResult: 转发跨服处理完毕是否需要回复状态,一般有消耗货币、物品相关的都要回复,且设置一个较长请求cd,防止重复处理
+    # @param reqCD: 转发跨服请求cd,秒,支持小数
+    
+    playerID = curPlayer.GetPlayerID()
+    
+    crossServerID = DBDataMgr.GetFamilyMgr().GetCurCrossServerID()
+    if crossServerID == -2:
+        PlayerControl.NotifyCode(curPlayer, "FamilyInTransData")
+        return
+    
+    if crossServerID < 0:
+        GameWorld.ErrLog("公会功能异常! crossServerID=%s" % crossServerID)
+        return
+    
+    # 本服处理
+    if crossServerID == 0 or crossServerID == GameWorld.GetGameWorld().GetServerID():
+        isOK = CallPyPackFunc(playerID, clientData, funcName, reqDataEx=reqDataEx)
+        if needResult:
+            __doFamilyPyPackRet(curPlayer, clientData, funcName, isOK)
+        return
+    
+    # 转发请求CD验证
+    if reqCD:
+        reqTick = curPlayer.GetDictByKey("FamilyPyPackForwardingTick")
+        if reqTick and (tick - reqTick) < reqCD * 1000:
+            PlayerControl.NotifyCode(curPlayer, "RequestLater")
+            return
+        curPlayer.SetDict("FamilyPyPackForwardingTick", tick)
+        
+    # 剩下的就是大于0
+    dataMsg = {"funcName":funcName}
+    if clientData:
+        dataMsg["packBuff"] = clientData.GetBuffer()       
+    if reqDataEx:
+        dataMsg["reqDataEx"] = reqDataEx
+    if needResult:
+        dataMsg["needResult"] = 1
+    CrossMsg.SendToCrossServer(ShareDefine.S2C_FamilyPyPack, dataMsg, [crossServerID], playerID)
+    return
+
+def S2C_FamilyPyPack(dataMsg, fromServerID, playerID):
+    funcName = dataMsg["funcName"]
+    packBuff = dataMsg.get("packBuff")
+    reqDataEx = dataMsg.get("reqDataEx")
+    clientData = None
+    if packBuff:
+        clientData = NetPackCommon.ReadRecPyPackData(packBuff)
+        if not clientData:
+            return
+    isOK = CallPyPackFunc(playerID, clientData, funcName, fromServerID, reqDataEx)
+    # 处理结束回复,无论成功与否
+    if "needResult" in dataMsg:
+        dataMsg.pop("needResult")
+        dataMsg["isOK"] = isOK
+        CrossMsg.SendToClientServer(ShareDefine.C2S_FamilyPyPackRet, dataMsg, [fromServerID], playerID)
+    return
+
+def C2S_FamilyPyPackRet(dataMsg, playerID):
+    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+    if not curPlayer:
+        return
+    curPlayer.SetDict("FamilyPyPackForwardingTick", 0)
+    
+    funcName = dataMsg["funcName"]
+    packBuff = dataMsg.get("packBuff")
+    clientData = None
+    if packBuff:
+        clientData = NetPackCommon.ReadRecPyPackData(packBuff)
+        if not clientData:
+            return
+    isOK = dataMsg.get("isOK")
+    __doFamilyPyPackRet(curPlayer, clientData, funcName, isOK)
+    return
+
+def CallPyPackFunc(playerID, clientData, funcName, fromServerID=0, reqDataEx=None):
+    crossPlayer = CrossPlayer.GetCrossPlayerMgr().FindCrossPlayer(playerID)
+    if not crossPlayer:
+        GameWorld.ErrLog("找不到该CrossPlayer! playerID=%s" % playerID, playerID)
+        return
+    
+    callFunc = GetCallFunc(funcName)
+    if not callFunc:
+        GameWorld.ErrLog("公会封包功能函数名不存在! %s" % funcName)
+        return
+    
+    # 执行函数
+    tick = GameWorld.GetGameWorld().GetTick()
+    isOK = callFunc(crossPlayer, clientData, tick, fromServerID, reqDataEx)
+    return isOK
+
+def __doFamilyPyPackRet(curPlayer, clientData, funcName, isOK):
+    ## 处理后额外处理,如成就、任务等
+    funcName = "%s_Ret" % funcName
+    callFunc = GetCallFunc(funcName)
+    if not callFunc:
+        # 结果额外处理函数允许不一定需要,根据功能自行决定
+        return
+    callFunc(curPlayer, clientData, isOK)
+    return
+
+def GetCallFunc(funcName):
+    callFunc = None
+    if "." in funcName:
+        # 分割字符串,最后一个部分是函数名
+        parts = funcName.split('.')
+        if len(parts) == 2:
+            moduleName, func_name = parts
+            # 导入模块
+            module = __import__(moduleName)
+            # 获取函数
+            if hasattr(module, func_name):
+                func = getattr(module, func_name)
+                if callable(func):
+                    callFunc = func
+    else:
+        gDict = globals()
+        if funcName in gDict and callable(gDict[funcName]):
+            # 获取函数对象
+            callFunc = gDict[funcName]
+    return callFunc
 
 #// A6 04 创建家族 #tagCMCreateFamily
 #
@@ -223,40 +418,53 @@
 #{
 #    tagHead        Head;
 #    char        Name[33];
-#    WORD        EmblemID; //选择徽章ID,解锁仙盟等级为1级的均为可选ID
+#    WORD        EmblemID; //选择徽章ID,解锁公会等级为1级的均为可选ID
 #    char        EmblemWord[3];    //徽章文字
 #};
-def OnCreateFamily(index, clientPack, tick):
+def OnCreateFamily(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    inputName = clientPack.Name
-    emblemID = clientPack.EmblemID
-    emblemWord = clientPack.EmblemWord
+    inputName = clientData.Name
     
-    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
+    GameWorld.DebugLog("OnCreateFamily: %s" % GameWorld.CodeToGbk(inputName))
+    
+    # 通用的前置验证,直接游戏服处理即可
+    if not CheckInputFamilyName(curPlayer, inputName):
         return
+    
+    needMoney = IpyGameDataPY.GetFuncCfg("CreateFamily", 1)
+    moneyType = IpyGameDataPY.GetFuncCfg("CreateFamily", 2)
+    if moneyType and needMoney:
+        if not PlayerControl.HaveMoney(curPlayer, moneyType, needMoney):
+            return
         
-    playerID = curPlayer.GetPlayerID()
-    playerFamilyID = curPlayer.GetFamilyID()
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnCreateFamily", True, 20)
+    return
+
+def __OnCreateFamily(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
+    inputName = clientData.Name
+    emblemID = clientData.EmblemID
+    emblemWord = clientData.EmblemWord
+    
+    GameWorld.DebugLog("__OnCreateFamily: %s" % GameWorld.CodeToGbk(inputName))
+    
+    fullFamilyName = inputName
+    
+    playerID = crossPlayer.GetPlayerID()
+    playerFamilyID = crossPlayer.GetFamilyID()
     familyMgr = DBDataMgr.GetFamilyMgr()
     if playerFamilyID:
         curFamily = familyMgr.FindFamily(playerFamilyID)
         if curFamily:
             if curFamily.FindMember(playerID):
                 #玩家已经有家族, 创建失败
-                PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_85890")
+                CrossPlayer.NotifyCode(crossPlayer, "GeRen_chenxin_85890")
                 return
             
-    fullFamilyName = CheckInputFamilyName(curPlayer, inputName)
-    if not fullFamilyName:
+    # 验证重名
+    if CheckFamilyNameExists(crossPlayer, fullFamilyName, fromServerID):
         return
     
-    needMoney = IpyGameDataPY.GetFuncCfg("CreateFamily", 1)
-    moneyType = IpyGameDataPY.GetFuncCfg("CreateFamily", 2)
-    if moneyType and needMoney:
-        if not PlayerControl.PayMoney(curPlayer, moneyType, needMoney, "CreateFamily"):
-            return
-        
-    serverID = GameWorld.GetPlayerServerID(curPlayer)
+    serverID = crossPlayer.GetServerID()
     curFamily = familyMgr.AddFamily(fullFamilyName, serverID)
     if curFamily == None:
         GameWorld.ErrLog("创建家族失败", playerID)
@@ -266,29 +474,45 @@
     emblemIDList = PlayerFamilyEmblem.GetDefaultFamilyEmblemIDList()
     if not emblemID or emblemID not in emblemIDList:
         emblemID = random.choice(emblemIDList) # 从默认徽章中随机选择一个
-    GameWorld.Log("创建仙盟: familyID=%s,playerID=%s,emblemID=%s" % (newFamilyID, playerID, emblemID))
+    GameWorld.Log("创建公会: familyID=%s,playerID=%s,emblemID=%s,serverID=%s" % (newFamilyID, playerID, emblemID, serverID))
     curFamily.SetEmblemID(emblemID)
     curFamily.SetEmblemWord(emblemWord)
     
+    # 扣除消耗
+    needMoney = IpyGameDataPY.GetFuncCfg("CreateFamily", 1)
+    moneyType = IpyGameDataPY.GetFuncCfg("CreateFamily", 2)
+    if moneyType and needMoney:
+        CrossPlayer.CostPlayerResources(crossPlayer, "CreateFamily", costMoneyDict={moneyType:needMoney})
+        
     #-设置家族成员属性
-    DoPlayerJionFamily(curFamily, playerID, curPlayer, IPY_PlayerDefine.fmlLeader)
-    familyMgr.Sort()
+    DoPlayerJionFamily(curFamily, playerID, crossPlayer, IPY_PlayerDefine.fmlLeader)
+    zoneMgr = familyMgr.GetZoneFamilyMgrByFamilyID(newFamilyID)
+    zoneMgr and zoneMgr.Sort()
     
     #XW_JZ_EstablishSud <n color="255,255,0">恭喜您,家族建立成功!</n>    25  -   -
-    PlayerControl.NotifyCode(curPlayer, "XW_JZ_EstablishSud")
-    PlayerControl.WorldNotify(0, "jiazu_liubo_671654", [curPlayer.GetName(), fullFamilyName, newFamilyID])
+    #CrossPlayer.NotifyCode(crossPlayer, "XW_JZ_EstablishSud")
+    #PlayerControl.WorldNotify(0, "jiazu_liubo_671654", [curPlayer.GetName(), fullFamilyName, newFamilyID])
     PlayerFamilyZhenbaoge.OnZhenbaogeReset(curFamily)
-    return
+    return True
 
 def CheckInputFamilyName(curPlayer, inputName):
-    '''检查玩家输入的仙盟名是否合法,建盟、改名通用
-    @return: None-不合法;非空-合法的仙盟全名
+    '''检查玩家输入的公会名是否合法,建盟、改名通用
+    【注】该函数仅在游戏服验证名字的通用合法性,如长度、敏感词等,公会名重名请在公会所在数据服验证
+    @return: None-不合法;非空-合法的公会全名
     '''
     #C++过滤空格
     familyName = GameWorld.GetGameWorld().GetCharTrim(inputName)
-    fullFamilyName = GetFamilyFullName(curPlayer, familyName)
-    if not fullFamilyName:
-        GameWorld.ErrLog("家族全名异常!", curPlayer.GetPlayerID())
+    
+    serverID = GameWorld.GetPlayerServerID(curPlayer)
+    maxServerID = IpyGameDataPY.GetFuncCfg("FamilyNameFormat", 3)
+    if serverID > maxServerID or serverID <= 0:
+        GameWorld.ErrLog("公会全名 serverID=%s error! maxServerID=%s, check FamilyNameFormat.txt" % (serverID, maxServerID))
+        return
+    
+    maxLen = IpyGameDataPY.GetFuncCfg("FamilyNameFormat", 2)
+    if len(familyName) > maxLen:
+        GameWorld.ErrLog("公会全名 familyName=%s, len=%s > %s, check FamilyNameFormat.txt" % (familyName, len(familyName), maxLen))
+        PlayerControl.NotifyCode(curPlayer, "NameLenLimit", [maxLen / 3, maxLen])
         return
     
     if DirtyList.IsWordForbidden(familyName):
@@ -300,49 +524,30 @@
         PlayerControl.NotifyCode(curPlayer, "NameLenLimit", [Def_CreatFamily_MaxStr / 3, Def_CreatFamily_MaxStr])
         return
     
+    return True
+
+def CheckFamilyNameExists(crossPlayer, familyName, fromServerID=0):
+    ## 重名在数据所在服务器验证
     familyMgr = DBDataMgr.GetFamilyMgr()
-    if familyMgr.FindFamilyByName(fullFamilyName):
+    zoneID = familyMgr.GetZoneIDInThisServer(fromServerID)
+    if zoneID < 0:
+        GameWorld.ErrLog("验证公会重名时分区异常也视为重名")
+        return True
+    zoneMgr = familyMgr.GetZoneFamilyMgr(zoneID)
+    # 不同分区暂时允许重名
+    if zoneMgr.FindFamilyByName(familyName):
         #XW_JZ_EstablishErr_Name    <n color="255,255,0">对不起,您输入的家族名已存在,建立家族失败!</n> 25  -   -
-        PlayerControl.NotifyCode(curPlayer, "NameExists")
-        return
-    
-    return fullFamilyName
+        CrossPlayer.NotifyCode(crossPlayer, "NameExists")
+        return True
+    return False
 
-
-## 获取家族全名
-def GetFamilyFullName(curPlayer, familyName):
-    serverID = GameWorld.GetPlayerServerID(curPlayer)
-    
-    maxServerID = IpyGameDataPY.GetFuncCfg("FamilyNameFormat", 3)
-    if serverID > maxServerID or serverID <= 0:
-        GameWorld.ErrLog("仙盟全名 serverID=%s error! maxServerID=%s, check FamilyNameFormat.txt" % (serverID, maxServerID))
-        return ""
-    
-    specServerDict = IpyGameDataPY.GetFuncEvalCfg("FamilyNameFormat", 4, {})
-    nameFormatInfo = GameWorld.GetDictValueByRangeKey(specServerDict, serverID)
-    if not nameFormatInfo:
-        nameFormatInfo = IpyGameDataPY.GetFuncEvalCfg("FamilyNameFormat", 1)
-    if not nameFormatInfo:
-        return ""
-    nameFormat = nameFormatInfo[0]
-    paramList = [eval(pName) for pName in nameFormatInfo[1:]]
-    fullName = nameFormat % tuple(paramList)
-    
-    maxLen = IpyGameDataPY.GetFuncCfg("FamilyNameFormat", 2)
-    if len(fullName) > maxLen:
-        GameWorld.ErrLog("仙盟全名 familyName=%s,全名=%s len=%s > %s, check FamilyNameFormat.txt" % (familyName, fullName, len(fullName), maxLen))
-        PlayerControl.NotifyCode(curPlayer, "NameLenLimit", [maxLen / 3, maxLen])
-        return ""
-    
-    return fullName
-
-def DoPlayerJionFamily(family, playerID, jionPlayer, jionFamilySetLv=IPY_PlayerDefine.fmlMember, broadcastFamilyChange=True):
+def DoPlayerJionFamily(family, playerID, crossPlayer, jionFamilySetLv=IPY_PlayerDefine.fmlMember, broadcastFamilyChange=True):
     '''加入家族,支持离线玩家加入
-    @param jionPlayer: 如果是离线玩家则为None
+    @param crossPlayer: 如果是离线玩家则为None
     '''
+    familyMgr = DBDataMgr.GetFamilyMgr()
     if isinstance(family, int):
         familyID = family
-        familyMgr = DBDataMgr.GetFamilyMgr()
         curFamily = familyMgr.FindFamily(familyID)
     else:
         curFamily = family
@@ -353,37 +558,32 @@
     familyID = curFamily.GetID()
     member = curFamily.AddMember(playerID)
     member.SetFmLV(jionFamilySetLv)
-    if jionPlayer:
-        member.RefreshMember(jionPlayer)
-    else:
-        member.RefreshMemberByID(playerID)
+    member.RefreshMemberByID(playerID)
     curFamily.SetFightPowerTotal(curFamily.GetFightPowerTotal() + member.GetFightPowerTotal())
     
     if jionFamilySetLv == IPY_PlayerDefine.fmlLeader:
         curFamily.SetLeaderID(playerID)
         
-    #设置玩家身上保存的家族信息
-    if jionPlayer:
-        MapServer_FamilyRefresh(jionPlayer, familyID)
-        Sync_FamilyInfo(jionPlayer)
+    if broadcastFamilyChange:
+        Broadcast_FamilyInfo(familyID, changeMemIDList=[playerID])
         
-    if jionFamilySetLv != IPY_PlayerDefine.fmlLeader:
-        if broadcastFamilyChange:
-            Broadcast_FamilyChange(familyID, FamilyChangeType_MemJoin, excludeIDList=[playerID])
+    familyMgr.DelPlayerReqJoinFamilyIDAll(playerID)
+    #设置玩家身上保存的家族信息
+    if crossPlayer:
+        MapServer_FamilyRefresh(crossPlayer, familyID)
+        Sync_RequestAddFamilyInfo(crossPlayer)
+        PlayerFamilyTaofa.OnCrossPlayerEnterFamily(crossPlayer)
+        
+    #if jionFamilySetLv != IPY_PlayerDefine.fmlLeader:
         #通知所有家族成员, 这个人加入了家族
         #NotifyAllFamilyMemberMsg(familyID, "XW_JZ_EnterFamily", [member.GetPlayerName()], excludeIDList=[playerID])
-        if jionPlayer:
-            PlayerControl.NotifyCode(jionPlayer, 'XW_JZ_EnterFamilyInfo', [family.GetName()])
+        #if jionPlayer:
+        #    PlayerControl.NotifyCode(jionPlayer, 'XW_JZ_EnterFamilyInfo', [family.GetName()])
             
     #记录加入事件
     tick = GameWorld.GetGameWorld().GetTick()
     AddFamilyActionNote(member.GetPlayerName(), familyID, ShareDefine.Def_ActionType_FamilyEvent, 
                         [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_Join, jionFamilySetLv, 0], tick)
-    
-    #玩家缓存
-    #PlayerViewCache.OnPlayerFamilyChange(jionPlayer.GetPlayerID(), curFamily.GetID(), curFamily.GetName())
-    #SetMemberFightPower(familyMember, PlayerControl.GetFightPower(jionPlayer))
-    #GetFamilyMgr().AddFamilyIDToFightPowerChangeList(curFamily.GetID(), jionPlayer.GetPlayerID())
     return
 
 def AddFamilyActionNote(curName, familyID, actionType, actionDataList, tick, isClearNone=True, useData=""):
@@ -408,135 +608,32 @@
             setFunc(value)
     return True
 
-def MapServer_FamilyRefresh(curPlayer, refreshFamilyID, isVoluntarily=0):
-    ''' 相当于GameServer调用 curPlayer.MapServer_FamilyRefresh()
-    @param familyID: 玩家更新的familyID
-    @param isVoluntarily: 是否自愿离开的,仅离开刷新时有效
-    '''
-    
-    tick = GameWorld.GetGameWorld().GetTick()
-    playerID = curPlayer.GetPlayerID()
-    refreshFmLV = 0
-    refreshFamilyLV = 0
-    refreshFamilyName = ""
-    if refreshFamilyID:
-        familyMgr = DBDataMgr.GetFamilyMgr()
-        curFamily = familyMgr.FindFamily(refreshFamilyID)
-        if curFamily:
-            refreshFamilyLV = curFamily.GetLV()
-            refreshFamilyName = curFamily.GetName()
-            member = curFamily.FindMember(playerID)
-            if member:
-                refreshFmLV = member.GetFmLV()
-        else:
-            refreshFamilyID = 0
-            
-    lastFamilyID = curPlayer.GetFamilyID()
-    lastFamilyLV = curPlayer.GetFamilyLV() # 仙盟等级,非职位等级
-    lastFmLV = PlayerControl.GetFamilyMemberLV(curPlayer)
-    
-    if lastFamilyID != refreshFamilyID:
-        curPlayer.SetFamilyID(refreshFamilyID)
-        
-    if curPlayer.GetFamilyName() != refreshFamilyName:
-        curPlayer.SetFamilyName(refreshFamilyName)
-        curPlayer.Notify_FamilyNameRefresh() #//04 36    周围玩家家族名刷新#tagPlayerFamilyNameRefresh
-        
-    if lastFmLV != refreshFmLV:
-        PlayerControl.SetFamilyMemberLV(curPlayer, refreshFmLV)
-        
-    if lastFamilyLV != refreshFamilyLV:
-        isLVUP = False
-        if lastFamilyLV and refreshFamilyLV > 0:
-            #触发家族升级事件
-            isLVUP = True
-        curPlayer.SetFamilyLV(refreshFamilyLV)
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyLV, refreshFamilyLV)
-        #触发家族升级事件, 在SetFamilyLV之后,任务可以取等级判定
-        if isLVUP:
-            pass
-        
-    if lastFamilyID != 0 and curPlayer.GetFamilyID() == 0:
-        #玩家离开家族
-        __OnLeaveFamily(curPlayer, isVoluntarily, tick)
-        
-    elif lastFamilyID == 0 and curPlayer.GetFamilyID() != 0:
-        #刚进家族并为族长,触发建家族事件
-        if curPlayer.GetFamilyMemberLV() == IPY_GameWorld.fmlLeader:
-            pass
-            
-        #进入家族触发事件
-        __OnEnterFamily(curPlayer, tick)
-        
-    #---通知客户端刷新属性---
-    curPlayer.View_FamilyInfoRefresh() #//04 30 玩家家族名字职位等信息刷新#tagPlayerInFamilyInfoRefresh
-    return
-
-def __OnEnterFamily(curPlayer, tick):
-    ## 进入家族触发事件
-    familyMgr = DBDataMgr.GetFamilyMgr()
-    familyMgr.DelPlayerReqJoinFamilyIDAll(curPlayer.GetPlayerID())
-    Sync_RequestAddFamilyInfo(curPlayer)
-    PlayerFamilyTaofa.OnPlayerEnterFamily(curPlayer)
-    PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_ReqOrJoinFamily)
-    return
-
-def __OnLeaveFamily(curPlayer, isVoluntarily, tick):
-    ## 退出家族触发事件
-    #---清空家族相关信息---
-    curPlayer.SetPerExp(0)
-    curPlayer.SetFamilyHornor(0)
-    curPlayer.SetFamilyActiveValue(0)
-    curPlayer.SetLastWeekFamilyActiveValue(0)
-    curPlayer.SetFamilyLV(0)
-    PlayerControl.SetLeaveFamilyTimeEx(curPlayer, int(time.time()))
-    leaveCnt, kickedCnt, _ = PlayerControl.GetLeaveFamilyInfo(curPlayer)
-    GameWorld.DebugLog("__OnLeaveFamily: isVoluntarily=%s,leaveCnt=%s,kickedCnt=%s" % (isVoluntarily, leaveCnt, kickedCnt))
-    delMoneyType, delMoneyPer = IpyGameDataPY.GetFuncCfg("FamilyLeave", 3), 0
-    if isVoluntarily:
-        delMoneyPerList = IpyGameDataPY.GetFuncEvalCfg("FamilyLeave", 4)
-        if delMoneyPerList:
-            delMoneyPer = delMoneyPerList[leaveCnt] if len(delMoneyPerList) > leaveCnt else delMoneyPerList[-1]
-            
-        leaveCnt += 1
-        GameWorld.DebugLog("    增加主动离开次数: leaveCnt=%s" % (leaveCnt))
-    else:
-        delMoneyPerList = IpyGameDataPY.GetFuncEvalCfg("FamilyLeave", 5)
-        if delMoneyPerList:
-            delMoneyPer = delMoneyPerList[kickedCnt] if len(delMoneyPerList) > kickedCnt else delMoneyPerList[-1]
-            
-        kickedCnt += 1
-        GameWorld.DebugLog("    增加被踢离开次数: kickedCnt=%s" % (kickedCnt))
-    PlayerControl.SetLeaveFamilyInfo(curPlayer, leaveCnt, kickedCnt, isVoluntarily)
-    if delMoneyType and delMoneyPer:
-        nowMoney = PlayerControl.GetMoney(curPlayer, delMoneyType)
-        delMoney = int(nowMoney * delMoneyPer / 100.0)
-        GameWorld.DebugLog("    扣除货币: delMoneyType=%s,delMoneyPer=%s,nowMoney=%s,delMoney=%s" % (delMoneyType, delMoneyPer, nowMoney, delMoney))        
-        PlayerControl.PayMoney(curPlayer, delMoneyType, delMoney, "LeaveFamily")
-        
-    PlayerFamilyTaofa.OnPlayerLeaveFamily(curPlayer)
-    FBLogic.OnLeaveFamily(curPlayer, tick)
-    return
-
 def GetFamilyMemberHasPow(member, powerID):
-    ## 仙盟成员是否有该权限
+    ## 公会成员是否有该权限
     powerDict = IpyGameDataPY.GetFuncEvalCfg("FamilyPower", 1, {})
     if str(powerID) not in powerDict:
         return False
     needMemberLV = powerDict[str(powerID)]
     return member.GetFmLV() >= needMemberLV
 
-def Sync_FamilyInfo(curPlayer, infoPack=None):
-    ## // A5 20 玩家家族信息 #tagMCRoleFamilyInfo
-    familyID = curPlayer.GetFamilyID()
+def Sync_FamilyInfo(crossPlayer, syncMemIDList=None, isSyncMem=True):
+    ## 通知指定玩家 // A5 20 玩家家族信息 #tagMCRoleFamilyInfo
+    familyID = crossPlayer.GetFamilyID()
     if not familyID:
         return
-    if not infoPack:
-        infoPack = GetPack_FamilyInfo(familyID)
-    NetPackCommon.SendFakePack(curPlayer, infoPack)
+    clientPack = GetPack_FamilyInfo(familyID, syncMemIDList, isSyncMem)
+    CrossPlayer.SendFakePack(crossPlayer, clientPack)
     return
 
-def GetPack_FamilyInfo(familyID):
+def Broadcast_FamilyInfo(familyID, changeMemIDList=None, isSyncMem=True, excludeIDList=None):
+    ## 广播给公会成员 // A5 20 玩家家族信息 #tagMCRoleFamilyInfo
+    # @param changeMemIDList: 指定仅通知哪些变化成员信息,差异更新通知
+    # @param isSyncMem: 是否需要通知成员信息
+    clientPack = GetPack_FamilyInfo(familyID, changeMemIDList, isSyncMem)
+    CrossPlayer.SendFakePackByFamily(familyID, clientPack, excludeIDList)
+    return
+
+def GetPack_FamilyInfo(familyID, changeMemIDList=None, isSyncMem=True):
     familyMgr = DBDataMgr.GetFamilyMgr()
     curFamily = familyMgr.FindFamily(familyID)
     if not curFamily:
@@ -558,85 +655,50 @@
     clientPack.BroadcastLen = len(clientPack.Broadcast)
     clientPack.LeaderID = curFamily.GetLeaderID()
     clientPack.MemberList = []
-    for index in xrange(curFamily.GetCount()):
-        member = curFamily.GetAt(index)
-        memInfo = ChPyNetSendPack.tagMCRoleFamilyMember()
-        memInfo.PlayerID = member.GetPlayerID()
-        memInfo.JoinTime = member.GetJoinTime()
-        memInfo.Name = member.GetPlayerName()
-        memInfo.NameLen = len(memInfo.Name)
-        memInfo.LV = member.GetLV()
-        memInfo.Job = member.GetJob()
-        memInfo.RealmLV = member.GetRealmLV()
-        memInfo.Face = member.GetFace()
-        memInfo.FacePic = member.GetFacePic()
-        memInfo.TitleID = member.GetTitleID()
-        memInfo.FightPower = member.GetFightPower()
-        memInfo.FightPowerEx = member.GetFightPowerEx()
-        memInfo.FmLV = member.GetFmLV()
-        memInfo.ServerID = member.GetServerID()
-        memInfo.ContribTotal = member.GetContribTotal()
-        memInfo.ContribDay = member.GetContribDay()
-        memInfo.DonateCntTotal = member.GetDonateCntTotal()
-        memInfo.DonateCntDay = member.GetDonateCntDay()
-        memInfo.OffTime = member.GetOffTime()
-        clientPack.MemberList.append(memInfo)
+    # ---------------
+    # 测试用,同步全部,等前端同步修改后删除
+    #isSyncMem = True 
+    #changeMemIDList = []
+    # ---------------
+    if isSyncMem:
+        for index in xrange(curFamily.GetCount()):
+            member = curFamily.GetAt(index)
+            memID = member.GetPlayerID()
+            if changeMemIDList and memID not in changeMemIDList:
+                continue
+            memInfo = ChPyNetSendPack.tagMCRoleFamilyMember()
+            memInfo.PlayerID = member.GetPlayerID()
+            memInfo.JoinTime = member.GetJoinTime()
+            memInfo.Name = member.GetPlayerName()
+            memInfo.NameLen = len(memInfo.Name)
+            memInfo.LV = member.GetLV()
+            memInfo.Job = member.GetJob()
+            memInfo.RealmLV = member.GetRealmLV()
+            memInfo.Face = member.GetFace()
+            memInfo.FacePic = member.GetFacePic()
+            memInfo.TitleID = member.GetTitleID()
+            memInfo.FightPower = member.GetFightPower()
+            memInfo.FightPowerEx = member.GetFightPowerEx()
+            memInfo.FmLV = member.GetFmLV()
+            memInfo.ServerID = member.GetServerID()
+            memInfo.ContribTotal = member.GetContribTotal()
+            memInfo.ContribDay = member.GetContribDay()
+            memInfo.DonateCntTotal = member.GetDonateCntTotal()
+            memInfo.DonateCntDay = member.GetDonateCntDay()
+            memInfo.OffTime = member.GetOffTime()
+            clientPack.MemberList.append(memInfo)
     clientPack.MemberCount = len(clientPack.MemberList)
+    clientPack.Extra1 = curFamily.GetExtra1()
     return clientPack
 
-def Broadcast_FamilyChange(familyID, changeType=FamilyChangeType_None, powerID=None, excludeIDList=None):
-    ## // A5 21 家族变更 #tagMCFamilyChange
-    # @param excludeIDList: 不广播的成员ID列表
-    clientPack = ChPyNetSendPack.tagMCFamilyChange()
-    clientPack.Type = changeType
-    Broadcast_FamilyPack(familyID, clientPack, powerID, excludeIDList)
-    return
-
-def Broadcast_FamilyPack(familyID, clientPack, powerID=None, excludeIDList=None):
-    ## 广播家族成员封包
-    # @param powerID: 可指定只发给有该权限的成员
-    # @param excludeIDList: 不广播的成员ID列表
-    if not clientPack:
-        return
-    familyMgr = DBDataMgr.GetFamilyMgr()
-    curFamily = familyMgr.FindFamily(familyID)
-    if not curFamily:
-        return
-    playerManager = GameWorld.GetPlayerManager()
-    for index in xrange(curFamily.GetCount()):
-        member = curFamily.GetAt(index)
-        playerID = member.GetPlayerID()
-        if excludeIDList and playerID in excludeIDList:
-            continue
-        
-        curPlayer = playerManager.FindPlayerByID(playerID)
-        if not curPlayer:
-            continue
-        
-        if powerID != None and not GetFamilyMemberHasPow(member, powerID):
-            continue
-        
-        NetPackCommon.SendFakePack(curPlayer, clientPack)
-    return
-
-def NotifyAllFamilyMemberMsg(familyID, code, paramList=[], excludeIDList=None):
-    ## 通知所有家族成员信息
-    # @param excludeIDList: 不通知的成员ID列表
-    familyMgr = DBDataMgr.GetFamilyMgr()
-    curFamily = familyMgr.FindFamily(familyID)
-    if not curFamily:
-        return
-    playerManager = GameWorld.GetPlayerManager()
-    for i in xrange(curFamily.GetCount()):
-        member = curFamily.GetAt(i)
-        playerID = member.GetPlayerID()
-        if excludeIDList and playerID in excludeIDList:
-            continue
-        curPlayer = playerManager.FindPlayerByID(playerID)
-        if not curPlayer:
-            continue
-        PlayerControl.NotifyCode(curPlayer, code, paramList)
-    return
+def GetPack_FamilyDel(delPlayerID, playerName, delType=0):
+    # @param delType: 0-踢出;1-主动退出
+    clientPack = ChPyNetSendPack.tagSCFamilyMemDel()
+    clientPack.Type = delType
+    clientPack.PlayerID = delPlayerID
+    clientPack.Name = playerName
+    clientPack.NameLen = len(clientPack.Name)
+    return clientPack
     
 #// A6 01 向玩家申请加入家族 #tagCMRequestJoinFamilyByPlayer
 #
@@ -646,17 +708,18 @@
 #    DWORD        TagPlayerID;    //目标家族玩家ID
 #};
 def OnRequestJoinFamilyByPlayer(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    tagPlayerID = clientData.TagPlayerID
-    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
-    if not tagPlayer:
-        GameWorld.DebugLog("对方不在线! tagPlayerID=%s" % tagPlayerID)
-        return
-    tagFamilyID = tagPlayer.GetFamilyID()
-    if tagFamilyID <= 0:
-        GameWorld.DebugLog("对方没有家族! tagPlayerID=%s" % tagPlayerID)
-        return
-    RequestJoinTagFamily(curPlayer, tagFamilyID)
+    #屏蔽,默认只使用 A6 02
+    #curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    #tagPlayerID = clientData.TagPlayerID
+    #tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
+    #if not tagPlayer:
+    #    GameWorld.DebugLog("对方不在线! tagPlayerID=%s" % tagPlayerID)
+    #    return
+    #tagFamilyID = tagPlayer.GetFamilyID()
+    #if tagFamilyID <= 0:
+    #    GameWorld.DebugLog("对方没有家族! tagPlayerID=%s" % tagPlayerID)
+    #    return
+    #RequestJoinTagFamily(curPlayer, tagFamilyID)
     return
 
 #// A6 02 申请加入家族#tagCMRequesJoinFamily
@@ -669,26 +732,41 @@
 #};
 def OnRequesJoinFamily(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    
+    requestType = clientData.Type
+    if requestType == 0:
+        if CheckInJoinCD(curPlayer):
+            return
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnRequesJoinFamily", True)
+    return
+
+def __OnRequesJoinFamily(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
     tagFamilyID = clientData.TagFamilyID  # 申请进入的家族ID
     requestType = clientData.Type   # 申请类型(申请/撤销)
+    GameWorld.DebugLog("__OnRequesJoinFamily: tagFamilyID=%s,requestType=%s" % (tagFamilyID, requestType))
     
     # 申请加入
     if requestType == 0:
-        PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_ReqOrJoinFamily, 1)
         if not tagFamilyID:
-            AutoJoinFamily(curPlayer)
+            AutoJoinFamily(crossPlayer)
         else:
-            RequestJoinTagFamily(curPlayer, tagFamilyID)
+            RequestJoinTagFamily(crossPlayer, tagFamilyID)
             
     # 撤销申请
     elif requestType == 1:
-        CancelJoinTagFamily(curPlayer, tagFamilyID)
+        CancelJoinTagFamily(crossPlayer, tagFamilyID)
+        
+    return True
+
+def __OnRequesJoinFamily_Ret(curPlayer, clientData, isOK):
+    requestType = clientData.Type   # 申请类型(申请/撤销)
+    # 申请加入
+    if requestType == 0:
+        PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_ReqOrJoinFamily, 1)
         
     return
 
 def CheckInJoinCD(curPlayer):
-    ## 检查是否加入仙盟CD中
+    ## 检查是否加入公会CD中
     leaveFamilyTime = PlayerControl.GetLeaveFamilyTimeEx(curPlayer)
     if not leaveFamilyTime:
         return False
@@ -711,25 +789,30 @@
         cdTimes = joinCDMinute * 60
         passTimes = int(time.time()) - leaveFamilyTime
         if passTimes < cdTimes:
-            GameWorld.DebugLog("加入仙盟CD中: leaveCnt=%s,kickedCnt=%s,lastVoluntarily=%s,leaveFamilyTime=%s(%s),passTimes=%s < %s" 
+            GameWorld.DebugLog("加入公会CD中: leaveCnt=%s,kickedCnt=%s,lastVoluntarily=%s,leaveFamilyTime=%s(%s),passTimes=%s < %s" 
                    % (leaveCnt, kickedCnt, lastVoluntarily, leaveFamilyTime, GameWorld.ChangeTimeNumToStr(leaveFamilyTime), passTimes, cdTimes))
             return True
     return False
 
-def AutoJoinFamily(curPlayer):
-    if curPlayer.GetFamilyID():
+def AutoJoinFamily(crossPlayer):
+    if crossPlayer.GetFamilyID():
         return
-    playerID = curPlayer.GetPlayerID()
-    realmLV = curPlayer.GetOfficialRank()
+    playerID = crossPlayer.GetPlayerID()
+    realmLV = crossPlayer.GetRealmLV()
     GameWorld.DebugLog("玩家一键自动加入家族! realmLV=%s" % realmLV, playerID)
-    if CheckInJoinCD(curPlayer):
-        return
+    #if CheckInJoinCD(curPlayer):
+    #    return
     
+    mainServerID = crossPlayer.GetMainServerID()
     familyMgr = DBDataMgr.GetFamilyMgr()
-    indexList = range(familyMgr.GetCount())
+    zoneID = familyMgr.GetZoneIDInThisServer(mainServerID)
+    if zoneID < 0:
+        return
+    zoneMgr = familyMgr.GetZoneFamilyMgr(zoneID)
+    indexList = range(zoneMgr.GetCount())
     random.shuffle(indexList) #打乱顺序
     for index in indexList:
-        family = familyMgr.GetAt(index)
+        family = zoneMgr.GetAt(index)
         if not family:
             continue
         #familyID = family.GetID()
@@ -746,16 +829,16 @@
             continue
         
         #直接加入
-        DoPlayerJionFamily(family, playerID, curPlayer)
+        DoPlayerJionFamily(family, playerID, crossPlayer)
         return
     
     # 可再扩展自动请求,暂时不处理
-    GameWorld.DebugLog("没有可自动进入的仙盟!")
-    PlayerControl.NotifyCode(curPlayer, "QuickEnterFamilyFail")
+    GameWorld.DebugLog("没有可自动进入的公会!")
+    CrossPlayer.NotifyCode(crossPlayer, "QuickEnterFamilyFail")
     return
 
 def GetFamilySetting(familyLV, fieldName):
-    ## 获取仙盟等级表对应字段值
+    ## 获取公会等级表对应字段值
     if not fieldName:
         return 0
     ipyData = IpyGameDataPY.GetIpyGameData("Family", familyLV)
@@ -766,23 +849,23 @@
         return 0
     return getattr(ipyData, attrName)()
 
-def RequestJoinTagFamily(curPlayer, familyID):
+def RequestJoinTagFamily(crossPlayer, familyID):
     ## 申请加入
-    if CheckInJoinCD(curPlayer):
-        return
-    playerID = curPlayer.GetPlayerID()
-    if curPlayer.GetFamilyID():
-        GameWorld.DebugLog('已经有仙盟不能再申请加入! familyID=%s' % curPlayer.GetFamilyID(), playerID)
+    #if CheckInJoinCD(curPlayer):
+    #    return
+    playerID = crossPlayer.GetPlayerID()
+    if crossPlayer.GetFamilyID():
+        GameWorld.DebugLog('已经有公会不能再申请加入! familyID=%s' % crossPlayer.GetFamilyID(), playerID)
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
     reqFamilyIDList = familyMgr.GetPlayerReqJoinFamilyIDList(playerID)
     if playerID in reqFamilyIDList:
-        GameWorld.DebugLog('已经在申请加入仙盟列表中! familyID=%s' % familyID, playerID)
+        GameWorld.DebugLog('已经在申请加入公会列表中! familyID=%s' % familyID, playerID)
         return
     
     maxReqFamilyCnt = IpyGameDataPY.GetFuncCfg("FamilyReqJoin", 2)
     if len(reqFamilyIDList) >= maxReqFamilyCnt:
-        GameWorld.DebugLog('已经达到最大申请加入仙盟数! %s, %s' % (len(reqFamilyIDList), reqFamilyIDList), playerID)
+        GameWorld.DebugLog('已经达到最大申请加入公会数! %s, %s' % (len(reqFamilyIDList), reqFamilyIDList), playerID)
         return
     
     tagFamily = familyMgr.FindFamily(familyID)
@@ -790,8 +873,8 @@
         return
     
     lvMin = tagFamily.GetJoinLVMin()
-    if curPlayer.GetOfficialRank() < lvMin:
-        GameWorld.DebugLog('官职未达到该仙盟加入最低限制! realmLV=%s < %s' % (curPlayer.GetOfficialRank(), lvMin), playerID)
+    if crossPlayer.GetRealmLV() < lvMin:
+        GameWorld.DebugLog('官职未达到该公会加入最低限制! realmLV=%s < %s' % (crossPlayer.GetRealmLV(), lvMin), playerID)
         return
     
     # 需要审核,满员后端不限制申请,由前端自行决定是否可申请
@@ -800,43 +883,43 @@
         if playerID not in reqPlayerIDDict:
             maxReqPlayerCnt = IpyGameDataPY.GetFuncCfg("FamilyReqJoin", 1)
             if len(reqPlayerIDDict) >= maxReqPlayerCnt:
-                GameWorld.DebugLog('目标仙盟申请加入数已满! %s, %s' % (len(reqFamilyIDList), reqFamilyIDList), playerID)
-                PlayerControl.NotifyCode(curPlayer, "jiazu_pan_141056")
+                GameWorld.DebugLog('目标公会申请加入数已满! %s, %s' % (len(reqFamilyIDList), reqFamilyIDList), playerID)
+                CrossPlayer.NotifyCode(crossPlayer, "jiazu_pan_141056")
                 return
             
         tagFamily.AddReqJoinPlayerID(playerID)
         # 广播给有招人权限的
-        Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
+        SendFamilyReqJoinInfo(familyID)
         
         #jiazu_pan_500807:申请入帮成功!请等待帮会管理人员审批! 
-        PlayerControl.NotifyCode(curPlayer, "jiazu_pan_500807")
-        Sync_RequestAddFamilyInfo(curPlayer)
+        CrossPlayer.NotifyCode(crossPlayer, "jiazu_pan_500807")
+        Sync_RequestAddFamilyInfo(crossPlayer)
         return
     
     # 不需要审核,自动加入
     memberMax = GetFamilySetting(tagFamily.GetLV(), "MemberMax")
     if tagFamily.GetCount() >= memberMax:
-        GameWorld.DebugLog('目标仙盟成员已满! familyLV=%s,memberMax=%s' % (tagFamily.GetLV(), memberMax), playerID)
+        GameWorld.DebugLog('目标公会成员已满! familyLV=%s,memberMax=%s' % (tagFamily.GetLV(), memberMax), playerID)
         return
     
-    DoPlayerJionFamily(tagFamily, playerID, curPlayer)
+    DoPlayerJionFamily(tagFamily, playerID, crossPlayer)
     return
 
-def CancelJoinTagFamily(curPlayer, familyID):
+def CancelJoinTagFamily(crossPlayer, familyID):
     # 撤销申请
     familyMgr = DBDataMgr.GetFamilyMgr()
-    playerID = curPlayer.GetPlayerID()
+    playerID = crossPlayer.GetPlayerID()
     tagFamily = familyMgr.FindFamily(familyID)
     if tagFamily:
         tagFamily.DelReqJoinPlayerID(playerID)
     familyMgr.DelPlayerReqJoinFamilyID(playerID, familyID)
-    Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
-    Sync_RequestAddFamilyInfo(curPlayer)
+    SendFamilyReqJoinInfo(familyID)
+    Sync_RequestAddFamilyInfo(crossPlayer)
     return
 
-def Sync_RequestAddFamilyInfo(curPlayer, isForce=True):
+def Sync_RequestAddFamilyInfo(crossPlayer, isForce=True):
     ## 通知当前申请加入的哪些家族
-    playerID = curPlayer.GetPlayerID()
+    playerID = crossPlayer.GetPlayerID()
     familyMgr = DBDataMgr.GetFamilyMgr()
     reqFamilyIDList = familyMgr.GetPlayerReqJoinFamilyIDList(playerID)
     # 非强制通知时没有申请记录的可不通知,如登录
@@ -846,7 +929,23 @@
     clientPack.Clear()
     clientPack.RequestJoinFamilyIDList = reqFamilyIDList
     clientPack.RequestCount = len(clientPack.RequestJoinFamilyIDList)
-    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    CrossPlayer.SendFakePack(crossPlayer, clientPack)
+    return
+
+def IsFamilyNeedViewPlayer(playerID):
+    ## 公会功能中查看玩家是否需要用到的
+    
+    # 公会成员已存储成员信息,所以成员不用判断,仅判断其他即可
+    # 是否有请求加入某个公会
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    if familyMgr.GetPlayerReqJoinFamilyIDList(playerID):
+        return True
+    
+    return False
+
+def SendFamilyReqJoinInfo(familyID):
+    ## 广播给公会有招人权限的
+    CrossPlayer.SendFakePackByFamily(familyID, GetPack_FamilyReqJoinInfo(familyID), None, GetFamilyMemberHasPow, FamilyPowerID_Call)
     return
 
 def GetPack_FamilyReqJoinInfo(familyID):
@@ -856,17 +955,18 @@
     if not curFamily:
         return
     reqPlayerIDDict = curFamily.GetReqJoinPlayerInfo()
-    
-    playerManager = GameWorld.GetPlayerManager()
+    #没人申请也要通知
+    #if not reqPlayerIDDict:
+    #    return
+    crossPlayerMgr = CrossPlayer.GetCrossPlayerMgr()
     clientPack = ChPyNetSendPack.tagMCFamilyReqJoinInfo()
     clientPack.ReqJoinList = []
     for playerID, reqTime in reqPlayerIDDict.items():
-        curPlayer = playerManager.FindPlayerByID(playerID)
+        crossPlayer = crossPlayerMgr.FindCrossPlayer(playerID)
         reqInfo = ChPyNetSendPack.tagMCFamilyReqJoinPlayer()
         reqInfo.PlayerID = playerID
         reqInfo.ReqTime = reqTime
-        if curPlayer:
-            reqInfo.IsOnLine = True
+        reqInfo.IsOnLine = 1 if crossPlayer else 0
         viewCache = PlayerViewCache.FindViewCache(playerID)
         if viewCache:
             reqInfo.Name = viewCache.GetPlayerName()
@@ -896,10 +996,16 @@
 #};
 def OnJoinFamilyReply(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnJoinFamilyReply")
+    return
+
+def __OnJoinFamilyReply(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
     tagPlayerID = clientData.TagPlayerID
     isOK = clientData.IsOK
-    playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
+    GameWorld.DebugLog("__OnJoinFamilyReply: tagPlayerID=%s,isOK=%s" % (tagPlayerID, isOK))
+    
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
     if familyID <= 0:
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
@@ -910,8 +1016,8 @@
     if not curMember:
         return
     if not GetFamilyMemberHasPow(curMember, FamilyPowerID_Call):
-        #GameWorld.DebugLog("没有招人权限,无法审核人员入盟!", playerID)
-        PlayerControl.NotifyCode(curPlayer, "XW_JZ_InviteErr_Popedom")
+        GameWorld.DebugLog("没有招人权限,无法审核人员入盟!", playerID)
+        #PlayerControl.NotifyCode(curPlayer, "XW_JZ_InviteErr_Popedom")
         return
     
     GameWorld.DebugLog("审核入盟申请: tagPlayerID=%s,familyID=%s,isOK=%s" % (tagPlayerID, familyID, isOK), playerID)
@@ -927,18 +1033,19 @@
         GameWorld.DebugLog("没有申请人员!")
         return
     
-    playerManager = GameWorld.GetPlayerManager()
+    crossPlayerMgr = CrossPlayer.GetCrossPlayerMgr()
     # 拒绝
     if not isOK:
         for tagPlayerID in tagPlayerIDList:
             family.DelReqJoinPlayerID(tagPlayerID)
-            tagPlayer = playerManager.FindPlayerByID(tagPlayerID)
-            if not tagPlayer:
+            tagCrossPlayer = crossPlayerMgr.FindCrossPlayer(tagPlayerID)
+            if not tagCrossPlayer:
                 continue
-            Sync_RequestAddFamilyInfo(tagPlayer)
+            Sync_RequestAddFamilyInfo(tagCrossPlayer)
             #jiazu_pan_592934:{%S}拒绝了您的入帮申请
-            PlayerControl.NotifyCode(tagPlayer, "jiazu_pan_592934", [family.GetName()])
-        Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
+            CrossPlayer.NotifyCode(tagCrossPlayer, "jiazu_pan_592934", [family.GetName()])
+            
+        SendFamilyReqJoinInfo(familyID)
         return
     
     # 处理同意
@@ -947,34 +1054,37 @@
     joinOKPlayerIDList = []
     for tagPlayerID in tagPlayerIDList:
         if family.GetCount() >= MemberMax:
-            PlayerControl.NotifyCode(curPlayer, "jiazu_lhs_202580")
+            CrossPlayer.NotifyCode(crossPlayer, "jiazu_lhs_202580")
             break
-        tagPlayer = playerManager.FindPlayerByID(tagPlayerID)
+        tagCrossPlayer = crossPlayerMgr.FindCrossPlayer(tagPlayerID)
         #申请目标不在线
-        if not tagPlayer:
+        if not tagCrossPlayer:
             if not offlinePlayerCanJoin:
-                GameWorld.DebugLog("离线玩家无法加入仙盟! tagPlayerID=%s" % tagPlayerID, playerID)
-                PlayerControl.NotifyCode(curPlayer, "jiazu_hwj35_367906")
+                GameWorld.DebugLog("离线玩家无法加入公会! tagPlayerID=%s" % tagPlayerID, playerID)
+                CrossPlayer.NotifyCode(crossPlayer, "jiazu_hwj35_367906")
                 continue
             
+        family.DelReqJoinPlayerID(tagPlayerID) # 以下只要操作的都删除
+        
         if family.FindMember(tagPlayerID):
             GameWorld.DebugLog("已经是本盟成员! tagPlayerID=%s" % tagPlayerID, playerID)
-            PlayerControl.NotifyCode(curPlayer, "XW_JZ_InviteErr_Repeat")
+            CrossPlayer.NotifyCode(crossPlayer, "XW_JZ_InviteErr_Repeat")
             continue
         
         tagFamilyID = familyMgr.GetPlayerFamilyID(tagPlayerID)
         if tagFamilyID:
-            GameWorld.DebugLog("已经加入其他仙盟! tagPlayerID=%s,tagFamilyID=%s" % (tagPlayerID, tagFamilyID), playerID)
-            PlayerControl.NotifyCode(curPlayer, "XW_JZ_InviteErr_Repeat")
+            GameWorld.DebugLog("已经加入其他公会! tagPlayerID=%s,tagFamilyID=%s" % (tagPlayerID, tagFamilyID), playerID)
+            CrossPlayer.NotifyCode(crossPlayer, "XW_JZ_InviteErr_Repeat")
             continue
         
-        DoPlayerJionFamily(family, tagPlayerID, tagPlayer, broadcastFamilyChange=False)
+        DoPlayerJionFamily(family, tagPlayerID, tagCrossPlayer, broadcastFamilyChange=False)
         joinOKPlayerIDList.append(tagPlayerID)
         
-    if not joinOKPlayerIDList:
-        return
-    Broadcast_FamilyChange(familyID, FamilyChangeType_MemJoin, excludeIDList=joinOKPlayerIDList)
-    Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
+    #if not joinOKPlayerIDList:
+    #    return
+    SendFamilyReqJoinInfo(familyID)
+    if joinOKPlayerIDList:
+        Broadcast_FamilyInfo(familyID, changeMemIDList=joinOKPlayerIDList)
     return
 
 #// A6 22 修改收人方式 #tagCMChangeFamilyJoin
@@ -987,11 +1097,16 @@
 #};
 def OnChangeFamilyJoin(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnChangeFamilyJoin")
+    return
+
+def __OnChangeFamilyJoin(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
     joinReview = clientData.JoinReview
     joinLVMin = clientData.JoinLVMin # 官职
+    GameWorld.DebugLog("__OnChangeFamilyJoin: joinReview=%s,joinLVMin=%s" % (joinReview, joinLVMin))
     
-    playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
     if familyID <= 0:
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
@@ -1007,8 +1122,7 @@
     GameWorld.DebugLog("修改招人设置: familyID=%s,joinReview=%s,joinLVMin=%s" % (familyID, joinReview, joinLVMin), playerID)
     family.SetJoinReview(joinReview)
     family.SetJoinLVMin(joinLVMin)
-    Sync_FamilyInfo(curPlayer)
-    Broadcast_FamilyChange(familyID, FamilyChangeType_JoinSet, FamilyPowerID_Call, excludeIDList=[playerID])
+    Broadcast_FamilyInfo(familyID, isSyncMem=False)
     return
 
 #// A6 23 修改家族公告 #tagCMChangeFamilyBroadcast
@@ -1020,10 +1134,14 @@
 #};
 def OnChangeFamilyBroadcast(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnChangeFamilyBroadcast")
+    return
+
+def __OnChangeFamilyBroadcast(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
     broadcast = clientData.Msg
     
-    playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
     if familyID <= 0:
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
@@ -1037,9 +1155,8 @@
         GameWorld.DebugLog("没有修改公告权限", playerID)
         return
     family.SetBroadcast(broadcast)
-    GameWorld.DebugLog('更改仙盟公告: Family=%s,公告=%s' % (GameWorld.CodeToGbk(family.GetName()), GameWorld.CodeToGbk(broadcast)), playerID)
-    Sync_FamilyInfo(curPlayer)
-    Broadcast_FamilyChange(familyID, FamilyChangeType_Broadcast, excludeIDList=[playerID])
+    GameWorld.DebugLog('更改公会公告: Family=%s,公告=%s' % (GameWorld.CodeToGbk(family.GetName()), GameWorld.CodeToGbk(broadcast)), playerID)
+    Broadcast_FamilyInfo(familyID, isSyncMem=False)
     return
 
 #// A6 24 修改家族徽章 #tagCMChangeFamilyEmblem
@@ -1052,9 +1169,13 @@
 #};
 def OnChangeFamilyEmblem(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnChangeFamilyEmblem")
+    return
+
+def __OnChangeFamilyEmblem(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
     changeEmblemID = clientData.EmblemID
     emblemWord = clientData.EmblemWord
-    PlayerFamilyEmblem.OnChangeFamilyEmblem(curPlayer, changeEmblemID, emblemWord)
+    PlayerFamilyEmblem.OnChangeFamilyEmblem(crossPlayer, changeEmblemID, emblemWord)
     return
 
 #// A6 25 修改家族成员职位 #tagCMChangeFamilyMemLV
@@ -1067,20 +1188,24 @@
 #};
 def OnChangeFamilyMemLV(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    OnChangeFamilyMemberLV(curPlayer, clientData.PlayerID, clientData.FmLV)
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnChangeFamilyMemLV")
     return
 
-def OnChangeFamilyMemberLV(curPlayer, tagID, changeFmlv, isGMOP=False):
+def __OnChangeFamilyMemLV(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
+    OnChangeFamilyMemberLV(crossPlayer, clientData.PlayerID, clientData.FmLV)
+    return
+
+def OnChangeFamilyMemberLV(crossPlayer, tagID, changeFmlv, isGMOP=False):
     '''变更成员职位
     @param curPlayer: 操作的玩家
     @param tagID: 目标成员ID
     @param changeFmlv: 修改为xx职位
     @param isGMOP: 是否是GM后台发起的,如果是GM发起的,一般curPlayer传入的为目标成员ID实例
     '''
-    if not curPlayer:
+    if not crossPlayer:
         return
-    playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
     if familyID <= 0:
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
@@ -1116,7 +1241,6 @@
                 return
             
     if changeFmlv == IPY_PlayerDefine.fmlLeader:
-        changeType = FamilyChangeType_LeaderChange
         ChangeFamilyLeader(family, tagMember)
         
     else:
@@ -1130,16 +1254,14 @@
         maxCnt = GetFamilySetting(family.GetLV(), Def_FmlSetAttrName.get(changeFmlv, ""))
         if fmLVMemCnt >= maxCnt:
             # jiazu_hwj35_272921 改为 jiazu_chenxin_31379
-            PlayerControl.NotifyCode(curPlayer, "jiazu_chenxin_31379")
+            CrossPlayer.NotifyCode(crossPlayer, "jiazu_chenxin_31379")
             GameWorld.DebugLog("目前该职位的人数已经达到上限! changeFmlv=%s,fmLVMemCnt=%s >= %s" % (changeFmlv, fmLVMemCnt, maxCnt))
             return
-        changeType = FamilyChangeType_MemFmlvChange
         ChangeFamilyMemberLv(tagMember, changeFmlv)
         
     if isGMOP:
         family.SetBroadcast("")
-    Sync_FamilyInfo(curPlayer)
-    Broadcast_FamilyChange(familyID, changeType, excludeIDList=[playerID, tagID])
+    Broadcast_FamilyInfo(familyID, changeMemIDList=[tagID])
     return True
 
 def ChangeFamilyLeader(family, newLeaderMem):
@@ -1170,12 +1292,11 @@
     
     tagMember.SetFmLV(changeFamilyLV)
     
-    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagID)
-    if tagPlayer:
-        MapServer_FamilyRefresh(tagPlayer, familyID)
-        Sync_FamilyInfo(tagPlayer)
+    tagCrossPlayer = CrossPlayer.GetCrossPlayerMgr().FindCrossPlayer(tagID)
+    if tagCrossPlayer:
+        MapServer_FamilyRefresh(tagCrossPlayer, familyID)
         if GetFamilyMemberHasPow(tagMember, FamilyPowerID_Call):
-            NetPackCommon.SendFakePack(tagPlayer, GetPack_FamilyReqJoinInfo(familyID))
+            CrossPlayer.SendFakePack(tagCrossPlayer, GetPack_FamilyReqJoinInfo(familyID))
         
     # 记录家族事件记录信息
     tick = GameWorld.GetGameWorld().GetTick()
@@ -1183,7 +1304,7 @@
                         [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_FMLV, changeFamilyLV, befFamilyLV], tick)
     
     #xx被任命为xx
-    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_AppointFamily", [memName, changeFamilyLV])
+    #NotifyAllFamilyMemberMsg(familyID, "XW_JZ_AppointFamily", [memName, changeFamilyLV])
     #GetFamilyMgr().SetSyncCrossFamilyUpd(familyMember.GetFamilyID(), familyMember.GetPlayerID(), syncNow=True) # 成员职位变更
     return
 
@@ -1251,10 +1372,11 @@
     GameWorld.Log("公会自动传位: familyID=%s,leaderID=%s,offTime=%s,passHours=%s,newLeaderID=%s" 
                   % (familyID, leaderID, GameWorld.ChangeTimeNumToStr(offTime), passHours, newLeaderID))
     ChangeFamilyLeader(curFamily, toMember)
-    Broadcast_FamilyChange(familyID, FamilyChangeType_LeaderChange, excludeIDList=[leaderID, newLeaderID])
+    Broadcast_FamilyInfo(familyID, changeMemIDList=[leaderID, newLeaderID])
     
     # 邮件通知
-    PlayerMail.SendMailByKey("FamilyLeaderAutoChange", newLeaderID, [], [curFamily.GetName()])
+    toServerID = toMember.GetServerID()
+    PlayerMail.SendMailByKey("FamilyLeaderAutoChange", newLeaderID, [], [curFamily.GetName()], toServerID=toServerID)
     return
 
 #// A6 26 请求家族成员列表 #tagCMGetFamilyInfo
@@ -1264,8 +1386,9 @@
 #    tagHead        Head;
 #};
 def OnGetFamilyInfo(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    Sync_FamilyInfo(curPlayer)
+    #改为后端主动同步差异,不用再请求了
+    #curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    #Sync_FamilyInfo(crossPlayer)
     return
 
 #// A6 03 离开家族 #tagCMLeaveFamily
@@ -1276,9 +1399,12 @@
 #};
 def OnLeaveFamily(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    
-    playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnMemLeaveFamily")
+    return
+
+def __OnMemLeaveFamily(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
     if familyID <= 0:
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
@@ -1294,7 +1420,7 @@
         GameWorld.DebugLog("族长在成员人数大于1时不能直接退出家族", playerID)
         return
     
-    # 功能限制退出仙盟
+    # 功能限制退出公会
     # ...
     
     # 进出时间限制暂不做,等正式功能再补
@@ -1304,20 +1430,21 @@
     GameWorld.DebugLog("离开家族! familyID=%s" % familyID, playerID)
     
     family.DeleteMember(playerID)
-    AddFamilyActionNote(curPlayer.GetName(), familyID, ShareDefine.Def_ActionType_FamilyEvent, 
+    AddFamilyActionNote(crossPlayer.GetPlayerName(), familyID, ShareDefine.Def_ActionType_FamilyEvent, 
                         [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_Leave], tick)
     
     #XW_JZ_LeaveFamily   <n color="0,190,255">{%S1%}</n><n color="255,255,0">退出了家族!</n>  25  -   -
-    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaveFamily", [curPlayer.GetName()])
+    #NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaveFamily", [curPlayer.GetName()])
     
-    __DoPlayerLeaveFamilyByID(family, playerID, curPlayer)
-    MapServer_FamilyRefresh(curPlayer, 0, 1)
+    __DoPlayerLeaveFamilyByID(family, playerID, crossPlayer)
+    MapServer_FamilyRefresh(crossPlayer, 0, 1)
+    CrossPlayer.SendFakePackByFamily(familyID, GetPack_FamilyDel(playerID, crossPlayer.GetPlayerName(), 1))
     
     if family.GetCount() == 0:
         #玩家离开后, 家族没有人了 , 删除这个家族
         familyMgr.DelFamily(familyID)
         return
-    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLeave)
+    
     return
 
 #// A6 05 删除家族成员 #tagCMDeleteFamilyMember
@@ -1329,13 +1456,18 @@
 #};
 def OnDeleteFamilyMember(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnDeleteFamilyMember")
+    return
+
+def __OnDeleteFamilyMember(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
     tagMemberID = clientData.MemberID
+    GameWorld.DebugLog("__OnDeleteFamilyMember tagMemberID=%s" % tagMemberID)
     
-    playerID = curPlayer.GetPlayerID()
+    playerID = crossPlayer.GetPlayerID()
     if playerID == tagMemberID:
         return
     
-    familyID = curPlayer.GetFamilyID()
+    familyID = crossPlayer.GetFamilyID()
     if familyID <= 0:
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
@@ -1372,20 +1504,20 @@
                         [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_KickOut], tick)
     
     #XW_JZ_LeaveFamily   <n color="0,190,255">{%S1%}</n><n color="255,255,0">退出了家族!</n>  25  -   -
-    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaveFamily", [tagPlayerName])
+    #NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaveFamily", [tagPlayerName])
     
     #删除玩家
-    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagMemberID)
-    __DoPlayerLeaveFamilyByID(family, tagPlayerID, tagPlayer)
-    if tagPlayer:
-        MapServer_FamilyRefresh(tagPlayer, 0)
+    crossPlayer = CrossPlayer.GetCrossPlayerMgr().FindCrossPlayer(tagMemberID)
+    __DoPlayerLeaveFamilyByID(family, tagPlayerID, crossPlayer)
+    if crossPlayer:
+        MapServer_FamilyRefresh(crossPlayer, 0)
         
-    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLeave)
+    CrossPlayer.SendFakePackByFamily(familyID, GetPack_FamilyDel(tagMemberID, tagPlayerName, 0))
     return
 
-def __DoPlayerLeaveFamilyByID(curFamily, leavePlayerID, tagPlayer=None):
+def __DoPlayerLeaveFamilyByID(curFamily, leavePlayerID, crossPlayer=None):
     ## 有玩家离开家族处理,主要针对家族层级的,玩家个人的在 __OnLeaveFamily 处理
-    PlayerFamilyTaofa.OnFamilyMemberLeave(curFamily, leavePlayerID, tagPlayer)
+    PlayerFamilyTaofa.OnFamilyMemberLeave(curFamily, leavePlayerID)
     return
 
 #// A6 11 家族改名 #tagCMRenameFamily
@@ -1400,10 +1532,21 @@
 def UpdateFamilyName(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
     newName = clientData.NewName
+    if not CheckInputFamilyName(curPlayer, newName):
+        GameWorld.DebugLog("名字验证不通过")
+        return
+    moneyType, moneyValue = IpyGameDataPY.GetFuncEvalCfg("FamilyRename", 1)
+    if moneyType and moneyValue and not PlayerControl.HaveMoney(curPlayer, moneyType, moneyValue):
+        return
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__UpdateFamilyName", True, 20)
+    return
+
+def __UpdateFamilyName(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
+    newName = clientData.NewName
     #itemIndex = clientData.ItemIndex
     
-    playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
     if familyID <= 0:
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
@@ -1418,42 +1561,39 @@
         GameWorld.DebugLog("非盟主不可改名!", playerID)
         return
     
+    curTime = int(time.time())
     cdHours = IpyGameDataPY.GetFuncCfg("FamilyRename", 2)
     if cdHours:
         cdSeconds = cdHours * 3600
-        curTime = int(time.time())
-        dataAction = GetFamilyDataAction(familyID)
-        lastRenameTime = GetRenameTime(dataAction)
+        lastRenameTime = GetRenameTime(family)
         if lastRenameTime and (curTime - lastRenameTime) < cdSeconds:
-            GameWorld.DebugLog("仙盟改名CD中! lastRenameTime=%s,cdHours=%s" % (GameWorld.ChangeTimeNumToStr(lastRenameTime), cdHours))
+            GameWorld.DebugLog("公会改名CD中! lastRenameTime=%s,cdHours=%s" % (GameWorld.ChangeTimeNumToStr(lastRenameTime), cdHours))
             return
         
-    familyName = CheckInputFamilyName(curPlayer, newName)
-    if not familyName:
+    # 验证重名
+    if CheckFamilyNameExists(crossPlayer, newName, fromServerID):
         return
     
     moneyType, moneyValue = IpyGameDataPY.GetFuncEvalCfg("FamilyRename", 1)
-    if moneyType and moneyValue and not PlayerControl.PayMoney(curPlayer, moneyType, moneyValue, "FamilyRename"):
-        return
-    
-    family.SetName(familyName)
-    
-    infoPack = GetPack_FamilyInfo(familyID)
-    playerManager = GameWorld.GetPlayerManager()
+    if moneyType and moneyValue:
+        CrossPlayer.CostPlayerResources(crossPlayer, "FamilyRename", costMoneyDict={moneyType:moneyValue})
+        
+    family.SetName(newName)        
+    if cdHours:
+        SetRenameTime(family, curTime)
+        
+    crossPlayerMgr = CrossPlayer.GetCrossPlayerMgr()
     for index in xrange(family.GetCount()):
         member = family.GetAt(index)
         memID = member.GetPlayerID()
-        player = playerManager.FindPlayerByID(memID)
-        if not player:
+        memCrossPlayer = crossPlayerMgr.FindCrossPlayer(memID)
+        if not memCrossPlayer:
             continue
-        Sync_FamilyInfo(player, infoPack)
-        player.SetFamilyName(familyName)
+        MapServer_FamilyRefresh(memCrossPlayer, familyID)
         #player.Notify_FamilyNameRefresh() #//04 36    周围玩家家族名刷新#tagPlayerFamilyNameRefresh
         
-    if cdHours:
-        SetRenameTime(dataAction, curTime)
-        SendFamilyActionInfo(None, familyID, ShareDefine.Def_ActionType_FamilyData)
-    return
+    Broadcast_FamilyInfo(familyID, isSyncMem=False)
+    return True
 
 #// A6 20 搜索家族列表 #tagCMViewFamilyPage
 #
@@ -1467,12 +1607,25 @@
 #};
 def OnViewFamilyPage(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnViewFamilyPage")
+    return
+
+def __OnViewFamilyPage(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
     msg = clientData.Msg
     pageIndex = clientData.PageIndex
     showCount = min(clientData.ShowCount, 50)
     
     familyMgr = DBDataMgr.GetFamilyMgr()
-    familyCount = familyMgr.GetCount()
+    zoneID = familyMgr.GetZoneIDInThisServer(fromServerID)
+    if zoneID < 0:
+        GameWorld.ErrLog("找不到服务器ID在本服中的公会分区! fromServerID=%s" % fromServerID)
+        return
+    
+    playerFamilyID = crossPlayer.GetFamilyID()
+    zoneMgr = familyMgr.GetZoneFamilyMgr(zoneID)
+    zoneMgr.Sort(True)
+    familyCount = zoneMgr.GetCount()
+    
     totalPage = 0
     
     if not msg:
@@ -1495,11 +1648,12 @@
     clientPack.PageIndex = pageIndex
     clientPack.ShowCount = showCount
     clientPack.TotalPage = totalPage
+    clientPack.Rank = zoneMgr.GetFamilyRank(playerFamilyID)
     clientPack.FamilyList = []
     for index in range(startIndex, endIndex + 1):
         if index >= familyCount:
             break
-        family = familyMgr.GetAt(index)
+        family = zoneMgr.GetAt(index)
         if not family:
             continue
         if msg:
@@ -1529,7 +1683,7 @@
         clientPack.FamilyCount = len(clientPack.FamilyList)
         if clientPack.FamilyCount >= showCount:
             break
-    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    CrossPlayer.SendFakePack(crossPlayer, clientPack)
     return
 
 
@@ -1542,18 +1696,8 @@
 #};
 def OnFamilyMoneyDonate(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    donateType = clientData.DonateType
     playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
-    if familyID <= 0:
-        return
-    familyMgr = DBDataMgr.GetFamilyMgr()
-    curFamily = familyMgr.FindFamily(familyID)
-    if not curFamily:
-        return
-    curMember = curFamily.FindMember(playerID)
-    if not curMember:
-        return
+    donateType = clientData.DonateType
     
     ipyData = IpyGameDataPY.GetIpyGameData("FamilyDonate", donateType)
     if not ipyData:
@@ -1568,13 +1712,49 @@
     moneyValue = ipyData.GetMoneyValue()
     if not moneyType or not moneyValue:
         return
-    if not PlayerControl.PayMoney(curPlayer, moneyType, moneyValue, "FamilyMoneyDonate"):
+    if not PlayerControl.HaveMoney(curPlayer, moneyType, moneyValue):
         return
+    
+    reqDataEx = {"donateCnt":donateCnt}
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnFamilyMoneyDonate", True, 20, reqDataEx=reqDataEx)
+    return
+
+def __OnFamilyMoneyDonate(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
+    donateType = clientData.DonateType
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
+        return
+    curMember = curFamily.FindMember(playerID)
+    if not curMember:
+        return
+    
+    if not reqDataEx:
+        return
+    
+    if "donateCnt" not in reqDataEx:
+        return
+    donateCnt = reqDataEx["donateCnt"]
+    
+    ipyData = IpyGameDataPY.GetIpyGameData("FamilyDonate", donateType)
+    if not ipyData:
+        return
+    
+    moneyType = ipyData.GetMoneyType()
+    moneyValue = ipyData.GetMoneyValue()
+    if not moneyType or not moneyValue:
+        return
+    
+    CrossPlayer.CostPlayerResources(crossPlayer, "FamilyMoneyDonate", costMoneyDict={moneyType:moneyValue})
     
     awardItemList = ipyData.GetAwardItemList()
     donateCnt += 1
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyDonateCnt % donateType, donateCnt)
-    SyncDonateCntInfo(curPlayer)
+    CrossPlayer.SetPlayerNomalDict(crossPlayer, {ChConfig.Def_Player_Dict_FamilyDonateCnt % donateType:donateCnt}, isDayReset=True)
+    #SyncDonateCntInfo(curPlayer)
     # 增加成员捐献次数记录
     memDonateCntDay = curMember.GetDonateCntDay() + 1
     memDonateCntTotal = min(curMember.GetDonateCntTotal() + 1, ChConfig.Def_UpperLimit_DWord)
@@ -1582,7 +1762,308 @@
     curMember.SetDonateCntTotal(memDonateCntTotal)
     GameWorld.DebugLog("家族捐献: donateType=%s,donateCnt=%s,%s,memDonateCntDay=%s,memDonateCntDay=%s" 
                        % (donateType, donateCnt, awardItemList, memDonateCntDay, memDonateCntTotal), playerID)
-    ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["FamilyMoneyDonate", False, {}])
+    CrossPlayer.GivePlayerResources(crossPlayer, awardItemList, eventName="FamilyMoneyDonate")
+    return True
+
+def __OnFamilyMoneyDonate_Ret(curPlayer, clientData, isOK):
+    if not isOK:
+        return
+    SyncDonateCntInfo(curPlayer)
+    return
+
+def AddFamilyExp(curPlayer, addExp):
+    ## 增加玩家家族经验
+    clientData, tick = None, 0
+    reqDataEx = {"addExp":addExp}
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__AddFamilyExp", reqCD=0, reqDataEx=reqDataEx)
+    return
+def __AddFamilyExp(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
+        return
+    curLV = curFamily.GetLV()
+    curExp = curFamily.GetExp()
+    
+    if not reqDataEx:
+        return
+    addExp = reqDataEx["addExp"]
+    
+    updLV = curLV
+    updExp = curExp + addExp
+    GameWorld.DebugLog("增加公会经验: curLV=%s,curExp=%s,addExp=%s,updExp=%s" % (curLV, curExp, addExp, updExp), playerID)
+    
+    ipyData = IpyGameDataPY.GetIpyGameData("Family", curLV)
+    lvUPExp = ipyData.GetNeedExp()
+    while lvUPExp and updExp >= lvUPExp:
+        ipyData = IpyGameDataPY.GetIpyGameDataNotLog("Family", updLV + 1)
+        if not ipyData:
+            break
+        updLV += 1
+        updExp -= lvUPExp
+        lvUPExp = ipyData.GetNeedExp()
+        GameWorld.DebugLog("    公会升级: updLV=%s,updExp=%s,lvUPExp=%s" % (updLV, updExp, lvUPExp), playerID)
+        
+    curFamily.SetLV(updLV)
+    curFamily.SetExp(updExp)
+    
+    Broadcast_FamilyInfo(familyID, isSyncMem=False)
+    return True
+
+def AddFamilyContrib(curPlayer, addContribValue):
+    ## 增加玩家累计家族贡献
+    clientData, tick = None, 0
+    reqDataEx = {"addContribValue":addContribValue}
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__AddFamilyContrib", reqCD=0, reqDataEx=reqDataEx)
+    return
+def __AddFamilyContrib(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
+        return
+    curMember = curFamily.FindMember(playerID)
+    if not curMember:
+        return
+    
+    if not reqDataEx:
+        return
+    addContribValue = reqDataEx["addContribValue"]
+    
+    contribDay = curMember.GetContribDay() + addContribValue
+    contribTotal = min(curMember.GetContribTotal() + addContribValue, ChConfig.Def_UpperLimit_DWord)
+    curMember.SetContribDay(contribDay)
+    curMember.SetContribTotal(contribTotal)
+    GameWorld.DebugLog("增加成员贡献: familyID=%s,addContribValue=%s,contribDay=%s,contribTotal=%s" % (familyID, addContribValue, contribDay, contribTotal), playerID)
+    
+    Broadcast_FamilyInfo(familyID, isSyncMem=False)
+    return
+
+## ------------------------------------------------------------------------------------------------
+
+#// A6 17 查询家族行为信息 #tagCMQueryFamilyAction
+#
+#struct    tagCMQueryFamilyAction
+#{
+#    tagHead        Head;
+#    BYTE        ActionType;        // 行为类型
+#    DWORD        FamilyID;         // 家族ID,发0默认自己家族
+#};
+def OnQueryFamilyAction(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    FamilyPyPackForwarding(curPlayer, clientData, tick, "__OnQueryFamilyAction")
+    return
+
+def __OnQueryFamilyAction(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
+    actionType = clientData.ActionType
+    familyID = clientData.FamilyID
+    if not familyID:
+        familyID = crossPlayer.GetFamilyID()
+    SendFamilyActionInfo(crossPlayer, familyID, actionType)
+    return
+
+def SendFamilyActionInfo(crossPlayer, familyID, actionType):
+    ## 发送家族行为
+    # @param crossPlayer: 为None时通知该公会所有成员
+    if not familyID:
+        return
+    familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, actionType)
+    
+    clientPack = ChPyNetSendPack.tagMCFamilyActionInfo()
+    clientPack.FamilyID = familyID
+    clientPack.ActionType = actionType
+    clientPack.FamilyActionList = []
+    
+    for index in xrange(familyAction.Count()):
+        familyActionData = familyAction.At(index)
+        
+        actionData = ChPyNetSendPack.tagMCFamilyAction()
+        actionData.Time = familyActionData.GetTime()
+        actionData.Name = familyActionData.GetName()
+        actionData.NameLen = len(actionData.Name)
+        actionData.Value1 = familyActionData.GetValue1()
+        actionData.Value2 = familyActionData.GetValue2()
+        actionData.Value3 = familyActionData.GetValue3()
+        actionData.Value4 = familyActionData.GetValue4()
+        actionData.Value5 = familyActionData.GetValue5()
+        actionData.Value6 = familyActionData.GetValue6()
+        actionData.UseData = familyActionData.GetUserData()
+        actionData.UseDataLen = len(actionData.UseData)
+        clientPack.FamilyActionList.append(actionData)
+        
+    clientPack.Count = len(clientPack.FamilyActionList)
+    
+    if crossPlayer:
+        CrossPlayer.SendFakePack(crossPlayer, clientPack)
+        return
+    CrossPlayer.SendFakePackByFamily(familyID, clientPack)
+    return
+
+def SendFamilyAction(actionDataList, crossPlayer=None):
+    ## 同步指定公会action
+    # @param actionDataList: 支持列表或指定actionData
+    # @param crossPlayer: 为None时通知该公会所有成员
+    if not isinstance(actionDataList, list):
+        actionDataList = [actionDataList]
+    if not actionDataList:
+        return
+    familyActionData = actionDataList[0]
+    familyID = familyActionData.GetFamilyID()
+    actionType = familyActionData.GetActionType()
+    
+    clientPack = ChPyNetSendPack.tagMCFamilyActionInfo()
+    clientPack.FamilyID = familyID
+    clientPack.ActionType = actionType
+    clientPack.FamilyActionList = []
+    for familyActionData in actionDataList:
+        actionData = ChPyNetSendPack.tagMCFamilyAction()
+        actionData.Time = familyActionData.GetTime()
+        actionData.Name = familyActionData.GetName()
+        actionData.NameLen = len(actionData.Name)
+        actionData.Value1 = familyActionData.GetValue1()
+        actionData.Value2 = familyActionData.GetValue2()
+        actionData.Value3 = familyActionData.GetValue3()
+        actionData.Value4 = familyActionData.GetValue4()
+        actionData.Value5 = familyActionData.GetValue5()
+        actionData.Value6 = familyActionData.GetValue6()
+        actionData.UseData = familyActionData.GetUserData()
+        actionData.UseDataLen = len(actionData.UseData)
+        clientPack.FamilyActionList.append(actionData)
+    clientPack.Count = len(clientPack.FamilyActionList)
+    
+    if crossPlayer:
+        CrossPlayer.SendFakePack(crossPlayer, clientPack)
+        return
+    CrossPlayer.SendFakePackByFamily(familyID, clientPack)
+    return
+
+## -------------------------------------- 游戏服本服处理 --------------------------------------------
+'''
+为方便本服、跨服互通公会逻辑统一,公会相关数据处理统一使用 CrossPlayer,视为以前的GameServer处理,这样本服跨服的公会管理通用
+本服的curPlayer仅处理以前类似MapServer的curPlayer相关逻辑
+【注】 MapServer的逻辑不能再直接获取 family 实例进行逻辑处理,只能处理 curPlayer 可用的逻辑
+'''
+
+def C2S_FamilyMapPlayer(dataMsg, playerID):
+    curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+    if not curPlayer:
+        return
+    doType = dataMsg["doType"]
+    doData = dataMsg["doData"]
+    if doType == "FamilyRefresh":
+        Do_MapServer_FamilyRefresh(curPlayer, doData)
+    return
+
+def Do_MapServer_PlayerOnDay(curPlayer):
+    ResetDailyDonateCnt(curPlayer)
+    return
+
+def Do_MapServer_PlayerLogin(curPlayer):
+    SyncDonateCntInfo(curPlayer)
+    PlayerFamilyZhenbaoge.OnPlayerLogin(curPlayer)
+    return
+
+def Do_MapServer_FamilyRefresh(curPlayer, doData):
+    tick = GameWorld.GetGameWorld().GetTick()
+    playerID = curPlayer.GetPlayerID()
+    refreshFamilyID = doData["FamilyID"]
+    refreshFmLV = doData.get("FmLV", 0)
+    refreshFamilyLV = doData.get("FamilyLV", 0)
+    refreshFamilyName = doData.get("FamilyName", "")
+    refreshEmblemID = doData.get("EmblemID", 0)
+    refreshEmblemWord = doData.get("EmblemWord", "")
+    
+    PlayerViewCache.UpdPlayerViewFamilyInfo(playerID, refreshFamilyID, refreshFamilyName, refreshEmblemID, refreshEmblemWord)
+    
+    lastFamilyID = curPlayer.GetFamilyID()
+    lastFamilyLV = curPlayer.GetFamilyLV() # 公会等级,非职位等级
+    lastFmLV = PlayerControl.GetFamilyMemberLV(curPlayer)
+    
+    if lastFamilyID != refreshFamilyID:
+        curPlayer.SetFamilyID(refreshFamilyID)
+        
+    if curPlayer.GetFamilyName() != refreshFamilyName:
+        curPlayer.SetFamilyName(refreshFamilyName)
+        #curPlayer.Notify_FamilyNameRefresh() #//04 36    周围玩家家族名刷新#tagPlayerFamilyNameRefresh
+        
+    if lastFmLV != refreshFmLV:
+        PlayerControl.SetFamilyMemberLV(curPlayer, refreshFmLV)
+        
+    if lastFamilyLV != refreshFamilyLV:
+        isLVUP = False
+        if lastFamilyLV and refreshFamilyLV > 0:
+            #触发家族升级事件
+            isLVUP = True
+        curPlayer.SetFamilyLV(refreshFamilyLV)
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyLV, refreshFamilyLV)
+        #触发家族升级事件, 在SetFamilyLV之后,任务可以取等级判定
+        if isLVUP:
+            pass
+        
+    if lastFamilyID != 0 and curPlayer.GetFamilyID() == 0:
+        #玩家离开家族
+        isVoluntarily = doData.get("isVoluntarily", 0)
+        __OnLeaveFamily(curPlayer, isVoluntarily, tick)
+        
+    elif lastFamilyID == 0 and curPlayer.GetFamilyID() != 0:
+        #刚进家族并为族长,触发建家族事件
+        if curPlayer.GetFamilyMemberLV() == IPY_GameWorld.fmlLeader:
+            pass
+            
+        #进入家族触发事件
+        __OnEnterFamily(curPlayer, tick)
+        
+    #---通知客户端刷新属性---
+    curPlayer.View_FamilyInfoRefresh() #//04 30 玩家家族名字职位等信息刷新#tagPlayerInFamilyInfoRefresh
+    return
+
+def __OnEnterFamily(curPlayer, tick):
+    ## 进入家族触发事件
+    PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_ReqOrJoinFamily)
+    return
+
+def __OnLeaveFamily(curPlayer, isVoluntarily, tick):
+    ## 退出家族触发事件
+    #---清空家族相关信息---
+    curPlayer.SetPerExp(0)
+    curPlayer.SetFamilyHornor(0)
+    curPlayer.SetFamilyActiveValue(0)
+    curPlayer.SetLastWeekFamilyActiveValue(0)
+    curPlayer.SetFamilyLV(0)
+    PlayerControl.SetLeaveFamilyTimeEx(curPlayer, int(time.time()))
+    leaveCnt, kickedCnt, _ = PlayerControl.GetLeaveFamilyInfo(curPlayer)
+    GameWorld.DebugLog("__OnLeaveFamily: isVoluntarily=%s,leaveCnt=%s,kickedCnt=%s" % (isVoluntarily, leaveCnt, kickedCnt))
+    delMoneyType, delMoneyPer = IpyGameDataPY.GetFuncCfg("FamilyLeave", 3), 0
+    if isVoluntarily:
+        delMoneyPerList = IpyGameDataPY.GetFuncEvalCfg("FamilyLeave", 4)
+        if delMoneyPerList:
+            delMoneyPer = delMoneyPerList[leaveCnt] if len(delMoneyPerList) > leaveCnt else delMoneyPerList[-1]
+            
+        leaveCnt += 1
+        GameWorld.DebugLog("    增加主动离开次数: leaveCnt=%s" % (leaveCnt))
+    else:
+        delMoneyPerList = IpyGameDataPY.GetFuncEvalCfg("FamilyLeave", 5)
+        if delMoneyPerList:
+            delMoneyPer = delMoneyPerList[kickedCnt] if len(delMoneyPerList) > kickedCnt else delMoneyPerList[-1]
+            
+        kickedCnt += 1
+        GameWorld.DebugLog("    增加被踢离开次数: kickedCnt=%s" % (kickedCnt))
+    PlayerControl.SetLeaveFamilyInfo(curPlayer, leaveCnt, kickedCnt, isVoluntarily)
+    if delMoneyType and delMoneyPer:
+        nowMoney = PlayerControl.GetMoney(curPlayer, delMoneyType)
+        delMoney = int(nowMoney * delMoneyPer / 100.0)
+        GameWorld.DebugLog("    扣除货币: delMoneyType=%s,delMoneyPer=%s,nowMoney=%s,delMoney=%s" % (delMoneyType, delMoneyPer, nowMoney, delMoney))        
+        PlayerControl.PayMoney(curPlayer, delMoneyType, delMoney, "LeaveFamily")
+        
+    PlayerFamilyTaofa.OnPlayerLeaveFamily(curPlayer)
+    FBLogic.OnLeaveFamily(curPlayer, tick)
     return
 
 def ResetDailyDonateCnt(curPlayer):
@@ -1614,163 +2095,3 @@
     clientPack.Count = len(clientPack.DonateCntList)
     NetPackCommon.SendFakePack(curPlayer, clientPack)
     return
-
-def AddFamilyExp(curPlayer, addExp):
-    ## 增加玩家家族经验
-    playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
-    if familyID <= 0:
-        return
-    familyMgr = DBDataMgr.GetFamilyMgr()
-    curFamily = familyMgr.FindFamily(familyID)
-    if not curFamily:
-        return
-    curLV = curFamily.GetLV()
-    curExp = curFamily.GetExp()
-    
-    updLV = curLV
-    updExp = curExp + addExp
-    GameWorld.DebugLog("增加仙盟经验: curLV=%s,curExp=%s,addExp=%s,updExp=%s" % (curLV, curExp, addExp, updExp), playerID)
-    
-    ipyData = IpyGameDataPY.GetIpyGameData("Family", curLV)
-    lvUPExp = ipyData.GetNeedExp()
-    while lvUPExp and updExp >= lvUPExp:
-        ipyData = IpyGameDataPY.GetIpyGameDataNotLog("Family", updLV + 1)
-        if not ipyData:
-            break
-        updLV += 1
-        updExp -= lvUPExp
-        lvUPExp = ipyData.GetNeedExp()
-        GameWorld.DebugLog("    仙盟升级: updLV=%s,updExp=%s,lvUPExp=%s" % (updLV, updExp, lvUPExp), playerID)
-        
-    curFamily.SetLV(updLV)
-    curFamily.SetExp(updExp)
-    
-    Sync_FamilyInfo(curPlayer)
-    Broadcast_FamilyChange(familyID, FamilyChangeType_FamilyLVExp, excludeIDList=[playerID])
-    return True
-
-def AddFamilyContrib(curPlayer, addContribValue):
-    ## 增加玩家累计家族贡献
-    
-    playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
-    if familyID <= 0:
-        return
-    familyMgr = DBDataMgr.GetFamilyMgr()
-    curFamily = familyMgr.FindFamily(familyID)
-    if not curFamily:
-        return
-    curMember = curFamily.FindMember(playerID)
-    if not curMember:
-        return
-    
-    contribDay = curMember.GetContribDay() + addContribValue
-    contribTotal = min(curMember.GetContribTotal() + addContribValue, ChConfig.Def_UpperLimit_DWord)
-    curMember.SetContribDay(contribDay)
-    curMember.SetContribTotal(contribTotal)
-    GameWorld.DebugLog("增加成员贡献: familyID=%s,addContribValue=%s,contribDay=%s,contribTotal=%s" % (familyID, addContribValue, contribDay, contribTotal), playerID)
-    
-    Sync_FamilyInfo(curPlayer)
-    Broadcast_FamilyChange(familyID, FamilyChangeType_MemContrib, excludeIDList=[playerID])
-    return
-
-## ------------------------------------------------------------------------------------------------
-
-#// A6 17 查询家族行为信息 #tagCMQueryFamilyAction
-#
-#struct    tagCMQueryFamilyAction
-#{
-#    tagHead        Head;
-#    BYTE        ActionType;        // 行为类型
-#    DWORD        FamilyID;         // 家族ID,发0默认自己家族
-#};
-def OnQueryFamilyAction(index, cliendData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    
-    if not curPlayer:
-        return
-    
-    actionType = cliendData.ActionType
-    familyID = cliendData.FamilyID
-    if not familyID:
-        familyID = curPlayer.GetFamilyID()
-        
-    SendFamilyActionInfo(curPlayer, familyID, actionType)
-    return
-
-def SendFamilyActionInfo(curPlayer, familyID, actionType):
-    ## 发送家族行为
-    # @param curPlayer: 为None时通知该仙盟所有成员
-    if not familyID:
-        return
-    familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, actionType)
-    
-    clientPack = ChPyNetSendPack.tagMCFamilyActionInfo()
-    clientPack.FamilyID = familyID
-    clientPack.ActionType = actionType
-    clientPack.FamilyActionList = []
-    
-    for index in xrange(familyAction.Count()):
-        familyActionData = familyAction.At(index)
-        
-        actionData = ChPyNetSendPack.tagMCFamilyAction()
-        actionData.Time = familyActionData.GetTime()
-        actionData.Name = familyActionData.GetName()
-        actionData.NameLen = len(actionData.Name)
-        actionData.Value1 = familyActionData.GetValue1()
-        actionData.Value2 = familyActionData.GetValue2()
-        actionData.Value3 = familyActionData.GetValue3()
-        actionData.Value4 = familyActionData.GetValue4()
-        actionData.Value5 = familyActionData.GetValue5()
-        actionData.Value6 = familyActionData.GetValue6()
-        actionData.UseData = familyActionData.GetUserData()
-        actionData.UseDataLen = len(actionData.UseData)
-        clientPack.FamilyActionList.append(actionData)
-        
-    clientPack.Count = len(clientPack.FamilyActionList)
-    
-    if curPlayer:
-        NetPackCommon.SendFakePack(curPlayer, clientPack)
-        return
-    Broadcast_FamilyPack(familyID, clientPack)
-    return
-
-def SendFamilyAction(actionDataList, curPlayer=None):
-    ## 同步指定仙盟action
-    # @param actionDataList: 支持列表或指定actionData
-    # @param curPlayer: 为None时通知该仙盟所有成员
-    if not isinstance(actionDataList, list):
-        actionDataList = [actionDataList]
-    if not actionDataList:
-        return
-    familyActionData = actionDataList[0]
-    familyID = familyActionData.GetFamilyID()
-    actionType = familyActionData.GetActionType()
-    
-    clientPack = ChPyNetSendPack.tagMCFamilyActionInfo()
-    clientPack.FamilyID = familyID
-    clientPack.ActionType = actionType
-    clientPack.FamilyActionList = []
-    for familyActionData in actionDataList:
-        actionData = ChPyNetSendPack.tagMCFamilyAction()
-        actionData.Time = familyActionData.GetTime()
-        actionData.Name = familyActionData.GetName()
-        actionData.NameLen = len(actionData.Name)
-        actionData.Value1 = familyActionData.GetValue1()
-        actionData.Value2 = familyActionData.GetValue2()
-        actionData.Value3 = familyActionData.GetValue3()
-        actionData.Value4 = familyActionData.GetValue4()
-        actionData.Value5 = familyActionData.GetValue5()
-        actionData.Value6 = familyActionData.GetValue6()
-        actionData.UseData = familyActionData.GetUserData()
-        actionData.UseDataLen = len(actionData.UseData)
-        clientPack.FamilyActionList.append(actionData)
-    clientPack.Count = len(clientPack.FamilyActionList)
-    
-    if curPlayer:
-        NetPackCommon.SendFakePack(curPlayer, clientPack)
-        return
-    Broadcast_FamilyPack(familyID, clientPack)
-    return
-
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyEmblem.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyEmblem.py
index b94f27e..1d5337f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyEmblem.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyEmblem.py
@@ -46,29 +46,32 @@
     defaultEmblemIDList = []
     curTime = int(time.time())
     actionType = ShareDefine.Def_ActionType_FamilyEmblem
-    familyManager = DBDataMgr.GetFamilyMgr()
-    for i in xrange(familyManager.GetCount()):
-        family = familyManager.GetAt(i)
-        if not family:
-            continue
-        familyID = family.GetID()
-        familyAction = familyManager.GetFamilyActionMgr().GetFamilyAction(familyID, actionType)
-        for index in range(familyAction.Count())[::-1]: # 可能触发删除,倒序遍历
-            emblemActionObj = familyAction.At(index)
-            emblemID = GetActionEmblemID(emblemActionObj)
-            endTime = GetActionEmblemEndTime(emblemActionObj)
-            if not endTime or endTime > curTime:
-                #GameWorld.Log("检查仙盟徽章未过期! familyID=%s,emblemID=%s,endTime=%s" % (familyID, emblemID, endTime))
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    # 每分钟刷新下仙盟战力排序
+    for zoneID in familyMgr.GetZoneIDListThisServer():
+        zoneMgr = familyMgr.GetZoneFamilyMgr(zoneID)
+        for index in range(zoneMgr.GetCount()):
+            family = zoneMgr.GetAt(index)
+            if not family:
                 continue
-            familyAction.DelAction(index)
-            GameWorld.Log("删除过期仙盟徽章! familyID=%s,emblemID=%s,endTime=%s" % (familyID, emblemID, endTime))
-            if family.GetEmblemID() == emblemID:
-                if not defaultEmblemIDList:
-                    defaultEmblemIDList = GetDefaultFamilyEmblemIDList()
-                updEmblemID = random.choice(defaultEmblemIDList) if defaultEmblemIDList else 0
-                GameWorld.Log("仙盟佩戴徽章过期恢复随机默认徽章! familyID=%s,emblemID=%s,endTime=%s,updEmblemID=%s" % (familyID, emblemID, endTime, updEmblemID))
-                family.SetEmblemID(updEmblemID)
-                PlayerFamily.Broadcast_FamilyChange(familyID, PlayerFamily.FamilyChangeType_EChange)
+            familyID = family.GetID()
+            familyAction = familyMgr.GetFamilyActionMgr().GetFamilyAction(familyID, actionType)
+            for index in range(familyAction.Count())[::-1]: # 可能触发删除,倒序遍历
+                emblemActionObj = familyAction.At(index)
+                emblemID = GetActionEmblemID(emblemActionObj)
+                endTime = GetActionEmblemEndTime(emblemActionObj)
+                if not endTime or endTime > curTime:
+                    #GameWorld.Log("检查仙盟徽章未过期! familyID=%s,emblemID=%s,endTime=%s" % (familyID, emblemID, endTime))
+                    continue
+                familyAction.DelAction(index)
+                GameWorld.Log("删除过期仙盟徽章! familyID=%s,emblemID=%s,endTime=%s" % (familyID, emblemID, endTime))
+                if family.GetEmblemID() == emblemID:
+                    if not defaultEmblemIDList:
+                        defaultEmblemIDList = GetDefaultFamilyEmblemIDList()
+                    updEmblemID = random.choice(defaultEmblemIDList) if defaultEmblemIDList else 0
+                    GameWorld.Log("仙盟佩戴徽章过期恢复随机默认徽章! familyID=%s,emblemID=%s,endTime=%s,updEmblemID=%s" % (familyID, emblemID, endTime, updEmblemID))
+                    family.SetEmblemID(updEmblemID)
+                    PlayerFamily.Broadcast_FamilyInfo(familyID, isSyncMem=False)
     return
 
 def GetFamilyEmblemActionData(familyID, emblemID):
@@ -134,10 +137,10 @@
     PlayerFamily.SendFamilyAction(emblemActionObj)
     return emblemActionObj
 
-def OnChangeFamilyEmblem(curPlayer, emblemID, emblemWord=""):
+def OnChangeFamilyEmblem(crossPlayer, emblemID, emblemWord=""):
     ## 修改仙盟徽章
-    playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
     if familyID <= 0:
         return
     familyMgr = DBDataMgr.GetFamilyMgr()
@@ -179,6 +182,5 @@
     curFamily.SetEmblemID(emblemID)
     if emblemWord:
         curFamily.SetEmblemWord(emblemWord)
-    PlayerFamily.Sync_FamilyInfo(curPlayer)
-    PlayerFamily.Broadcast_FamilyChange(familyID, PlayerFamily.FamilyChangeType_EChange, excludeIDList=[playerID])
+    PlayerFamily.Broadcast_FamilyInfo(familyID, isSyncMem=False)
     return True
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyTaofa.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyTaofa.py
index 5b4cae8..5b6ec67 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyTaofa.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyTaofa.py
@@ -125,13 +125,13 @@
     SyncTaofaInfo(curPlayer)
     return
 
-def OnFamilyMemberLeave(family, leavePlayerID, leavePlayer=None):
+def OnFamilyMemberLeave(family, leavePlayerID):
     ## 公会成员删除,针对公会的处理
     familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(family.GetID(), ActionType)
     actionData = familyAction.GetActionDataByValue1(leavePlayerID, False)
     if not actionData:
         return
-    memInfo = PlayerViewCache.GetPlayerBaseViewInfo(leavePlayerID, leavePlayer)
+    memInfo = PlayerViewCache.GetPlayerBaseViewInfo(leavePlayerID)
     actionData.GetUserDict().update({"info":memInfo})
     PlayerFamily.SendFamilyAction([actionData])
     return
@@ -146,10 +146,10 @@
     SyncTaofaInfo(curPlayer)
     return
 
-def OnPlayerEnterFamily(curPlayer):
+def OnCrossPlayerEnterFamily(crossPlayer):
     ## 玩家进入新公会
-    familyID = curPlayer.GetFamilyID()
-    PlayerFamily.SendFamilyActionInfo(curPlayer, familyID, ActionType)
+    familyID = crossPlayer.GetFamilyID()
+    PlayerFamily.SendFamilyActionInfo(crossPlayer, familyID, ActionType)
     return
 
 #def RefreshFamilyBuZhenInfo(family):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyZhenbaoge.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyZhenbaoge.py
index b06784e..44cd284 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyZhenbaoge.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamilyZhenbaoge.py
@@ -20,9 +20,9 @@
 import IpyGameDataPY
 import NetPackCommon
 import ChPyNetSendPack
-import ItemControler
 import PlayerControl
 import PlayerFamily
+import CrossPlayer
 import GameWorld
 import DBDataMgr
 
@@ -205,9 +205,37 @@
 #};
 def OnZhenbaogeOP(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    opType = clientData.OpType
     playerID = curPlayer.GetPlayerID()
-    familyID = curPlayer.GetFamilyID()
+    opType = clientData.OpType
+    
+    reqDataEx = {}
+    # 砍价
+    if opType == 0:
+        leaveTimeEx = PlayerControl.GetLeaveFamilyTimeEx(curPlayer)
+        cutState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut)
+        if cutState and leaveTimeEx:
+            cutCDTimes = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 3) * 60
+            passTimes = int(time.time()) - leaveTimeEx
+            if passTimes < cutCDTimes:
+                GameWorld.DebugLog("今日已砍价变更仙盟砍价CD中! passTimes=%s < %s" % (passTimes, cutCDTimes), playerID)
+                return
+        reqDataEx["cutState"] = cutState
+    # 购买
+    elif opType == 1:
+        buyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
+        if buyState:
+            GameWorld.DebugLog("珍宝阁今日已购买!", playerID)
+            return
+        moneyType = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 1)
+        playerMoneyValue = PlayerControl.GetMoney(curPlayer, moneyType)
+        reqDataEx["playerMoneyValue"] = playerMoneyValue
+        
+    PlayerFamily.FamilyPyPackForwarding(curPlayer, clientData, tick, "PlayerFamilyZhenbaoge.__OnZhenbaogeOP", True, 20, reqDataEx=reqDataEx)
+    return
+def __OnZhenbaogeOP(crossPlayer, clientData, tick, fromServerID=0, reqDataEx=None):
+    opType = clientData.OpType
+    playerID = crossPlayer.GetPlayerID()
+    familyID = crossPlayer.GetFamilyID()
     if not familyID:
         GameWorld.DebugLog("没有仙盟无法操作珍宝阁!", playerID)
         return
@@ -219,35 +247,31 @@
         GameWorld.DebugLog("珍宝阁还没有刷新! familyID=%s" % familyID, playerID)
         return
     
+    if not reqDataEx:
+        return
+    
     # 砍价
     if opType == 0:
-        leaveTimeEx = PlayerControl.GetLeaveFamilyTimeEx(curPlayer)
-        cutState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut)
-        if cutState and leaveTimeEx:
-            cutCDTimes = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 3) * 60
-            passTimes = int(time.time()) - leaveTimeEx
-            if passTimes < cutCDTimes:
-                GameWorld.DebugLog("今日已砍价变更仙盟砍价CD中! passTimes=%s < %s" % (passTimes, cutCDTimes), playerID)
-                return
-            
+        cutState = reqDataEx["cutState"]
+        
         cutPrice = CalcCutPrice(curFamily, gActionData, playerID)
         if not cutPrice:
             return
         
-        AddCutPrice(familyID, playerID, curPlayer.GetName(), cutPrice, gActionData)
-        PlayerControl.NotifyCode(curPlayer, "ZhenbaogeCut", [cutPrice])
-        if not curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut):
-            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeCut, 1)
-            Sync_ZhenbaogeInfo(curPlayer)
+        AddCutPrice(familyID, playerID, crossPlayer.GetPlayerName(), cutPrice, gActionData)
+        CrossPlayer.NotifyCode(crossPlayer, "ZhenbaogeCut", [cutPrice])
+        if not cutState:
+            CrossPlayer.SetPlayerNomalDict(crossPlayer, {ChConfig.Def_Player_Dict_FamilyZhenbaogeCut:1}, True)
+            #Sync_ZhenbaogeInfo(crossPlayer)
             
     # 购买
     elif opType == 1:
-        buyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
-        if buyState:
-            GameWorld.DebugLog("珍宝阁今日已购买!", playerID)
-            return
+        #buyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
+        #if buyState:
+        #    GameWorld.DebugLog("珍宝阁今日已购买!", playerID)
+        #    return
         moneyType = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 1)
-        playerMoneyValue = PlayerControl.GetMoney(curPlayer, moneyType)
+        playerMoneyValue = reqDataEx["playerMoneyValue"]
         
         actionData = GetZhenbaogeActionData(familyID, playerID)
         if not actionData:
@@ -269,22 +293,25 @@
         SetFABuyState(actionData, 1)
         PlayerFamily.SendFamilyAction(actionData)
         
+        moneyDict = {moneyType:0} # 奖励货币
         if nowPrice > 0:
-            if not PlayerControl.PayMoney(curPlayer, moneyType, nowPrice, "Zhenbaoge"):
-                GameWorld.ErrLog("珍宝阁购买货币不足! nowPrice=%s" % nowPrice, playerID)
-                return
+            CrossPlayer.CostPlayerResources(crossPlayer, "Zhenbaoge", {moneyType:nowPrice})
         elif nowPrice < 0:
-            PlayerControl.GiveMoney(curPlayer, moneyType, -nowPrice, "Zhenbaoge")
+            moneyDict[moneyType] = -nowPrice
         else: # 0不处理
             pass
         
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy, 1)
-        Sync_ZhenbaogeInfo(curPlayer)
+        CrossPlayer.SetPlayerNomalDict(crossPlayer, {ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy:1}, True)
+        #Sync_ZhenbaogeInfo(curPlayer)
         
-        if giveItemList:
-            ItemControler.GivePlayerItemOrMail(curPlayer, giveItemList, event=["Zhenbaoge", False, {}], isNotifyAward=False)
-        ItemControler.NotifyGiveAwardInfo(curPlayer, giveItemList, "Zhenbaoge", moneyInfo={moneyType:0 if nowPrice > 0 else -nowPrice})
-                
+        CrossPlayer.GivePlayerResources(crossPlayer, giveItemList, moneyDict, eventName="Zhenbaoge")
+        
+    return True
+
+def __OnZhenbaogeOP_Ret(curPlayer, clientData, isOK):
+    if not isOK:
+        return
+    Sync_ZhenbaogeInfo(curPlayer)
     return
 
 def Sync_ZhenbaogeInfo(curPlayer):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLuckyCloudBuy.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLuckyCloudBuy.py
index 4ee1242..59fe2c9 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLuckyCloudBuy.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLuckyCloudBuy.py
@@ -91,7 +91,9 @@
         return
     
     unLimitHour, unLimitMinute = IpyGameDataPY.GetFuncEvalCfg("LuckyCloudBuyCost", 3)
-    crossServerDateTime = GameWorld.ChangeStrToDatetime(GameWorld.GetCrossServerTimeStr())
+    crossServerDateTime = None #GameWorld.ChangeStrToDatetime(GameWorld.GetCrossServerTimeStr())
+    if not crossServerDateTime:
+        return
     unLimitDateTime = GameWorld.ChangeStrToDatetime("%d-%d-%d %d:%d:00" \
                                 % (crossServerDateTime.year, crossServerDateTime.month, crossServerDateTime.day, unLimitHour, unLimitMinute))
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerMail.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerMail.py
index 6628ce3..b773156 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerMail.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerMail.py
@@ -15,6 +15,7 @@
 #"""Version = 2025-05-14 12:00"""
 #-------------------------------------------------------------------------------
 
+import CrossMsg
 import GameWorld
 import ItemCommon
 import PlayerControl
@@ -110,9 +111,19 @@
             Sync_PlayerMailState(curPlayer, notifyGUIDState)
     return
 
-def SendMailByKey(mailTypeKey, playerID, itemList, paramList=[], limitDays=7):
+def SendMailByKey(mailTypeKey, playerID, itemList, paramList=[], limitDays=7, toServerID=0):
     ## 发送个人邮件魔板
     # @param itemList: 元素支持字典{itemID:itemCount, ...} 或列表 [itemID, itemCount, 可选是否拍品, 物品UserData]
+    # @param toServerID: 向其他服玩家发送邮件时需指定玩家所在服务器
+    if toServerID > 0:
+        if not GameWorld.IsCrossServer():
+            GameWorld.ErrLog("非跨服服务器不能向其他服务器发送个人邮件! %s,playerID=%s" % (mailTypeKey, playerID))
+            return
+        dataMsg = {"mailTypeKey":mailTypeKey, "itemList":itemList, "paramList":paramList, "limitDays":limitDays}
+        mainServerID = GameWorld.GetMainServerID(toServerID)
+        CrossMsg.SendToClientServer(ShareDefine.C2S_SendPlayerMail, dataMsg, [mainServerID], playerID)
+        return
+    
     if not mailTypeKey:
         mailTypeKey = ShareDefine.DefaultLackSpaceMailType
     title = "<T>%s</T>" % mailTypeKey
@@ -120,6 +131,16 @@
     SendMail(playerID, title, text, itemList, limitDays)
     return
 
+def C2S_SendPlayerMail(dataMsg, playerID):
+    mailTypeKey = dataMsg["mailTypeKey"]
+    itemList = dataMsg["itemList"]
+    paramList = dataMsg["paramList"]
+    limitDays = dataMsg["limitDays"]
+    if not GameWorld.GetDBPlayerAccIDByID(playerID):
+        return
+    SendMailByKey(mailTypeKey, playerID, itemList, paramList, limitDays)
+    return
+
 def SendMail(playerID, title, text, itemList=None, limitDays=7, mailType=0):
     ## 发送个人邮件
     # @param itemList: 元素支持字典{itemID:itemCount, ...} 或列表 [itemID, itemCount, 可选是否拍品, 物品UserData]
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
index cd3b221..bd832cd 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerOnline.py
@@ -29,12 +29,12 @@
 import GameLogic_Dingjunge
 import PlayerMingge
 import PlayerBeauty
-import PlayerFamily
 import PlayerHorse
 import PlayerGubao
 import PlayerHero
 import PlayerHJG
 import GameWorld
+import ChPlayer
 import ChConfig
 import ChEquip
 
@@ -1198,7 +1198,4 @@
     else:
         GameWorld.DebugLog("主线阵容没有在战斗中,不需要处理", playerID)
         
-    PlayerFamily.RefreshFamilyMember(curPlayer) # 更新公会
-    # 更新排行榜
-    
     return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPrestigeSys.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPrestigeSys.py
index 92b36ea..1a0a47d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPrestigeSys.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPrestigeSys.py
@@ -25,7 +25,8 @@
 import ShareDefine
 import GameWorld
 import ChConfig
-import PlayerBillboard
+import ChPlayer
+import IPY_PlayerDefine
 import PlayerTongTianLing
 import PlayerTask
 import PlayerOnline
@@ -266,6 +267,6 @@
     PlayerTongTianLing.AddTongTianTaskValue(curPlayer, ChConfig.TTLTaskType_RealmUp, 1)
     PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_RealmLV)
     PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_OSARealmLV, nextRealmLv)
-    #更新排行榜
-    PlayerBillboard.UpdateRealmBillboard(curPlayer)
+    
+    ChPlayer.OnPlayerBaseInfoChange(curPlayer, IPY_PlayerDefine.CDBPlayerRefresh_OfficialRank) # 境界
     return True
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
index 55895ad..216ce3e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
@@ -18,6 +18,8 @@
 import ChConfig
 import GameWorld
 import PyMongoMain
+import CrossPlayer
+import PlayerFamily
 import PlayerControl
 import NetPackCommon
 import ChPyNetSendPack
@@ -54,18 +56,31 @@
     
     return
 
+def OnCrossPlayerLogout(crossPlayer):
+    playerID = crossPlayer.GetPlayerID()
+    viewCacheMgr = DBDataMgr.GetPlayerViewCacheMgr()
+    curCache = viewCacheMgr.GetPlayerViewCache(playerID)
+    if not curCache:
+        return
+    
+    if not IsSaveDBViewCache(curCache):
+        viewCacheMgr.DelPlayerViewCache(playerID)
+        return
+    
+    return
+
 def DelOutofTimeViewCacheData():
     ## 删除过期的查看缓存数据
     
-    playerManager = GameWorld.GetPlayerManager()
+    crossPlayerMgr = CrossPlayer.GetCrossPlayerMgr()
     viewCacheMgr = DBDataMgr.GetPlayerViewCacheMgr()
     for index in range(viewCacheMgr.GetCount())[::-1]: # 有删除需倒序遍历
         viewCache = viewCacheMgr.At(index)
         playerID = viewCache.GetPlayerID()
         if playerID < ShareDefine.RealPlayerIDStart:
             continue
-        curPlayer = playerManager.FindPlayerByID(playerID)
-        if curPlayer:
+        crossPlayer = crossPlayerMgr.FindCrossPlayer(playerID)
+        if crossPlayer:
             continue
         if IsSaveDBViewCache(viewCache):
             continue
@@ -82,14 +97,18 @@
     if playerID < ShareDefine.RealPlayerIDStart:
         #非真实玩家不入库
         return False
+        
+    isCrossServer = GameWorld.IsCrossServer()
     
     #某个功能中不能删除的
-    #...
     
+    if PlayerFamily.IsFamilyNeedViewPlayer(playerID):
+        return True
     
     #排行版上的默认保留
     billboardMgr = DBDataMgr.GetBillboardMgr()
-    for bType in ShareDefine.BillboardTypeAllList:
+    billboardTypeList = ShareDefine.CrossBillboardTypeList if isCrossServer else ShareDefine.BillboardTypeList
+    for bType in billboardTypeList:
         if bType in ShareDefine.FamilyBillboardList:
             continue
         groupList = billboardMgr.GetBillboardGroupList(bType)
@@ -139,8 +158,8 @@
         if updCache:
             curCache = updCache
             
-    # 真实玩家
-    elif playerID >= ShareDefine.RealPlayerIDStart:
+    # 真实玩家,仅游戏服更新,跨服直接使用游戏服同步的简要信息,需要详细信息的时候直接去玩家所在服查询
+    elif playerID >= ShareDefine.RealPlayerIDStart and GameWorld.IsMainServer():
         curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
         # 本服在线玩家,直接生成新数据
         if curPlayer:
@@ -155,8 +174,7 @@
         # 跨服玩家
         else:
             pass
-            # 跨服玩家,去子服拉取数据,理论上也一定有,但是如果需要拉数据,有一定延迟
-            # 逻辑待扩展
+            # 跨服玩家,游戏服不处理,仅跨服服务器支持获取基础信息,游戏服如果要查看跨服玩家,直接去玩家所在服查询
             
     # 机器人
     #elif ShareDefine.RobotIDStart <= playerID <= ShareDefine.RobotIDMax:
@@ -227,7 +245,7 @@
         return
     
     familyID = curPlayer.GetFamilyID()
-    family = DBDataMgr.GetFamilyMgr().FindFamily(familyID) if familyID else None
+    #familyBase = DBDataMgr.GetFamilyMgr().GetFamilyViewBase(familyID)
     
     tick = GameWorld.GetGameWorld().GetTick()
     curPlayer.SetDict(Key_UpdViewCacheTick, tick)
@@ -243,9 +261,10 @@
     curCache.SetEquipShowSwitch(curPlayer.GetEquipShowSwitch())
     curCache.SetTitleID(PlayerControl.GetTitleID(curPlayer))
     curCache.SetFamilyID(familyID)
-    curCache.SetFamilyName(family.GetName() if family else "")
-    curCache.SetFamilyEmblemID(family.GetEmblemID() if family else 0)
-    curCache.SetFamilyEmblemWord(family.GetEmblemWord() if family else "")
+    #公会信息由公会刷新更新,玩家常规更新不更新公会信息
+    #curCache.SetFamilyName(familyBase.GetName())
+    #curCache.SetFamilyEmblemID(familyBase.GetEmblemID())
+    #curCache.SetFamilyEmblemWord(familyBase.GetEmblemWord())
     curCache.SetFightPowerTotal(PlayerControl.GetFightPower(curPlayer))
     curCache.SetServerID(GameWorld.GetPlayerServerID(curPlayer))
     if isOffline:
@@ -340,14 +359,25 @@
     curCache.SetEquipShowSwitch(dbPlayer.EquipShowSwitch)
     curCache.SetTitleID(dbPlayer.ExAttr3)
     curCache.SetFamilyID(familyID)
-    family = DBDataMgr.GetFamilyMgr().FindFamily(familyID) if familyID else None
-    curCache.SetFamilyName(family.GetName() if family else "")
-    curCache.SetFamilyEmblemID(family.GetEmblemID() if family else 0)
-    curCache.SetFamilyEmblemWord(family.GetEmblemWord() if family else "")
+    #familyBase = DBDataMgr.GetFamilyMgr().GetFamilyViewBase(familyID)
+    #curCache.SetFamilyName(familyBase.GetName())
+    #curCache.SetFamilyEmblemID(familyBase.GetEmblemID())
+    #curCache.SetFamilyEmblemWord(familyBase.GetEmblemWord())
     curCache.SetFightPowerTotal(dbPlayer.FightPowerEx * ChConfig.Def_PerPointValue + dbPlayer.FightPower)
     curCache.SetServerID(GameWorld.GetAccIDServerID(dbPlayer.AccID))
     curCache.SetOffTime(GameWorld.ChangeTimeStrToNum(dbPlayer.LogoffTime) if dbPlayer.LogoffTime else 0)
     return curCache
+
+def UpdPlayerViewFamilyInfo(playerID, familyID, familyName, emblemID, emblemWord):
+    ## 玩家公会刷新时更新,兼容本服或跨服回传回来更新
+    curCache = DBDataMgr.GetPlayerViewCacheMgr().GetPlayerViewCache(playerID)
+    if not curCache:
+        return
+    curCache.SetFamilyID(familyID)
+    curCache.SetFamilyName(familyName)
+    curCache.SetFamilyEmblemID(emblemID)
+    curCache.SetFamilyEmblemWord(emblemWord)
+    return
 
 def GetPlayerBaseViewInfo(playerID, curPlayer=None):
     ## 获取玩家基础查看信息
@@ -382,6 +412,25 @@
                         }
     return baseInfo
 
+def UpdPlayerBaseViewInfo(playerID, baseInfo, isOffline):
+    ## 更新玩家基础查看信息,一般跨服服务器用,由游戏服同步过来
+    viewCacheMgr = DBDataMgr.GetPlayerViewCacheMgr()
+    curCache = viewCacheMgr.GetPlayerViewCache(playerID)
+    if not curCache:
+        curCache = viewCacheMgr.AddPlayerViewCache(playerID)
+    curCache.SetPlayerName(baseInfo.get("Name", curCache.GetPlayerName()))
+    curCache.SetLV(baseInfo.get("LV", curCache.GetLV()))
+    curCache.SetJob(baseInfo.get("Job", curCache.GetJob()))
+    curCache.SetRealmLV(baseInfo.get("RealmLV", curCache.GetRealmLV()))
+    curCache.SetFace(baseInfo.get("Face", curCache.GetFace()))
+    curCache.SetFacePic(baseInfo.get("FacePic", curCache.GetFacePic()))
+    curCache.SetTitleID(baseInfo.get("TitleID", curCache.GetTitleID()))
+    curCache.SetServerID(baseInfo.get("ServerID", curCache.GetServerID()))
+    curCache.SetFightPowerTotal(baseInfo.get("FightPower", curCache.GetFightPowerTotal()))
+    if isOffline:
+        curCache.SetOffTime(int(time.time()))
+    return curCache
+
 def GetRobotByViewCache(curCache):
     ## 根据缓存内容获取机器人数据
     if not curCache:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossRealmReg.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossRealmReg.py
deleted file mode 100644
index a3e467d..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossRealmReg.py
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#-------------------------------------------------------------------------------
-#
-##@package Player.RemoteQuery.GY_Query_CrossRealmReg
-#
-# @todo:跨服活动玩家注册
-# @author hxp
-# @date 2018-12-21
-# @version 1.0
-#
-# 详细描述: 跨服活动玩家注册
-#
-#-------------------------------------------------------------------------------
-#"""Version = 2018-12-21 18:00"""
-#-------------------------------------------------------------------------------
-
-import GameWorld
-import PlayerControl
-import CrossRealmPlayer
-import IPY_GameWorld
-import ChPyNetSendPack
-import CrossPlayerData
-import NetPackCommon
-import ChConfig
-import FBCommon
-import FBLogic
-
-
-#------------------------------------------------------------------------------ 
-## 跨服赛报名调用接口
-#  @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):
-    resultInfo = eval(funResult)
-    GameWorld.Log("GY_Query_CrossRealmReg DoResult %s" % funResult, curPlayer.GetPlayerID())
-    if not resultInfo:
-        return
-    registerMap, mapID, dataMapID, copyMapID, posX, posY, lineID = resultInfo
-    RegisterEnterCrossServer(curPlayer, registerMap, mapID, dataMapID, copyMapID, posX, posY, lineID)
-    return
-
-def RegisterEnterCrossServer(curPlayer, registerMap, mapID=0, dataMapID=0, copyMapID=0, posX=0, posY=0, lineID=0):
-    '''
-    @param registerMap: 一般是功能地图ID dataMapID
-    @param mapID: 真实场景地图ID
-    @param dataMapID: 真实场景地图ID对应场景数据地图ID
-    '''
-    playerID = curPlayer.GetPlayerID()
-    if GameWorld.IsCrossServer():
-        GameWorld.Log("    跨服服务器不允许上传报名数据!", playerID)
-        return
-    
-    playerRegisterMap = curPlayer.NomalDictGetProperty(ChConfig.Def_PlayerKey_CrossRegisterMap)
-    if playerRegisterMap in ChConfig.RegisterEnter_CrossServerMapIDList:
-        GameWorld.ErrLog("跨服已经在上传数据,不重复提交!playerRegisterMap=%s,registerMap=%s" % (playerRegisterMap, registerMap), curPlayer.GetPlayerID())
-        return
-    
-    #跨服前更新自己所属服务器组ID
-    PlayerControl.UpdPlayerServerGroupID(curPlayer)
-    serverGroupID = PlayerControl.GetPlayerServerGroupID(curPlayer)
-    zoneIpyData = CrossRealmPlayer.GetCrossZoneIpyDataByServerGroupID(registerMap, serverGroupID)
-    if not zoneIpyData:
-        return
-    zoneID = zoneIpyData.GetZoneID()
-    
-    if not mapID:
-        zoneIpyData = CrossRealmPlayer.GetServerCrossZoneMapIpyData(zoneID, registerMap)
-        if not zoneIpyData:
-            GameWorld.ErrLog("找不到该服务器对应跨服分区: registerMap=%s" % (registerMap))
-            return
-        mapID, dataMapID, copyMapID, posX, posY = zoneIpyData.GetMapID(), zoneIpyData.GetDataMapID(), zoneIpyData.GetCopyMapID(), zoneIpyData.GetPosX(), zoneIpyData.GetPosY()
-    
-    if not posX or not posY:
-        fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, lineID)
-        if fbLineIpyData:
-            tick = GameWorld.GetGameWorld().GetTick()
-            ipyEnterPosInfo = FBCommon.GetFBLineEnterPosInfo(mapID, lineID, fbLineIpyData)
-            retPos = FBLogic.OnGetFBEnterPos(curPlayer, mapID, lineID, ipyEnterPosInfo, tick)
-            if not retPos:
-                GameWorld.ErrLog("未找到进入副本坐标!mapID=%s,lineID=%s" % (mapID, lineID))
-                return
-            posX, posY = retPos
-            
-    if not mapID or not posX or not posY:
-        return
-    
-    if not FBLogic.OnRegEnterCrossFB(curPlayer, mapID, lineID):
-        GameWorld.ErrLog("OnRegEnterCrossFB 进入跨服副本注册失败,进入条件不足!无法注册! mapID=%s,lineID=%s" % (mapID, lineID), playerID)
-        return
-    
-    if registerMap in ChConfig.RegisterEnter_CrossServerMapIDList:
-        prepareEnterCrossServer = ChPyNetSendPack.tagMCPrepareEnterCrossServer()
-        prepareEnterCrossServer.DataMapID = registerMap
-        NetPackCommon.SendFakePack(curPlayer, prepareEnterCrossServer)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PlayerKey_CrossRegisterMap, registerMap) # 登记中记录,返回后清空
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ReqCrossFBMapID, registerMap) # 纯替换记录,不清空
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ReqCrossFBFuncLine, lineID)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ReqCrossFBZoneID, zoneID)
-    CrossPlayerData.OnPlayerCrossReg(curPlayer)
-    #curPlayer.SendMergeRegisterPlayer(mapID, dataMapID, copyMapID, posX, posY)
-    curPlayer.SendMergeRegisterPlayerAfterChange(CrossRealmPlayer.GetCrossPlayerName(curPlayer), mapID, dataMapID, copyMapID, posX, posY)
-    GameWorld.Log("    发送跨服玩家数据注册: registerMap=%s,lineID=%s,zoneID=%s,mapID=%s,dataMapID=%s,copyMapID=%s,posX=%s,posY=%s,GetVsRoomId=%s" 
-                  % (registerMap, lineID, zoneID, mapID, dataMapID, copyMapID, posX, posY, curPlayer.GetVsRoomId()), playerID)
-    return True
-
-## 跨服赛报名结果(上传数据)
-#  @param index 玩家索引
-#  @param tick 当前时间
-#  @return None
-def GameServer_MergeRegisterResult(index, tick):
-    registerResult = IPY_GameWorld.IPY_GMMergeRegisterPlayerResult()
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    registerMap = curPlayer.NomalDictGetProperty(ChConfig.Def_PlayerKey_CrossRegisterMap)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PlayerKey_CrossRegisterMap, 0)
-    curPlayer.SetDict(ChConfig.Def_PlayerKey_RequestEnterCrossServerTick, 0)
-    playerID = curPlayer.GetPlayerID()
-    result = registerResult.GetResult()
-    GameWorld.Log("GameServer_MergeRegisterResult registerMap=%s,result=%s" % (registerMap, result), playerID)
-    if not result:
-        errorMsg = registerResult.GetErrorMsg()
-        GameWorld.Log("CrossRealmReg result Error:%s" % errorMsg, playerID)
-        NetPackCommon.SendFakePack(curPlayer, ChPyNetSendPack.tagMCEnterCrossServerError())
-        return
-    
-    if registerMap in ChConfig.RegisterEnter_CrossServerMapIDList:
-        CrossRealmPlayer.DoEnterCrossRealm(curPlayer)
-        PlayerControl.SetCrossMapID(curPlayer, registerMap)
-        NetPackCommon.SendFakePack(curPlayer, ChPyNetSendPack.tagMCStartEnterCrossServer())
-        return
-    
-    #newAccount = registerResult.GetAccount()
-    #newName = registerResult.GetPwd()
-    
-    msgList = str([registerMap]) 
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, "CrossRealmReg", msgList, len(msgList))    
-    return
-    
-    
-    
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/UpdatePlayerName.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/UpdatePlayerName.py
index d9c6372..67c0d89 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/UpdatePlayerName.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/UpdatePlayerName.py
@@ -19,13 +19,13 @@
 import GameWorld
 import PlayerControl
 import ChPyNetSendPack
-import PlayerBillboard
+import IPY_PlayerDefine
 import NetPackCommon
 import IpyGameDataPY
-import PlayerFamily
 import PyMongoMain
 import PlayerTask
 import DirtyList
+import ChPlayer
 
 def OnPlayerLogin(curPlayer):
     if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Rename):
@@ -88,10 +88,7 @@
     clientPack.PlayerName = curPlayer.GetPlayerName()
     NetPackCommon.SendFakePack(curPlayer, clientPack)
     
-    #同步其他功能玩家名
-    PlayerFamily.RefreshFamilyMember(curPlayer)
-    PlayerBillboard.UpdatePlayerBillboardName(curPlayer)
-    #社交名待更新
+    ChPlayer.OnPlayerBaseInfoChange(curPlayer, IPY_PlayerDefine.CDBPlayerRefresh_PlayerName) # 玩家名
     
     PlayerTask.UpdTaskValue(curPlayer, ChConfig.TaskType_Rename)
     return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
index e80895e..e6513b7 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -18,6 +18,8 @@
 g_loadDataOK = False # 是否成功加载数据,备档、db数据
 g_lastRTBTime = 0 # 上一次备档时间戳
 g_initGameTime = 0 # 开始初始化服务器时间戳
+g_initGameWorldOK = False # GameWorld初始化成功
+g_initPyItem = False # 是否加载过物品表所需要的Py数据, 每张地图只在启动时执行一次
 g_serverInitOK = False # 服务器是否启动成功
 g_highProcessTime = 0 # 每秒触发一次,上次Time
 g_minuteProcess = -1 # 每分钟触发一次,上次处理的分钟
@@ -30,11 +32,14 @@
 
 g_pyGameDataManager = None
 
+g_ssServerMgr = None
+
 g_dbPlayerIDMap = {} # 本服DBPlayer玩家表ID映射关系 {playerID:accID, ...}
 g_onlineAccIDList = [] # 在线玩家账号列表 [accID, ...]
 g_ctgOrderIDList = [] # 正在兑换商品中的充值订单ID [orderID, ...]
 
-g_onlineMgr = None
+g_onlineMgr = None # 本服在线玩家管理
+g_crossPlayerMgr = None # 跨服玩家管理
 
 g_turnFightMgr = None
 
@@ -53,7 +58,6 @@
 g_needRefreshMapServerState = True # 常规地图分线人数是否有变更需要通知
 g_ipyDataRecycleCheckTime = 0 # 地图IpyData数据回收检查time
 
-InitPyItem = False # 是否加载过物品表所需要的Py数据, 每张地图只在启动时执行一次
 DailyUseCountLimitItemIDList = [] # 每日有使用个数限制的物品ID列表
 EquipItemSkillIDList = [] # 装备技能ID列表
 AutoTransformCountItemIDList = [] # 自动转化为对应物品个数的物品ID列表
@@ -70,7 +74,6 @@
 g_teamPlayerDict = {} # 地图队伍对应玩家ID列表,含离线玩家 {teamID:[playerID, ...], ...}
 g_teamPlayerInfoDict = {} # 地图队伍对应玩家ID信息 {teamID:{playerID:{k:v, ...}, ...}
 
-g_disconnectPlayer = {} # 在本地图离线的玩家信息 {playerID:[tick, posX, posY], ...}
 g_lastExitFBType = {} # 最后一个离开副本信息 {fbIndex:[exitType, tick], ...} exitType: 1-掉线,2-主动退出
 
 g_sgzztopPlayerName = '' #上古战场积分王名字
@@ -109,7 +112,6 @@
 
 g_luckyCloudBuyInfo = {} # 幸运云购最新一期信息
 
-g_crossServerTimeInfo = [0, 0] # 跨服时间信息 [crossServerTime, curServerTime]
 g_crossZoneName = "" # 跨服分区名
 g_crossRegPlayerAttrDict = {} #跨服注册时登记的会影响战力的属性值 {playerID:[value, ...], ...}
 g_crossSyncTickDict = {} #需要同步跨服数据的玩家同步tick字典 {playerID:tick, ...}
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py
index cdfcca2..df14436 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/Collections/DataServerPlayerData.py
@@ -27284,6 +27284,11 @@
         ('FightPowerEx', ctypes.c_ulong),
         ('EmblemID', ctypes.c_ushort),
         ('EmblemWord', ctypes.c_char * 3),
+        ('Extra1', ctypes.c_ulong),
+        ('Extra2', ctypes.c_ulong),
+        ('Extra3', ctypes.c_ulong),
+        ('Extra4', ctypes.c_ulong),
+        ('Extra5', ctypes.c_ulong),
         ('ADOResult', ctypes.c_ulong),
     ]
 
@@ -27307,6 +27312,11 @@
         self.FightPowerEx = 0
         self.EmblemID = 0
         self.EmblemWord = ''
+        self.Extra1 = 0
+        self.Extra2 = 0
+        self.Extra3 = 0
+        self.Extra4 = 0
+        self.Extra5 = 0
 
     def readData(self, buf, pos = 0, length = 0):
         if not pos <= length:
@@ -27333,6 +27343,11 @@
         self.FightPowerEx, pos = CommFunc.ReadDWORD(buf, pos)
         self.EmblemID, pos = CommFunc.ReadWORD(buf, pos)
         self.EmblemWord, pos = CommFunc.ReadString(buf, pos, 3)
+        self.Extra1, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Extra2, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Extra3, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Extra4, pos = CommFunc.ReadDWORD(buf, pos)
+        self.Extra5, pos = CommFunc.ReadDWORD(buf, pos)
         return self.getLength()
 
     def getBuffer(self):
@@ -27352,6 +27367,11 @@
         buf = CommFunc.WriteDWORD(buf, self.FightPowerEx)
         buf = CommFunc.WriteWORD(buf, self.EmblemID)
         buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 3, self.EmblemWord)
+        buf = CommFunc.WriteDWORD(buf, self.Extra1)
+        buf = CommFunc.WriteDWORD(buf, self.Extra2)
+        buf = CommFunc.WriteDWORD(buf, self.Extra3)
+        buf = CommFunc.WriteDWORD(buf, self.Extra4)
+        buf = CommFunc.WriteDWORD(buf, self.Extra5)
         return buf
 
     def getLength(self):
@@ -27371,6 +27391,11 @@
         length += sizeof(ctypes.c_ulong)
         length += sizeof(ctypes.c_ushort)
         length += sizeof(ctypes.c_char) * 3
+        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)
         return length
 
     def getRecord(self):
@@ -27391,6 +27416,11 @@
         rec[u'FightPowerEx'] = self.FightPowerEx
         rec[u'EmblemID'] = self.EmblemID
         rec[u'EmblemWord'] = fix_incomingText(self.EmblemWord)
+        rec[u'Extra1'] = self.Extra1
+        rec[u'Extra2'] = self.Extra2
+        rec[u'Extra3'] = self.Extra3
+        rec[u'Extra4'] = self.Extra4
+        rec[u'Extra5'] = self.Extra5
         return rec
 
     def readRecord(self, rec):
@@ -27410,6 +27440,11 @@
         self.FightPowerEx = rec.get(u'FightPowerEx', 0)
         self.EmblemID = rec.get(u'EmblemID', 0)
         self.EmblemWord = fix_outgoingText(rec.get(u'EmblemWord', u''))
+        self.Extra1 = rec.get(u'Extra1', 0)
+        self.Extra2 = rec.get(u'Extra2', 0)
+        self.Extra3 = rec.get(u'Extra3', 0)
+        self.Extra4 = rec.get(u'Extra4', 0)
+        self.Extra5 = rec.get(u'Extra5', 0)
 
     def adoLoad(self, collection):
         '''使用KEY查找并读取'''
@@ -27576,6 +27611,11 @@
             FightPowerEx = %s,
             EmblemID = %s,
             EmblemWord = %s,
+            Extra1 = %s,
+            Extra2 = %s,
+            Extra3 = %s,
+            Extra4 = %s,
+            Extra5 = %s,
             ADOResult = %s,
             '''%(
                 self.ID,
@@ -27593,12 +27633,17 @@
                 self.FightPowerEx,
                 self.EmblemID,
                 self.EmblemWord,
+                self.Extra1,
+                self.Extra2,
+                self.Extra3,
+                self.Extra4,
+                self.Extra5,
                 self.ADOResult,
             )
         return output
 
     def dumpString(self):
-        output = '''%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s'''%(
+        output = '''%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s\t%1s'''%(
                 self.ID,
                 self.Name,
                 self.LeaderID,
@@ -27614,6 +27659,11 @@
                 self.FightPowerEx,
                 self.EmblemID,
                 self.EmblemWord,
+                self.Extra1,
+                self.Extra2,
+                self.Extra3,
+                self.Extra4,
+                self.Extra5,
             )
         return output
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py
index d4e8700..cfd3f55 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/LogicProcess/UserCtrlDB.py
@@ -56,8 +56,6 @@
 Def_Cmp_Equ = 0                   #等于
 Def_Cmp_Greater = 1               #大于
 
-IsMergeServer = DBConfig.IsMergeServer
-
 #跨服玩家上传数据信息列表索引
 (
 MergeRegPInfoIndex_LoginTime, # 登录时间 索引
@@ -347,10 +345,7 @@
         self.connectDB()
         return
             
-    def IsMergeServer(self):
-        global IsMergeServer
-        return IsMergeServer
-    
+    def IsMergeServer(self): return GameWorld.IsCrossServer()
     
     # 每X分钟清除已下线的玩家跨服数据, 离线超过3分钟玩家直接返回子服
     def PopOfflineMergePlayer(self):
@@ -484,7 +479,7 @@
         pos = 0
         requestType, pos = CommFunc.ReadBYTE(pack.getBuffer(), pos)
         
-        mylog.debug("begin process request type = %d"%requestType)
+        #mylog.debug("begin process request type = %d"%requestType)
         
         if requestType == CommonDefine.gstCrossServerToServerPack:
             oFuncGrade = self.GetFuncGrade('gstCrossServerToServerPack')
@@ -954,9 +949,9 @@
 
     def OnGMToolCommand(self, db, pack):
 
-        if CommonDefine.IsDebug():
-            import binascii
-            mylog.debug('buf = %s'%binascii.b2a_hex(pack.getBuffer()))
+        #if CommonDefine.IsDebug():
+        #    import binascii
+        #    mylog.debug('buf = %s'%binascii.b2a_hex(pack.getBuffer()))
         
         try:
             ProjSpecialProcess.OnGMToolCommand(pack)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/RecvPackToMapDB.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/RecvPackToMapDB.py
index 3c3b20f..190da97 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/RecvPackToMapDB.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyMongoDB/RecvPackToMapDB.py
@@ -26,6 +26,8 @@
         return False
 
     #GameWorld.Log("RecvPackToMapDB packlen %s"%len(packBuff))
+    if not PyGameData.g_usrCtrlDB:
+        return
     PyGameData.g_usrCtrlDB.requestLogicProcess(pack)
 
 
@@ -36,5 +38,7 @@
         pack.setBuffer(packBuff)    # 只设置数据
     else:
         pack.readData(packBuff)     # 设置封包头 和 数据
-            
-    PyGameData.g_usrCtrlDB.requestLogicProcess(pack)
\ No newline at end of file
+    if not PyGameData.g_usrCtrlDB:
+        return
+    PyGameData.g_usrCtrlDB.requestLogicProcess(pack)
+    
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ReadChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ReadChConfig.py
index c122de1..83033e1 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ReadChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ReadChConfig.py
@@ -41,13 +41,8 @@
 AllChConfig = {}
 GeneralProgramme = {}
 ServersRouteConfig = None
+ServersConfigDict = {}
 PyMongoDataServerConfig = None
-DBAllChConfig = {}
-
-# db路径下对应的配置文件路径 {key:path, ...}
-Def_DBCfgFilePath = {
-                     "DBPlatformNum":"\\Config\\DBPlatformNum.txt",
-                     }
 
 #---------------------------------------------------------------------
 ## 获取原样的Config此方法仅用于公式 !!!!
@@ -101,11 +96,27 @@
 
 def SetReloadConfig():
     ## 标记重读配置
+    global PyMongoDataServerConfig
+    global ServersRouteConfig
+    global ServersConfigDict
+    
     GameWorld.Log("=== 设置重读配置 ===")
     GameWorld.GetGameWorld().SetGameWorldDict(ShareDefine.Def_Notify_WorldKey_ReloadConfig, 1)
+    PyMongoDataServerConfig = None
+    ServersRouteConfig = None
+    ServersConfigDict = {}
     IpyGameDataPY.IPYData.IpyDataClear()
     import DataRecordPack
     DataRecordPack.DR_Reload("config")
+    OnReloadConfig()
+    return
+
+def OnReloadConfig():
+    ## 配置文件重读后需要额外处理的逻辑
+    GameWorld.Log("OnReloadConfig...")
+    if GameWorld.IsCrossCenter():
+        import DBFamily
+        DBFamily.OnReloadConfig()
     return
 
 ## 重读,清除配置
@@ -114,17 +125,11 @@
 def ClearAllConfig():
     global AllChConfig
     global GeneralProgramme
-    global PyMongoDataServerConfig
-    global ServersRouteConfig
-    global DBAllChConfig
     
     #重读所有的配置表
     AllChConfig = {}
     GeneralProgramme = {}
     FormulaControl.ClearCompileFormulaDist()
-    PyMongoDataServerConfig = None
-    ServersRouteConfig = None
-    DBAllChConfig = {}
     
     GameWorld.Log('MapServer_Reload_ChConfig')
     #关闭字典
@@ -244,6 +249,22 @@
     strParam = ServersRouteConfig.get(section, option, raw)
     return strParam
 
+def GetServerConfigDict():
+    global ServersConfigDict
+    if not ServersConfigDict:
+        filePath = ChConfig.GetServersRoutePath() + "\\Config\\ServersConfig.json"
+        if not os.path.isfile(filePath):
+            GameWorld.Log('无法找到文件 = %s'%(filePath))
+            raise Exception('无法找到文件 = %s'%(filePath))
+        
+        f = open(filePath, 'r')
+        strMsg = f.read()
+        f.close()
+        
+        ServersConfigDict = eval(strMsg)
+        
+    return ServersConfigDict
+
 ## PyMongoDataServer.ini配置读取
 #  @param section: 分段区块名
 #  @param option: 配置项名
@@ -272,56 +293,3 @@
     
     strParam = PyMongoDataServerConfig.get(section, option, raw)
     return strParam
-
-def GetDBConfig(key): return __DoLogic_GetDBConfig(key)
-def GetDBEvalChConfig(key): return __DoLogic_GetDBConfig(key, True)
-
-## 通过key查找策划表,如果还未加载,则进行加载
-#  @param key 表名
-#  @return None
-#  @remarks 函数详细说明.
-def __DoLogic_GetDBConfig(key, needEval=False):
-    global DBAllChConfig
-    
-    #是否重读所有的配置表
-    if GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ReloadConfig):
-        ClearAllConfig()
-    else:
-        #找到了,就返回
-        if DBAllChConfig.has_key(key):
-            return DBAllChConfig[key]
-        
-    if key not in Def_DBCfgFilePath:
-        GameWorld.Log('DB配置中未发现Key文件 = %s' % (key))
-        return
-    filePath = ChConfig.GetServerConfigPath() + Def_DBCfgFilePath[key]
-    
-    retData = __ReadConfigDataEx(key, filePath, needEval)
-    if not retData:
-        return
-    DBAllChConfig.update({key:retData})
-    return retData
-
-def __ReadConfigDataEx(fileName, filePath, needEval):
-    
-    if not os.path.isfile(filePath):
-        GameWorld.Log('未发现目标文件 = %s' % (filePath))
-        raise Exception ('未发现目标文件 = %s' % (filePath))
-    
-    file = open(filePath, 'r')
-    strMsg = file.read()
-    file.close()
-    
-    if needEval:
-        try:
-            result = eval(strMsg)
-        except BaseException, e:
-            GameWorld.Log('获取配置信息Key = %s 读取失败,无法解析原因:%s, 抛出,%s' % (fileName, e, strMsg))
-            raise Exception('获取配置信息Key = %s 读取失败' % fileName)
-        
-        return result
-    
-    else:
-        #编译后储存
-        return compile(strMsg, 'ReadChConfig', 'eval')
-
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index d504b88..650e9f8 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -33,6 +33,7 @@
 Def_MixServerDay = 'MixServerDay' #服务器已经合服多少天
 Def_IsMixServerInitOK = 'IsMixServerInitOK' #服务器合服首次启动OK
 Def_LastMixServerDay = 'LastMixServerDay' #上次合服时的开服天数
+Def_CrossCenterEvent = 'CrossCenterEvent' # 跨服中心事件值
 #首次开服时间,注意不要用该日期做开服天相关的功能逻辑,如果要用开服天,请用 Def_ServerDay
 ''' 原因: 
 因为目前开服天的逻辑大部分是用 Def_ServerDay,当出现服务器宕机超过24小时时,就会导致 Def_ServerDay 与 Def_InitOpenServerTime 不对应
@@ -42,9 +43,9 @@
 Def_InitOpenServerTime = 'InitOpenServerTime'
 Def_SetOpenServerTime = 'SetOpenServerTime' # GM工具预定的开服时间
 
-
+Def_FamilyCrossState = 'FamilyCrossState' # 本服公会跨服状态, 0-未跨服;1-已跨服
+Def_FamilyTransDataTime = 'FamilyTransDataTime' # 本服公会首次跨服互通数据开始传输时间戳,不为0代表传输数据中
 Def_OSAAwardState = 'OSAAwardState' #开服冲榜活动结算状态
-# ------------------------- WorldKey ------------------------- 
 
 #---奇迹, 职业枚举定义---
 (
@@ -988,7 +989,7 @@
 
 #家族行为类型 在GameServer.ChConfig.ActionTypeSaveCnt 中配置最高存储条数
 Def_ActionTypeList = (
-                      Def_ActionType_FamilyData, #仙盟额外记录信息0
+                      Def_ActionType_0,
                       Def_ActionType_1,
                       Def_ActionType_2,
                       Def_ActionType_FamilyAdd,    #申请进入家族3
@@ -1062,11 +1063,19 @@
 CampType_Evil,       #邪恶(与 Def_ID2Win 一致)
 ] = range(3)
 
-# json里的配表 服务器类型(0主服,1子服,2跨服,3战斗服)]
+# serverJosn里配置索引 ServersConfig.json目前配置规则{SeverID:[GroupName,MapID,服务器类型(0主服,1子服,2跨服)], ...}
+(
+serverCfgIndex_GroupName, # 所属 GroupName
+serverCfgIndex_MapID, # 服务器对应的地图ID
+serverCfgIndex_ServerType, # 服务器类型
+) = range(3)
+
+# json里的配表 服务器类型(0主服,1子服,2跨服,3战斗服,4跨服中心)]
 serverType_Main = 0 # 0主服
 serverType_Child = 1 # 1子服
 serverType_Cross = 2 # 2跨服
 serverType_Battle = 3 # 3战斗服
+serverType_CrossCenter = 4 # 4跨服中心,只允许最多1台
 
 # dirType //0全广播,1通知主服务器排除合服子服,2通知服务器包含合服子服, 3通知跨服服务器 ,4通知战斗服务器
 dirType_All = 0 # 0全广播
@@ -1074,10 +1083,47 @@
 dirType_Child = 2 # 2通知服务器包含合服子服
 dirType_Cross = 3 # 3通知跨服服务器
 dirType_Battle = 4 # 4通知战斗服务器
+dirType_MainAndCross = 5 # 通知主服务器+跨服
+
+# 服务器间连接状态
+(
+ssConn_Unknown, # 未知 0
+ssConn_Normal, # 正常连接 1
+ssConn_Disconnected, # 断开 2
+) = range(3)
 
 # 服务器间的信息定义
-SSMsg_BattleRequest = "SS_BattleRequest"
-SSMsg_BattleResult = "SS_BattleResult"
+# 服务器类型简写: C - 跨服/跨服中心; CC - 跨服中心;S - 游戏服; B - 战斗服
+
+# 跨服中心 -> 其他跨服
+CC2C_FamilyCrossCfg = "CC2C_FamilyCrossCfg"             # 公会分区配置
+
+# 跨服  -> 游戏服
+#C2S_PlayerLoginOK = "C2S_PlayerLoginOK"                 # 跨服玩家处理登录成功
+C2S_SendFakePack = "C2S_SendFakePack"                   # 给玩家发送封包
+C2S_FamilyCrossInfo = "C2S_FamilyCrossInfo"             # 跨服同步给游戏服的公会信息
+C2S_FamilyDataRet = "C2S_FamilyDataRet"                 # 公会首次跨服互通时同步数据结果回复
+C2S_FamilyMapPlayer = "C2S_FamilyMapPlayer"             # 给公会玩家处理地图服务器逻辑
+C2S_FamilyPyPackRet = "C2S_FamilyPyPackRet"             # 公会功能玩家请求包处理结束回包,一般用于重置请求cd等
+C2S_NotifyCode = "C2S_NotifyCode"                       # 给玩家发送信息提示
+C2S_CostPlayerResources = "C2S_CostPlayerResources"     # 扣除玩家资源,货币、物品等
+C2S_GivePlayerResources = "C2S_GivePlayerResources"     # 奖励玩家资源,货币、物品等
+C2S_SetPlayerNomalDict = "C2S_SetPlayerNomalDict"       # 设置玩家字典值
+C2S_SendPlayerMail = "C2S_SendPlayerMail"               # 发送玩家个人邮件
+
+# 游戏服  -> 跨服
+S2C_OnlineState = "S2C_OnlineState"                     # 玩家在线状态同步
+S2C_PlayerBaseInfo = "S2C_PlayerBaseInfo"               # 玩家基础信息同步
+S2C_FamilyData = "S2C_FamilyData"                       # 公会首次跨服互通时同步数据
+S2C_FamilyPyPack = "S2C_FamilyPyPack"                   # 公会功能玩家请求包
+S2C_GMCMD = "S2C_GMCMD"                                 # GM命令
+
+# 其他
+S2B_BattleRequest = "S2B_BattleRequest"                 # 战斗请求
+B2S_BattleResult = "B2S_BattleResult"                   # 战斗结果
+
+# Debug日志不输出通讯数据明细的类型,debug模式下看,一些纯数据类的可不输出通讯数据明细
+NoLogDataSSMsgTypes = [S2B_BattleRequest, B2S_BattleResult, S2C_FamilyData, C2S_SendFakePack]
 
 # 跨服服务器发送子服信息定义
 CrossServerMsg_CrossServerState = "CrossServerState"    # 跨服服务器状态变更

--
Gitblit v1.8.0