ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
@@ -57,7 +57,6 @@
import GameWorldFamilyWar
import PlayerFBHelpBattle
import GameWorldSkyTower
import GMT_CTG
import PyGameData
import GMShell
import IPY_PlayerDefine
@@ -74,9 +73,63 @@
import CrossBattlefield
import CrossActAllRecharge
import CrossYaomoBoss
import CrossRealmMsg
import PlayerViewCache
import PlayerFuncTeam
import PyDataManager
import GameWorldMineArea
import PlayerPackData
import PlayerRecData
import GameWorship
import GameXiangong
import CrossFamilyGCZ
#---------------------------------------------------------------------
#---------------------------------------------------------------------
class OnlinePlayerMgr():
    ''' 在线玩家管理,子服跨服通用
            注:跨服服务器时,玩家不一定在跨服服务器,只是表示有同步到跨服服务器的在线玩家,且不是所有玩家都有同步
    '''
    def __init__(self):
        self.onlinePlayerDict = {} # 在线玩家 {playerID:serverGroupID, ...}
        return
    def IsOnline(self, playerID): return playerID in self.onlinePlayerDict
    def GetOLPlayerServerGroupID(self, playerID): return self.onlinePlayerDict.get(playerID, 0)
    def __SetOnline(self, playerID, serverGroupID):
        self.onlinePlayerDict[playerID] = serverGroupID
        return
    def __SetOffline(self, playerID, serverGroupID):
        self.onlinePlayerDict.pop(playerID, None)
        return
    def SetOnlineState(self, playerID, isOnline, serverGroupID=0):
        if isOnline:
            self.__SetOnline(playerID, serverGroupID)
        else:
            self.__SetOffline(playerID, serverGroupID)
        return
    def GetOfflineValue(self, playerID, viewCache=None):
        ## 离线值:0-在线;1-离线;>1-上次离线时间戳,可用于计算离线多久了;当取不到玩家信息时用1代表已离线;
        if playerID in self.onlinePlayerDict:
            return 0
        offlineValue = 1
        if viewCache and viewCache.OffTime:
            offlineValue = viewCache.OffTime
        return offlineValue
def GetOnlinePlayerMgr():
    mgr = PyGameData.g_onlinePlayerMgr
    if mgr == None:
        mgr = OnlinePlayerMgr()
        PyGameData.g_onlinePlayerMgr = mgr
    return mgr
#---------------------------------------------------------------------
@@ -129,8 +182,6 @@
    ''' 玩家登录需要处理的内容,本服及跨服服务器分开
    '''
    if GameWorld.IsCrossServer():
        #跨服PK
        CrossRealmPK.OnPlayerLoginCrossServer(curPlayer)
        #协助
        PlayerAssist.OnPlayerLoginCrossServer(curPlayer)
        return
@@ -209,7 +260,6 @@
        GameWorldSkyTower.OnPlayerLogin(curPlayer)
        #福地
        GameWorldMineArea.OnPlayerLogin(curPlayer)
        GMT_CTG.OnPlayerLogin(curPlayer)
        
    else:
        pass
@@ -242,10 +292,17 @@
        CrossBattlefield.OnPlayerLogin(curPlayer)
        #跨服排位
        CrossChampionship.OnPlayerLogin(curPlayer, tick)
        #仙盟攻城战
        CrossFamilyGCZ.OnPlayerLogin(curPlayer)
        #跨服全民充值
        CrossActAllRecharge.OnPlayerLogin(curPlayer)
        #跨服妖魔boss
        CrossYaomoBoss.OnPlayerLogin(curPlayer)
        #玩家记录
        PlayerRecData.OnPlayerLogin(curPlayer)
        PlayerPackData.OnPlayerLogin(curPlayer)
        #在线状态变更,放最后
        __OnPlayerOnlineStateChange(curPlayer, True)
        
    if isMixServerFirstLogin:
        PlayerCharm.OnMixServerFirstLogin(curPlayer)
@@ -585,9 +642,7 @@
    
    if GameWorld.IsCrossServer():
        PlayerFB.OnPlayerDisconnectCrossServer(curPlayer)
    #跨服匹配PK
    CrossRealmPK.OnLeaveServer(curPlayer)
        return
    
    #组队玩家离线
    PlayerTeam.DoPlayerLogOffTeamLogic(curPlayer, tick)
@@ -611,7 +666,119 @@
    if not PlayerControl.GetIsTJG(curPlayer):
        playerID = curPlayer.GetPlayerID()
        PyGameData.g_unTJLogoffTime[playerID] = int(time.time())
        PyGameData.g_xiangongCanLikeTimeDict.pop(playerID, None)
        
        #在线状态变更,放最后
        __OnPlayerOnlineStateChange(curPlayer, False)
    return
def __OnPlayerOnlineStateChange(curPlayer, isOnline):
    ## 在线状态变更
    if PlayerControl.GetIsTJG(curPlayer):
        return
    playerID = curPlayer.GetPlayerID()
    olMgr = GetOnlinePlayerMgr()
    olMgr.SetOnlineState(playerID, isOnline)
    #relatedPlayerIDList = [] # 本服相关玩家
    #offlineValue = olMgr.GetOfflineValue(playerID, PlayerViewCache.FindViewCache(playerID))
    #SyncRelatedPlayerOnlineState(playerID, offlineValue, relatedPlayerIDList)
    syncLV = IpyGameDataPY.GetFuncCfg("CrossSyncSet", 1)
    if curPlayer.GetLV() < syncLV:
        #GameWorld.DebugLog("跨服相关功能未开启,不同步在线状态到跨服服务器! LV=%s < %s" % (curPlayer.GetLV(), syncLV), curPlayer.GetPlayerID())
        return
    cacheBase = PlayerViewCache.GetSyncCrossCacheBase(curPlayer)
    dataMsg = {"playerID":playerID, "isOnline":isOnline, "cacheBase":cacheBase}
    CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PlayerLoginout, dataMsg)
    return
def ClientServerMsg_PlayerLoginout(serverGroupID, msgData):
    ## 收到子服玩家上下线
    playerID = msgData["playerID"]
    isOnline = msgData["isOnline"]
    cacheBase = msgData["cacheBase"]
    isLogout = not isOnline
    olMgr = GetOnlinePlayerMgr()
    olMgr.SetOnlineState(playerID, isOnline, cacheBase.get("ServerGroupID", 0))
    PlayerViewCache.UpdCrossCacheBase(playerID, cacheBase, isLogout)
    serverID = GameWorld.GetAccIDServerID(cacheBase["AccID"])
    # 上线
    if isOnline:
        # 需要管理跨服在线状态时,默认需要同步缓存信息、打包数据信息
        syncStateInfo = {"playerID":playerID, "ViewCacheCross":1, "PackDataCross":1}
        CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PlayerPackDataState, syncStateInfo, [serverGroupID])
        GameXiangong.OnPlayerLogin_CrossLogic(serverGroupID, serverID, playerID)
        #仙盟攻城战
        CrossFamilyGCZ.OnPlayerLogin_CrossLogic(serverGroupID, serverID, playerID)
    # 下线
    else:
        pass
    SyncCrossPlayerOnlineStateToRelatedPlayer(playerID)
    return
def SyncCrossPlayerOnlineStateToRelatedPlayer(playerID):
    ## 同步跨服玩家在线状态给相关玩家
    relatedPlayerIDList = []
    # 功能队伍
    funcTeamMgr = PyDataManager.GetDBPyFuncTeamManager()
    playerTeamIDDict = funcTeamMgr.GetPlayerTeamIDDict(playerID)
    for _, teamID in playerTeamIDDict.items():
        funcTeam = funcTeamMgr.GetFuncTeam(teamID)
        if not funcTeam:
            continue
        relatedPlayerIDList += funcTeam.GetMemberIDList()
    # 其他...
    # 去重汇总
    relatedPlayerIDList = list(set(relatedPlayerIDList))
    if playerID in relatedPlayerIDList:
        relatedPlayerIDList.remove(playerID)
    if not relatedPlayerIDList:
        return
    offlineValue = GetOnlinePlayerMgr().GetOfflineValue(playerID, PlayerViewCache.FindViewCache(playerID))
    dataMsg = {"loginoutPlayerID":playerID, "offlineValue":offlineValue, "relatedPlayerIDList":relatedPlayerIDList}
    CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PlayerLoginout, dataMsg)
    return
def CrossServerMsg_PlayerLoginout(msgData):
    ## 收到跨服服务器信息 - 玩家上下线状态变更
    loginoutPlayerID = msgData["loginoutPlayerID"]
    offlineValue = msgData["offlineValue"]
    relatedPlayerIDList = msgData["relatedPlayerIDList"]
    SyncRelatedPlayerOnlineState(loginoutPlayerID, offlineValue, relatedPlayerIDList, 1)
    return
def SyncRelatedPlayerOnlineState(loginoutPlayerID, offlineValue, relatedPlayerIDList, isCross=0):
    clientPack = None
    playerMgr = GameWorld.GetPlayerManager()
    for playerID in relatedPlayerIDList:
        if not PlayerControl.GetDBPlayerAccIDByID(playerID):
            continue
        curPlayer = playerMgr.FindPlayerByID(playerID)
        if not curPlayer or not curPlayer.GetInitOK():
            continue
        if not clientPack:
            clientPack = ChPyNetSendPack.tagGCRelatedPlayerOnlineState()
            clientPack.PlayerID = loginoutPlayerID
            clientPack.OfflineValue = offlineValue
            clientPack.IsCross = isCross
        NetPackCommon.SendFakePack(curPlayer, clientPack)
    return
## 设置玩家离线时间
@@ -676,6 +843,7 @@
    packValue = playerStatePack.GetValue()
    packValueEx = playerStatePack.GetValueEx()
    packType = playerStatePack.GetType()
    #packValueTotal = packValue + packValueEx * ChConfig.Def_PerPointValue
    
    #---特殊逻辑处理---
    if packType == ShareDefine.CDBPlayerRefresh_ForbidenTalk:
@@ -685,7 +853,11 @@
    if packType == ShareDefine.CDBPlayerRefresh_ExAttr17:
        PlayerControl.SetPlayerAccState(curPlayer, packValue)
        return
    if packType == ShareDefine.CDBPlayerRefresh_ExAttr19:
        PlayerControl.SetLeaveFamilyTimeEx(curPlayer, packValue)
        return
    if packType == IPY_GameServer.CDBPlayerRefresh_State:
        # 脱机在线
        PlayerControl.SetIsTJG(curPlayer, packValue)
@@ -721,7 +893,6 @@
        
    elif packType == IPY_GameServer.CDBPlayerRefresh_LV:
        curPlayer.SetLV(packValue)
        PlayerSocial.UpdateSocialInfo(curPlayer.GetID(), packType, packValue)
        #玩家等级记录
        playerID = curPlayer.GetID()
        if playerID in PyGameData.g_todayPlayerLVDict:
@@ -771,10 +942,18 @@
    
    elif packType == IPY_GameServer.CDBPlayerRefresh_OfficialRank:
        curPlayer.SetOfficialRank(packValue)
        PlayerSocial.UpdateSocialInfo(curPlayer.GetID(), packType, packValue)
        #更新排行榜的境界
        PlayerBillboard.UpdateBillboardRealm(curPlayer)
    elif packType == IPY_GameServer.CDBPlayerRefresh_Face:
        curPlayer.SetFace(packValue)
        PlayerBillboard.UpdateBillboardFace(curPlayer)
    elif packType == IPY_GameServer.CDBPlayerRefresh_HairColor:
        #c++头像外框 用头发颜色通知  - 遗漏问题
        curPlayer.SetFacePic(packValue)
        PlayerBillboard.UpdateBillboardFacePic(curPlayer)
        
    #社交信息
    PlayerSocial.UpdateSocialInfo(curPlayer.GetID(), packType, packValue)
    #组队成员刷新
    PlayerTeam.PlayerTeamMemberRefresh(curPlayer, packType, packValue, tick)
    #家族刷新