hxp
2024-11-15 79a0b7a92d3dfbcc326fd9465b70f05cc3cbdf92
ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
@@ -64,12 +64,70 @@
import GameWorldArena
import CrossLuckyCloudBuy
import CrossRealmPK
import CrossChampionship
import AuctionHouse
import PlayerAssist
import PlayerFB
import PlayerLove
import PlayerCharm
import CrossRealmPlayer
import CrossBattlefield
import CrossActAllRecharge
import CrossYaomoBoss
import CrossRealmMsg
import PlayerViewCache
import PlayerFuncTeam
import PyDataManager
import GameWorldMineArea
import PlayerPackData
import PlayerRecData
import GameWorship
import GameXiangong
#---------------------------------------------------------------------
#---------------------------------------------------------------------
class OnlinePlayerMgr():
    ''' 在线玩家管理,子服跨服通用
            注:跨服服务器时,玩家不一定在跨服服务器,只是表示有同步到跨服服务器的在线玩家,且不是所有玩家都有同步
    '''
    def __init__(self):
        self.onlinePlayerDict = {} # 在线玩家 {playerID:serverGroupID, ...}
        return
    def IsOnline(self, playerID): return playerID in self.onlinePlayerDict
    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
#---------------------------------------------------------------------
@@ -124,6 +182,8 @@
    if GameWorld.IsCrossServer():
        #跨服PK
        CrossRealmPK.OnPlayerLoginCrossServer(curPlayer)
        #协助
        PlayerAssist.OnPlayerLoginCrossServer(curPlayer)
        return
    
    #玩家家族刷新
@@ -131,8 +191,9 @@
    PlayerFamily.PlayerLoginRefreshFamily(curPlayer, tick)
    #玩家队伍初始化
    PlayerTeam.OnPlayerLoginRefreshTeam(curPlayer, tick)
    PlayerCompensation.NotifyPlayerCompensation(curPlayer)
    #PlayerCompensation.NotifyPlayerCompensation(curPlayer)
    __UpdOnedayJobPlayerLoginoffTime(curPlayer)
    CrossRealmPlayer.OnPlayerLogin(curPlayer)
    
    if not PlayerControl.GetIsTJG(curPlayer):
        # 只有通知逻辑的应该放此处减少IO,如有逻辑处理存储等不可放在此处
@@ -194,14 +255,15 @@
        #骑宠boss状态通知
        PlayerHorsePetBoss.OnLogin(curPlayer)
        #协助
        PlayerAssist.OnPlayerLogin(curPlayer, False)
        PlayerAssist.OnPlayerLogin(curPlayer)
        #天星塔
        GameWorldSkyTower.OnPlayerLogin(curPlayer)
        #福地
        GameWorldMineArea.OnPlayerLogin(curPlayer)
        GMT_CTG.OnPlayerLogin(curPlayer)
        
    else:
        #协助
        PlayerAssist.OnPlayerLogin(curPlayer, True)
        pass
        
    return
@@ -216,6 +278,8 @@
    if GameWorld.IsCrossServer():
        return
    
    PyGameData.g_dbPlayerIDMap[curPlayer.GetPlayerID()] = curPlayer.GetAccID()
    if not PlayerControl.GetIsTJG(curPlayer):
        #家族副本boss状态通知
        PlayerFamilyBoss.OnLogin(curPlayer)
@@ -223,10 +287,26 @@
        PlayerCharm.OnPlayerLogin(curPlayer)
        #情缘
        PlayerLove.OnPlayerLogin(curPlayer)
        #膜拜
        GameWorship.OnPlayerLogin(curPlayer)
        #跨服战场
        CrossBattlefield.OnPlayerLogin(curPlayer)
        #跨服排位
        CrossChampionship.OnPlayerLogin(curPlayer, tick)
        #跨服全民充值
        CrossActAllRecharge.OnPlayerLogin(curPlayer)
        #跨服妖魔boss
        CrossYaomoBoss.OnPlayerLogin(curPlayer)
        #玩家记录
        PlayerRecData.OnPlayerLogin(curPlayer)
        PlayerPackData.OnPlayerLogin(curPlayer)
        #在线状态变更,放最后
        __OnPlayerOnlineStateChange(curPlayer, True)
        
    if isMixServerFirstLogin:
        PlayerCharm.OnMixServerFirstLogin(curPlayer)
        
    PyGameData.g_noPlayerLoginWarningMailState = 2
    return
def __UpdOnedayJobPlayerLoginoffTime(curPlayer):
@@ -561,7 +641,8 @@
    
    if GameWorld.IsCrossServer():
        PlayerFB.OnPlayerDisconnectCrossServer(curPlayer)
        return
    #跨服匹配PK
    CrossRealmPK.OnLeaveServer(curPlayer)
    
@@ -587,7 +668,113 @@
    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)
    if curPlayer.GetLV() < 50:
        #GameWorld.DebugLog("跨服相关功能未开启,不同步在线状态到跨服服务器! LV=%s" % curPlayer.GetLV(), 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:
        PlayerPackData.OnPlayerLogin_CrossLogic(serverGroupID, serverID, playerID)
        GameXiangong.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
## 设置玩家离线时间
@@ -652,6 +839,7 @@
    packValue = playerStatePack.GetValue()
    packValueEx = playerStatePack.GetValueEx()
    packType = playerStatePack.GetType()
    #packValueTotal = packValue + packValueEx * ChConfig.Def_PerPointValue
    
    #---特殊逻辑处理---
    if packType == ShareDefine.CDBPlayerRefresh_ForbidenTalk:
@@ -661,7 +849,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)
@@ -697,13 +889,14 @@
        
    elif packType == IPY_GameServer.CDBPlayerRefresh_LV:
        curPlayer.SetLV(packValue)
        PlayerSocial.UpdateSocialInfo(curPlayer.GetID(), packType, packValue)
        #玩家等级记录
        playerID = curPlayer.GetID()
        if playerID in PyGameData.g_todayPlayerLVDict:
            PyGameData.g_todayPlayerLVDict[playerID] = packValue
    elif packType == IPY_GameServer.CDBPlayerRefresh_Job:
        if packValue != curPlayer.GetJob():
            PlayerBillboard.DelJobFightPowerBillboard(curPlayer, curPlayer.GetJob())
        curPlayer.SetJob(packValue)
        
#    elif packType == IPY_GameServer.CDBPlayerRefresh_CurrentPlayerType:
@@ -731,7 +924,8 @@
        PlayerControl.SetCrossMapID(curPlayer, packValue, False)
        
    elif packType == IPY_GameServer.CDBPlayerRefresh_ExAttr9:
        PlayerControl.SetVIPExpireTime(curPlayer, packValue)
        curPlayer.SetExAttr9(packValue)
        #PlayerControl.SetVIPExpireTime(curPlayer, packValue)
        
    elif packType == IPY_GameServer.CDBPlayerRefresh_ExAttr10:
        PlayerControl.SetChatBubbleBox(curPlayer, packValue)
@@ -744,10 +938,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)
    #家族刷新
@@ -1201,11 +1403,6 @@
#  @param tick 时间戳
#  @return None
def Sync_PyServerDataTimeToClient(curPlayer, tick):
    if not GameWorld.RefurbishPlayerTick(curPlayer, ChConfig.TYPE_Player_Tick_SyncClientTick, tick):
        #间隔未到
        return
    # 服务器时间
    serverTime = GameWorld.GetServerTime()
    if not serverTime: