From 415c7723223a95ab35f3f135bdf12a982ec879e6 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 11 四月 2025 16:30:22 +0800
Subject: [PATCH] 10367 【越南】【英语】【BT】【砍树】仙盟攻城战-服务端(跨服仙盟支持;后台查询区服仙盟支持;活动时间流程支持;攻城战主活动功能完整流程:公示、分组、战备、战斗、榜单、竞猜、领奖等;)

---
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py |  406 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 374 insertions(+), 32 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
index d9af3a4..ff60117 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
@@ -44,6 +44,8 @@
 import PlayerFamilySWRH
 import PlayerViewCache
 import GameWorldBoss
+import CrossRealmMsg
+import CrossFamilyGCZ
 import AuctionHouse
 import PlayerAssist
 import PlayerTalk
@@ -61,6 +63,62 @@
 ImpeachLastTime  # 弹劾需要持续的时间
 ) = range(3)
 
+class FamilyMgr():
+    
+    def __init__(self):
+        self.sortFamilyIDList = [] #本服仙盟排序顺序 [familyID, ...]
+        self.fightPowerChangeFamilyIDList = [] # 仙盟成员战力有变更的仙盟ID [familyID, ...]
+        
+        #这里仅针对增改信息,删除的另外处理,因为删除的需要确保成功删除,所以需要入库未成功删除的记录
+        #而变更同步的会定时同步,每次重连服务器也会强制同步,所以不需要有成功回复
+        self.syncCrossFamilyDict = {} # 需要同步跨服的仙盟 {familyID:[需要同步的成员ID, ...], ...}
+        return
+    
+    def OnDeleteFamilyID(self, familyID):
+        if familyID in self.sortFamilyIDList:
+            self.sortFamilyIDList.remove(familyID) # 直接从排序列表中移除, 不需要重新排序
+        self.SetSyncCrossFamilyDel(familyID) # 解散仙盟
+        return
+    
+    def GetFamilyIDRank(self, familyID):
+        if familyID not in self.sortFamilyIDList:
+            return len(self.sortFamilyIDList) + 1
+        return self.sortFamilyIDList.index(familyID) + 1
+    
+    def AddFamilyIDToFightPowerChangeList(self, familyID, playerID=0):
+        if familyID not in self.fightPowerChangeFamilyIDList:
+            self.fightPowerChangeFamilyIDList.append(familyID)
+            GameWorld.DebugLog("仙盟战力变更待处理列表: fightPowerChangeFamilyIDList=%s" % self.fightPowerChangeFamilyIDList)
+        self.SetSyncCrossFamilyUpd(familyID, playerID) # 仙盟战力变更、成员战力变更
+        return
+    
+    def SetSyncCrossFamilyUpd(self, familyID, playerID=0, syncNow=False):
+        if familyID not in self.syncCrossFamilyDict:
+            self.syncCrossFamilyDict[familyID] = []
+        if playerID:
+            needSyncMemIDList = self.syncCrossFamilyDict[familyID]
+            if playerID not in needSyncMemIDList:
+                needSyncMemIDList.append(playerID)
+        # 变更数据是否立即同步跨服,否则等待定时同步即可
+        if syncNow:
+            Sync_ClientFamilyUpdToCrossServer()
+        return
+    
+    def SetSyncCrossFamilyDel(self, familyID, playerID=0):
+        ## 设置同步跨服服务器仙盟删除
+        # @param playerID: 如果有值代表仅成员删除
+        valueSetList = [playerID]
+        gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+        gameRecMgr.AddGameRecData(ShareDefine.Def_GameRecType_FamilyDelSyncCross, familyID, valueSetList)
+        Sync_ClientFamilyDelToCrossServer() # 删除的立马同步
+        return
+    
+def GetFamilyMgr():
+    mgr = PyGameData.g_familyMgr
+    if not mgr:
+        mgr = FamilyMgr()
+        PyGameData.g_familyMgr = mgr
+    return mgr
 
 ## ------------------ 仙盟 ----------------------
 ## 仙盟联赛排名
@@ -71,6 +129,7 @@
 def SetFamilyTotalFightPower(curFamily, totalFightPower):
     curFamily.SetExtra4(totalFightPower / ChConfig.Def_PerPointValue)
     curFamily.SetExtra5(totalFightPower % ChConfig.Def_PerPointValue)
+    GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID()) # 仙盟战力变更
     return
 def GetFamilyTotalFightPowerByID(familyID):
     family = GameWorld.GetFamilyManager().FindFamily(familyID)
@@ -79,7 +138,10 @@
     return GetFamilyTotalFightPower(family)
 # 徽章ID
 def GetFamilyEmblemID(curFamily): return curFamily.GetExtra6()
-def SetFamilyEmblemID(curFamily, emblemID): return curFamily.SetExtra6(emblemID)
+def SetFamilyEmblemID(curFamily, emblemID):
+    curFamily.SetExtra6(emblemID)
+    GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID()) # 徽章变更
+    return
 
 # 公告修改次数
 def GetFamilyBroadcastCnt(curFamily): return curFamily.GetExtra3()
@@ -108,11 +170,17 @@
 
 def OnGameServerInitOK():
     ## 服务器启动成功处理
-    DoFamilySort()
+    if GameWorld.IsCrossServer():
+        pass
+    else:
+        DoFamilySort()
     return
 
 def OnMixServerInit():
     ## 合服后首次启动成功处理
+    
+    if GameWorld.IsCrossServer():
+        return
     
     # 仙盟联赛重置
     GameWorldFamilyWar.DoFamilyWarReset()
@@ -440,7 +508,7 @@
     #加入家族
     familyMember = curFamily.AddMember(jionPlayer)
     #刷新基本信息
-    RefreshFamilyMemberBaseMsg(familyMember, jionPlayer)
+    RefreshFamilyMemberBaseMsg(curFamily, familyMember, jionPlayer)
     
     #族长设置
     if jionFamilySetLv == IPY_GameServer.fmlLeader:
@@ -486,7 +554,7 @@
     #仙盟拍品
     AuctionHouse.Sync_FamilyAuctionItemInfo(jionPlayer, curFamily.GetID())
     SetMemberFightPower(familyMember, PlayerControl.GetFightPower(jionPlayer))
-    AddFamilyIDToFightPowerChangeList(curFamily.GetID())
+    GetFamilyMgr().AddFamilyIDToFightPowerChangeList(curFamily.GetID(), jionPlayer.GetPlayerID())
     
     #通知仙盟盛宴题目
     PlayerFamilyParty.NotifyFamilyPartyQuestion(jionPlayer)
@@ -678,7 +746,7 @@
 # @remarks 通知客户端服务器家族信息
 def Sync_AllFamilyInfo(curPlayer, viewPage, pageCnt=ChConfig.Def_ViewAllFamilyPageCount, sortRule=IPY_GameServer.fsrHornor):
     #familyCount = GameWorld.GetFamilyManager().GetCount()
-    familyCount = len(PyGameData.g_sortFamilyIDList)
+    familyCount = len(GetFamilyMgr().sortFamilyIDList)
     allPageCnt = GameWorld.GetIntUpper(familyCount, pageCnt)
 
     if allPageCnt != 0 and (viewPage < 0 or viewPage >= allPageCnt):
@@ -716,7 +784,8 @@
     return
 
 def Sync_PyAllFamilyInfo(curPlayer, allPageCnt, viewPage, startIndex, endIndex):
-    familyCount = len(PyGameData.g_sortFamilyIDList)
+    sortFamilyIDList = GetFamilyMgr().sortFamilyIDList
+    familyCount = len(sortFamilyIDList)
     if startIndex < 0 or endIndex >= familyCount:
         return
     
@@ -727,7 +796,7 @@
     familyViewPack.CurPage = viewPage
     familyViewPack.Family = []
     for i in xrange(startIndex, endIndex + 1):
-        familyID = PyGameData.g_sortFamilyIDList[i]
+        familyID = sortFamilyIDList[i]
         family = familyMgr.FindFamily(familyID)
         if not family:
             continue
@@ -785,7 +854,7 @@
     familyViewPack.TotalCount = 1
     #familyViewPack.CurPage = viewPage
     familyViewPack.Family = []
-    for i, familyID in enumerate(PyGameData.g_sortFamilyIDList):
+    for i, familyID in enumerate(GetFamilyMgr().sortFamilyIDList):
         family = familyMgr.FindFamily(familyID)
         if not family:
             continue
@@ -822,7 +891,7 @@
     familyViewPack.TotalCount = 1
     #familyViewPack.CurPage = viewPage
     familyViewPack.Family = []
-    for i, familyID in enumerate(PyGameData.g_sortFamilyIDList):
+    for i, familyID in enumerate(GetFamilyMgr().sortFamilyIDList):
         family = familyMgr.FindFamily(familyID)
         if not family:
             continue
@@ -908,6 +977,7 @@
             continue
         curPlayer.ChatMi(notifyPlayer, 1, pack.GetMsg(), 0, PlayerTalk.GetTalkExtraValue(curPlayer))
         PyDataManager.GetContactsManager().AddContactsBoth(curPlayer.GetID(), notifyPlayer.GetID())
+    GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID()) # 公告变更
     return
 
 ## 检测目标玩家是否可以加入家族
@@ -1696,11 +1766,12 @@
     PlayerFamilyAction.DelFamilyOfficerModelEquip(curFamily.GetID(), leavePlayerID)
     # 玩家战盟名变更处理
     __OnFamilyNameChange(leavePlayerID, '')
-    AddFamilyIDToFightPowerChangeList(curFamily.GetID())
+    GetFamilyMgr().AddFamilyIDToFightPowerChangeList(curFamily.GetID(), leavePlayerID)
     PlayerViewCache.OnPlayerFamilyChange(leavePlayerID, 0, "")
     PlayerAssist.OnPlayerLeaveFamily(curFamily.GetID(), leavePlayerID, tagPlayer)
     if leavePlayerID in PyGameData.g_autoViceleaderDict.get(curFamily.GetID(),[]):
         PyGameData.g_autoViceleaderDict[curFamily.GetID()].remove(leavePlayerID)
+    GetFamilyMgr().SetSyncCrossFamilyDel(curFamily.GetID(), leavePlayerID) # 成员离开、踢出
     return
 
 #//////////////////////////////////////////////////////////////
@@ -1845,7 +1916,7 @@
     
     SetMemberFightPower(curMember, fightPower)
     GameWorld.DebugLog("仙盟成员战力变更 familyID=%s,fightPower=%s" % (familyID, fightPower), playerID)
-    AddFamilyIDToFightPowerChangeList(familyID)
+    GetFamilyMgr().AddFamilyIDToFightPowerChangeList(familyID, playerID)
     return
 
 ## A4 07 升级家族#tagCGFamilyLVUp
@@ -1954,6 +2025,7 @@
     #世界服务器家族重新排序
     #GameWorld.GetFamilyManager().SortByLV()
     DoFamilySort() # 升级直接强排一次
+    GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID(), syncNow=True) # 仙盟等级变更
     return True
 
 #---------------------------------------------------------------------
@@ -2002,6 +2074,8 @@
 #  @remarks 函数详细说明.
 def OnPlayerChangeMap(curPlayer, tick):
     #同步给玩家, 最新的家族信息(家族等级刷新)
+    if GameWorld.IsCrossServer():
+        return
     curPlayer.MapServer_FamilyRefresh()
     return
 
@@ -2151,7 +2225,7 @@
 #  @param curPlayer 真实玩家
 #  @return None
 #  @remarks 刷新家族成员基本信息
-def RefreshFamilyMemberBaseMsg(curMember, curPlayer):
+def RefreshFamilyMemberBaseMsg(curFamily, curMember, curPlayer):
     curMember.SetName(curPlayer.GetName())
     curMember.SetLV(curPlayer.GetLV())
     curMember.SetReincarnationLv(curPlayer.GetReincarnationLv())
@@ -2160,6 +2234,7 @@
     curMember.SetOfficialRank(curPlayer.GetOfficialRank())
     curMember.SetFace(curPlayer.GetFace())
     curMember.SetFacePic(curPlayer.GetFacePic())
+    GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID(), curPlayer.GetPlayerID()) # 成员基础信息刷新,含加入仙盟刷新
     return
 #---------------------------------------------------------------------
 ## 玩家刷新
@@ -2174,9 +2249,9 @@
     if curMember == None:
         return
     
