From 79a0b7a92d3dfbcc326fd9465b70f05cc3cbdf92 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 15 十一月 2024 18:11:55 +0800
Subject: [PATCH] 1111 修改同步跨服缓存数据条件(50级以内不同步)

---
 ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py |  261 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 244 insertions(+), 17 deletions(-)

diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
index 2189b3c..682d763 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
@@ -62,11 +62,72 @@
 import GMShell
 import IPY_PlayerDefine
 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
 
 #---------------------------------------------------------------------
 
@@ -121,6 +182,8 @@
     if GameWorld.IsCrossServer():
         #跨服PK
         CrossRealmPK.OnPlayerLoginCrossServer(curPlayer)
+        #协助
+        PlayerAssist.OnPlayerLoginCrossServer(curPlayer)
         return
     
     #玩家家族刷新
@@ -128,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,如有逻辑处理存储等不可放在此处
@@ -169,8 +233,6 @@
         PlayerStore.OnPlayerLogin(curPlayer)
         #通知世界boss信息
         GameWorldBoss.OnPlayerLogin(curPlayer)
-        #家族副本boss状态通知
-        PlayerFamilyBoss.OnLogin(curPlayer)
         #渡劫
         PlayerDuJie.OnPlayerLogin(curPlayer)
         #守卫人皇
@@ -186,20 +248,65 @@
         GameWorldArena.OnPlayerLogin(curPlayer)
         #跨服PK
         CrossRealmPK.OnPlayerLogin(curPlayer)
+        #幸运云购
+        CrossLuckyCloudBuy.OnPlayerLogin(curPlayer)
         #诛仙BOSS
         PlayerZhuXianBoss.OnPlayerLogin(curPlayer)
         #骑宠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
+
+def DoPlayerRealLoginOK(curPlayer, loginMsg, tick):
+    ''' 玩家最终登录成功处理, 由  MapServer  DoPlayerRealLoginOK  通知
+        该函数为地图最终登录成功才会执行到,以后一些功能类的登录处理建议均写到这里
+        旧的功能先不动( __DoPlayerLoginServer 函数中的功能),如果有登录相关的bug再考虑是否移动到此函数
+    '''
+    isMixServerFirstLogin = loginMsg[0]
+    GameWorld.Log("GameServer->DoPlayerRealLoginOK, isMixServerFirstLogin=%s" % isMixServerFirstLogin, curPlayer.GetPlayerID())
+    
+    if GameWorld.IsCrossServer():
+        return
+    
+    PyGameData.g_dbPlayerIDMap[curPlayer.GetPlayerID()] = curPlayer.GetAccID()
+    
+    if not PlayerControl.GetIsTJG(curPlayer):
+        #家族副本boss状态通知
+        PlayerFamilyBoss.OnLogin(curPlayer)
+        #魅力
+        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):
@@ -534,7 +641,8 @@
     
     if GameWorld.IsCrossServer():
         PlayerFB.OnPlayerDisconnectCrossServer(curPlayer)
-        
+        return
+    
     #跨服匹配PK
     CrossRealmPK.OnLeaveServer(curPlayer)
     
@@ -552,13 +660,121 @@
     AuctionHouse.OnPlayerLeaveServer(curPlayer)
     #协助
     PlayerAssist.OnLeaveServer(curPlayer)
+    #红包
+    PlayerFamilyRedPacket.OnLeaveServer(curPlayer)
     #------------镖车逻辑
     #TruckPlayerDisconnectProcess(curPlayer, tick)
     
     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
 
 ## 设置玩家离线时间
@@ -623,6 +839,7 @@
     packValue = playerStatePack.GetValue()
     packValueEx = playerStatePack.GetValueEx()
     packType = playerStatePack.GetType()
+    #packValueTotal = packValue + packValueEx * ChConfig.Def_PerPointValue
     
     #---特殊逻辑处理---
     if packType == ShareDefine.CDBPlayerRefresh_ForbidenTalk:
@@ -632,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)
@@ -668,13 +889,14 @@
         
     elif packType == IPY_GameServer.CDBPlayerRefresh_LV:
         curPlayer.SetLV(packValue)
-        PlayerSocial.UpdateSocialInfo(curPlayer, 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:
@@ -702,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)
@@ -715,10 +938,18 @@
     
     elif packType == IPY_GameServer.CDBPlayerRefresh_OfficialRank:
         curPlayer.SetOfficialRank(packValue)
-        PlayerSocial.UpdateSocialInfo(curPlayer, 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)
     #家族刷新
@@ -1172,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:
@@ -1190,7 +1416,8 @@
     serverDateTime.Hour = serverTime.hour
     serverDateTime.Minute = serverTime.minute
     serverDateTime.Second = serverTime.second
-    serverDateTime.MicSecond = serverTime.microsecond   
+    serverDateTime.MicSecond = serverTime.microsecond
+    serverDateTime.CrossServerTime = GameWorld.GetCrossServerTimeStr()
     
     # 通知客户端同步时间
     NetPackCommon.SendFakePack(curPlayer, serverDateTime)

--
Gitblit v1.8.0