-    RefreshFamilyMemberBaseMsg(curMember, curPlayer)
-    #家族长境界
     family = curPlayer.GetFamily()
+    RefreshFamilyMemberBaseMsg(family, curMember, curPlayer)
+    #家族长境界
     if family.GetLeaderID() == curPlayer.GetID():
         family.SetLeaderOfficialRank(curPlayer.GetOfficialRank())
     return
@@ -2292,8 +2367,7 @@
     
     #重新排序家族
     #GameWorld.GetFamilyManager().SortByLV()
-    if familyID in PyGameData.g_sortFamilyIDList:
-        PyGameData.g_sortFamilyIDList.remove(familyID) # 直接从排序列表中移除, 不需要重新排序
+    GetFamilyMgr().OnDeleteFamilyID(familyID)
         
     #家族科技删除, 改为地图直接处理, 暂屏蔽
     #PlayerFamilyTech.DelFamilyTechData(familyID)
@@ -2322,6 +2396,7 @@
     #设置族长权限
     ChangeFamilyMemberLv(familyMember, IPY_GameServer.fmlLeader)
     GameWorldFamilyWar.OnChangeFamilyLeader(curFamily.GetID(), familyMember.GetPlayerID())
+    GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID(), syncNow=True) # 盟主变更
     return
 #---------------------------------------------------------------------
 ##更改家族成员等级.
@@ -2353,6 +2428,8 @@
     # 变为普通成员,删除模型装备信息
     elif changeFamilyLV == IPY_GameServer.fmlMember:
         PlayerFamilyAction.DelFamilyOfficerModelEquip(familyMember.GetFamilyID(), familyMember.GetPlayerID())
+        
+    GetFamilyMgr().SetSyncCrossFamilyUpd(familyMember.GetFamilyID(), familyMember.GetPlayerID(), syncNow=True) # 成员职位变更
     return
 
 #---------------------------------------------------------------------
@@ -2531,6 +2608,7 @@
     #通知家族刷新
     curFamily.Broadcast_FamilyChange()
     
+    GetFamilyMgr().SetSyncCrossFamilyUpd(curFamilyID, syncNow=True) # 仙盟改名
     playerManager = GameWorld.GetPlayerManager()
     
     #仙盟联赛
@@ -2711,6 +2789,8 @@
 # @return 返回值无意义
 # @remarks 家族过天
 def FamilyOnDay(tick):
+    if GameWorld.IsCrossServer():
+        return
     #---设置所有玩家可以再次加入家族---
     GameWorld.GetPlayerManager().ClearForbiddenEnterFamily()
     #---扣除地图上所有家族的维护费---
@@ -2769,6 +2849,8 @@
     return
 
 def FamilyOnDayEx(tick):
+    if GameWorld.IsCrossServer():
+        return
     familyManager = GameWorld.GetFamilyManager()
     for i in range(0, familyManager.GetCount()):
         family = familyManager.GetAt(i)
@@ -2784,7 +2866,8 @@
 # @return 返回值无意义
 # @remarks 家族过周
 def FamilyOnWeek(tick):
-    
+    if GameWorld.IsCrossServer():
+        return
     #---计算上周家族活跃度---
     familyManager = GameWorld.GetFamilyManager()
     for i in range(0, familyManager.GetCount()):
@@ -2816,6 +2899,8 @@
     return
 
 def FamilyOnHour():
+    if GameWorld.IsCrossServer():
+        return
     familyManager = GameWorld.GetFamilyManager()
     for i in xrange(familyManager.GetCount()):
         family = familyManager.GetAt(i)
@@ -2885,12 +2970,31 @@
             return cmp(GetMemberJoinTime(member1), GetMemberJoinTime(member2))
     return ret
 
+def SortCrossFamily(serverIDList, top=0):
+    ''' 跨服仙盟排序, 排序规则: 总战力  > 等级 > ID
+    @param serverIDList: 仙盟所属区服ID范围列表
+    @param top: 返回排序靠前x个仙盟,0则全部返回
+    '''
+    familyList = []
+    familyManager = GameWorld.GetFamilyManager()
+    for i in xrange(familyManager.GetCount()):
+        family = familyManager.GetAt(i)
+        serverID = family.GetServerID()
+        if not GameWorld.CheckServerIDInList(serverID, serverIDList):
+            continue
+        familyList.append(family)
+    familyList.sort(key=lambda f: (GetFamilyTotalFightPower(f), f.GetLV(), f.GetID()), reverse=True)
+    totalCnt = len(familyList)
+    return familyList[:top] if top else familyList, totalCnt
+    
 #---------------------------------------------------------------------
 ##通知地图服务器, 玩家家族属性刷新
 # @param curFamily 家族实例
 # @return 返回值无意义
 # @remarks IPY_MFamilyRefresh
 def SendPack_MapServer_PlayerFamilyRefresh(curFamily):
+    if GameWorld.IsCrossServer():
+        return
 #===============================================================================
 #    当家族以下权限变更时要通知地图服务器 IPY_MFamilyRefresh
 #    GetFamilyLV
@@ -3534,21 +3638,30 @@
             break
     return leaderLV
 
-def AddFamilyIDToFightPowerChangeList(familyID):
-    if familyID not in PyGameData.g_fightPowerChangeFamilyIDList:
-        PyGameData.g_fightPowerChangeFamilyIDList.append(familyID)
-        GameWorld.DebugLog("仙盟战力变更待处理列表: fightPowerChangeFamilyIDList=%s" % PyGameData.g_fightPowerChangeFamilyIDList)
+def OnMinuteProcess(curMinute):
+    if GameWorld.IsCrossServer():
+        return
+    
+    #每5分钟触发一次仙盟更新
+    if curMinute % 5 != 0:
+        return
+    
+    UpdFamilyTotalFightPower()
+    PlayerFamilyRedPacket.CheckDelRedpacketData()
+    PlayerFamilyEmblem.CheckExpireEmblem()
+    Sync_ClientFamilyUpdToCrossServer()
     return
 
 def UpdFamilyTotalFightPower():
     ## 更新仙盟总战力
-    if not PyGameData.g_fightPowerChangeFamilyIDList:
+    mgr = GetFamilyMgr()
+    if not mgr.fightPowerChangeFamilyIDList:
         #GameWorld.DebugLog("不需要更新仙盟总战力!")
         return
         
-    GameWorld.DebugLog("更新仙盟总战力 fightPowerChangeFamilyIDList=%s" % PyGameData.g_fightPowerChangeFamilyIDList)
+    GameWorld.DebugLog("更新仙盟总战力 fightPowerChangeFamilyIDList=%s" % mgr.fightPowerChangeFamilyIDList)
     familyManager = GameWorld.GetFamilyManager()
-    for familyID in PyGameData.g_fightPowerChangeFamilyIDList:    
+    for familyID in mgr.fightPowerChangeFamilyIDList:    
         family = familyManager.FindFamily(familyID)
         if not family:
             continue
@@ -3560,19 +3673,17 @@
         SetFamilyTotalFightPower(family, totalFightPower)
         GameWorld.DebugLog("    familyID=%s,totalFightPower=%s" % (familyID, totalFightPower))
         
-    PyGameData.g_fightPowerChangeFamilyIDList = []
+    mgr.fightPowerChangeFamilyIDList = []
     
     DoFamilySort(False) # 此处必须为False
     return True
 
-def GetSortFamilyIDList(): return PyGameData.g_sortFamilyIDList
+def GetSortFamilyIDList(): return GetFamilyMgr().sortFamilyIDList
 def GetFamilyIDRank(familyID):
     '''获取仙盟的排名, 注意与联赛排名区分
     每个仙盟一定有排名,但是不一定有联赛排名,联赛排名只是决定仙盟最终排名的一个比较因素
     '''
-    if familyID not in PyGameData.g_sortFamilyIDList:
-        return len(PyGameData.g_sortFamilyIDList) + 1
-    return PyGameData.g_sortFamilyIDList.index(familyID) + 1
+    return GetFamilyMgr().GetFamilyIDRank(familyID)
 
 def DoFamilySort(isUpdTotalFightPower=True):
     ''' 仙盟排序, 排序规则: 联赛评级 > 总战力 > 等级 > 创建时间
@@ -3590,12 +3701,13 @@
         familyList.append(family)
     familyList.sort(cmp=CmpFamilySort)
     
-    PyGameData.g_sortFamilyIDList = []
+    mgr = GetFamilyMgr()
+    mgr.sortFamilyIDList = []
     for i, family in enumerate(familyList, 1):
         GameWorld.DebugLog("    i=%s,warRank=%s,fightPower=%s,LV=%s,CreateTime=%s,familyID=%s" 
                            % (i, GetFamilyWarRank(family), GetFamilyTotalFightPower(family), family.GetLV(), family.GetCreateTime(), family.GetID()))
-        PyGameData.g_sortFamilyIDList.append(family.GetID())
-    GameWorld.DebugLog("    sortFamilyIDList=%s" % PyGameData.g_sortFamilyIDList)
+        mgr.sortFamilyIDList.append(family.GetID())
+    GameWorld.DebugLog("    sortFamilyIDList=%s" % mgr.sortFamilyIDList)
     return
 
 def CmpFamilySort(family1, family2):
@@ -3836,6 +3948,17 @@
 
 ##--------------------------------------------------------------------------------------------------
 
+def CrossServerMsg_FamilyDelRet(msgData):
+    ## 跨服仙盟删除结果,有收到结果即代表成功
+    familyID = msgData["familyID"]
+    playerID = msgData.get("playerID", 0)
+    gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+    if playerID:
+        gameRecMgr.DelGameRecDataByTypeValue(ShareDefine.Def_GameRecType_FamilyDelSyncCross, [playerID], familyID)
+    else:
+        gameRecMgr.DelGameRecDataByTypeID(ShareDefine.Def_GameRecType_FamilyDelSyncCross, familyID)
+    return
+
 def GetFamilyBillboardInfo(curFamily):
     ## 获取仙盟榜单信息 区服ID、徽章、仙盟名、盟主名、仙盟总战力、仙盟等级
     familyID = curFamily.GetID()
@@ -3851,3 +3974,222 @@
     return {"id":familyID, "name":name, "id2":id2, "name2":name2, "value1":value1, "value2":value2, 
             "value3":value3, "value4":value4, "value5":value5}
 
+def Sync_ClientFamilyUpdToCrossServer():
+    ## 定时同步仙盟变更数据到跨服服务器
+    
+    Sync_ClientFamilyDelToCrossServer() # 防止未删除成功,这里补通知
+    
+    mgr = GetFamilyMgr()
+    if not mgr.syncCrossFamilyDict:
+        return
+    
+    familyManager = GameWorld.GetFamilyManager()
+    for familyID, updMemIDList in mgr.syncCrossFamilyDict.items():
+        family = familyManager.FindFamily(familyID)
+        if not family:
+            continue
+        Send_ClientServerMsg_SyncFamilyInfo("FamilyUpd", GetSyncCrossServerFamilyInfo(family, updMemIDList))
+        
+    mgr.syncCrossFamilyDict = {}
+    return
+
+def Sync_ClientFamilyAllToCrossServer():
+    ## 同步子服所有仙盟信息到跨服
+    
+    if GameWorld.GetGameWorld().GetDictByKey(ChConfig.Def_WorldKey_SyncFamilyAllToCross):
+        return
+    GameWorld.GetGameWorld().SetDict(ChConfig.Def_WorldKey_SyncFamilyAllToCross, 1)
+    GameWorld.Log("开始同步本服所有仙盟到跨服服务器!")
+    
+    Sync_ClientFamilyDelToCrossServer() # 防止未删除成功,这里补通知
+    
+    familyManager = GameWorld.GetFamilyManager()
+    for i in xrange(familyManager.GetCount()):
+        family = familyManager.GetAt(i)
+        if not family:
+            continue
+        Send_ClientServerMsg_SyncFamilyInfo("FamilyUpd", GetSyncCrossServerFamilyInfo(family))
+    return
+
+def Sync_ClientFamilyDelToCrossServer():
+    ## 同步仙盟删除数据到跨服服务器
+    gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+    recDataDict = gameRecMgr.GetGameRecDataDict(ShareDefine.Def_GameRecType_FamilyDelSyncCross)
+    for familyID, recDataList in recDataDict.items():
+        for recData in recDataList:
+            playerID = recData.GetValue1()
+            Send_ClientServerMsg_SyncFamilyInfo("FamilyDel", {"familyID":familyID, "playerID":playerID})
+    return
+
+def GetCrossFamilyBaseInfo(family):
+    return {"ID": family.GetID(), "Name": family.GetName(), "LV":family.GetLV(), "FightPower":GetFamilyTotalFightPower(family), 
+            "LeaderID": family.GetLeaderID(), "LeaderName": family.GetLeaderName(), "EmblemID":GetFamilyEmblemID(family), 
+            "ServerID":family.GetServerID(), "Broadcast":family.GetBroadcast()}
+    
+def GetCrossFamilyMemInfo(member):
+    return {"Name":member.GetName(), "LV":member.GetLV(), "Job":member.GetJob(), "OfficialRank":member.GetOfficialRank(), 
+            "Face":member.GetFace(), "FacePic":member.GetFacePic(), "FamilyLV":member.GetFamilyLV(), "FightPower":GetMemberFightPower(member)}
+    
+def GetSyncCrossServerFamilyInfo(family, memIDList=None):
+    ## 获取仙盟跨服所需信息
+    # @param memIDList: 需要获取成员信息ID列表,不传则取所有成员
+    
+    crossFamilyInfo = GetCrossFamilyBaseInfo(family)
+    
+    memAll = True if memIDList == None else False
+    memInfo = {}
+    for m in xrange(family.GetCount()):
+        member = family.GetAt(m)
+        memID = member.GetPlayerID()
+        if not memID:
+            continue
+        if memIDList and memID not in memIDList:
+            continue
+        memInfo[memID] = GetCrossFamilyMemInfo(member)
+        
+    crossFamilyInfo.update({"memInfo":memInfo, "memAll":memAll})
+    return crossFamilyInfo
+
+def Send_ClientServerMsg_SyncFamilyInfo(syncType, syncInfo):
+    dataMsg = {"syncType":syncType, "syncInfo":syncInfo}
+    CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_SyncFamilyInfo, dataMsg)
+    return
+
+def ClientServerMsg_SyncFamilyInfo(serverGroupID, msgData):
+    ## 收到子服 - 仙盟信息
+    
+    syncType = msgData["syncType"]
+    syncInfo = msgData["syncInfo"]
+    
+    if syncType == "FamilyUpd":
+        __CrossServer_FamilyUpd(syncInfo)
+        
+    elif syncType == "FamilyDel":
+        __CrossServer_FamilyDel(serverGroupID, syncInfo)
+        
+    return
+
+def __CrossServer_FamilyDel(serverGroupID, syncInfo):
+    ## 跨服服务器删除子服仙盟、成员
+    familyID = syncInfo["familyID"]
+    playerID = syncInfo.get("playerID", 0)
+    if playerID:
+        curFamily = GameWorld.GetFamilyManager().FindFamily(familyID)
+        if curFamily:
+            curFamily.DeleteMember(playerID)
+    else:
+        #删除家族 
+        GameWorld.GetFamilyManager().DelFamily(familyID)
+        #删除家族行为数据
+        PlayerFamilyAction.ClearFamilyAction(familyID)
+        
+    # 直接回复就是删除成功
+    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_FamilyDelRet, syncInfo, [serverGroupID])
+    return
+
+def __CrossServer_FamilyUpd(familyInfo):
+    ## 跨服服务器更新子服仙盟 - 这里只覆盖更新,不考虑删除的情况
+    
+    familyID = familyInfo["ID"]
+    familyName = familyInfo["Name"]
+    curFamily = FindAndFixCrossFamilyByIDName(familyID, familyName)
+    if not curFamily:
+        GameWorld.ErrLog("跨服更新仙盟失败! 仙盟不存在或者创建失败! familyID=%s" % familyID)
+        return
+    
+    #curFamily.SetName(familyInfo["Name"]) # 这里不再更新名称
+    curFamily.SetLV(familyInfo["LV"])
+    SetFamilyTotalFightPower(curFamily, familyInfo["FightPower"])
+    curFamily.SetLeaderID(familyInfo["LeaderID"])
+    curFamily.SetLeaderName(familyInfo["LeaderName"])
+    SetFamilyEmblemID(curFamily, familyInfo["EmblemID"])
+    curFamily.SetServerID(familyInfo["ServerID"])
+    curFamily.SetBroadcast(familyInfo["Broadcast"])
+    
+    updMemIDList = []
+    memAll = familyInfo.get("memAll", False)
+    memInfoDict = familyInfo.get("memInfo", {})
+    if memInfoDict:
+        for m in range(curFamily.GetCount())[::-1]:
+            member = curFamily.GetAt(m)
+            memID = member.GetPlayerID()
+            if not memID:
+                continue
+            if memID not in memInfoDict:
+                if memAll:
+                    curFamily.DeleteMember(memID)
+                continue
+            memInfo = memInfoDict.pop(memID)
+            __updCrossFamilyMemberInfo(curFamily, member, memInfo)
+            updMemIDList.append(memID)
+            
+        # 剩下的就是新增的成员
+        for memID, memInfo in memInfoDict.items():
+            member = curFamily.AddMemberEx(memID)
+            if not member:
+                continue
+            __updCrossFamilyMemberInfo(curFamily, member, memInfo)
+            updMemIDList.append(memID)
+            
+    # 相关活动数据更新
+    CrossFamilyGCZ.OnCrossJoinFamilyMemberUpd(curFamily, updMemIDList)
+    return
+
+def FindAndFixCrossFamilyByIDName(familyID, familyName):
+    ## 按仙盟名及ID查找跨服仙盟,重名时系统会自动修改仙盟名
+    
+    familyManager = GameWorld.GetFamilyManager()
+    curFamily = familyManager.FindFamily(familyID)
+    if not curFamily:
+        for i in range(100):
+            crossFamilyName = familyName if i == 0 else ("%s_%s" % (familyName, i))
+            curFamily = familyManager.AddFamilyEx(crossFamilyName, familyID)
+            if curFamily:
+                GameWorld.DebugLog("跨服添加新仙盟! familyID=%s, i=%s" % (familyID, i))
+                break
+        return curFamily
+    
+    # 验证当前名字是否还是唯一的,因为延迟同步的原因,仙盟可能改名时在本服唯一,但是在跨服不唯一
+    nameFamily = familyManager.FindFamilyByName(familyName)
+    if not nameFamily:
+        GameWorld.DebugLog("新同步的名字已经不存在仙盟了,可直接替换新仙盟名! familyID=%s" % familyID)
+        curFamily.SetName(familyName)
+        return curFamily
+    
+    if nameFamily.GetID() == familyID:
+        #GameWorld.DebugLog("还是自己原来的仙盟名,直接返回! familyID=%s" % familyID)
+        return curFamily
+    
+    # 尝试修改仙盟名,如果没有唯一名,则不修改保留最后一次同步的仙盟名,至少最后一次的名字还是唯一的
+    for i in range(1, 100):
+        fixFamilyName = "%s_%s" % (familyName, i)
+        family = familyManager.FindFamilyByName(fixFamilyName)
+        if family:
+            if family.GetID() == familyID:
+                #GameWorld.DebugLog("保留原系统修改的仙盟名! familyID=%s" % familyID)
+                break
+            # 已存在该仙盟名,且不是自己的仙盟
+            continue
+        curFamily.SetName(fixFamilyName)
+        GameWorld.Log("跨服强制修改仙盟名: familyID=%s,%s,%s" % (familyID, i, fixFamilyName))
+        break
+    
+    return curFamily
+
+def __updCrossFamilyMemberInfo(curFamily, member, memInfo):
+    member.SetName(memInfo.get("Name", ""))
+    member.SetLV(memInfo.get("LV", 1))
+    member.SetJob(memInfo.get("Job", 1))
+    member.SetOfficialRank(memInfo.get("OfficialRank", 1))
+    member.SetFace(memInfo.get("Face", 0))
+    member.SetFacePic(memInfo.get("FacePic", 0))
+    SetMemberFightPower(member, memInfo.get("FightPower", 0))
+    memFamilyLV = memInfo.get("FamilyLV", 0)
+    member.SetFamilyLV(memFamilyLV)
+    if memFamilyLV == IPY_GameServer.fmlLeader:
+        curFamily.SetLeaderID(member.GetPlayerID())
+        curFamily.SetLeaderName(member.GetName())
+        curFamily.SetLeaderOfficialRank(member.GetOfficialRank())
+        
+    return
+

--
Gitblit v1.8.0