#!/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 def IsServerOpen(self): ## ÊÇ·ñÕý³£¿ª·ÅÖÐ # ÑéÖ¤Á¬½Ó״̬ if self._connState != ShareDefine.ssConn_Normal: return False # Ñé֤ά»¤×´Ì¬ return True 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 not GameWorld.IsCrossServer(): # Ŀǰ½ö¿ç·þ·þÎñÆ÷ÐèÒª´¦ÀíÐÄÌø¹ã²¥ £¬ÆäËûÔÝʱ²»Óà return # ʱ¼ä»Øµ÷ʱҲÁ¢¿Ìͬ²½ÐÄÌø if self._heartTime and curTime >= self._heartTime and curTime - self._heartTime < HeartBreat: #GameWorld.DebugLog("²»¹ã²¥ÐÄÌø! self._heartTime=%s,curTime=%s,diff=%s" % (self._heartTime, curTime, curTime - self._heartTime)) return self._heartTime = curTime #GameWorld.DebugLog("¹ã²¥ÐÄÌø! self._heartTime=%s,%s" % (self._heartTime, GameWorld.ChangeTimeNumToStr(self._heartTime))) 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) ssServer.SetServerType(serverType) ssServer.SetHeartCurTime(curTime) befConnState = ssServer.GetConnState() # Ä¿±êÊÇ¿ç·þÖÐÐÄ£¬¸üпç·þʱ¼ä if serverType == ShareDefine.serverType_CrossCenter: if not self._crossCenterID: self._crossCenterID = serverID updCrossTime = serverTime curCrossTime = self.GetCrossTime() self.SetCrossTime(updCrossTime, curTime) diffSeconds = updCrossTime - curCrossTime # Îó²îÃë #GameWorld.DebugLog("curCrossTime=%s" % GameWorld.ChangeTimeNumToStr(curCrossTime)) #GameWorld.DebugLog("updCrossTime=%s" % GameWorld.ChangeTimeNumToStr(updCrossTime)) #GameWorld.DebugLog("Óë¿ç·þʱ¼äÎó²î=%s" % diffSeconds) if abs(diffSeconds) >= 30: GameWorld.Log("±¾·þµÄ¿ç·þʱ¼äÓë¿ç·þʵ¼Êʱ¼äÎó²î¹ý´óͬ²½Ç°¶Ë! diffSeconds=%s" % diffSeconds) GameWorld.Log("curCrossTime=%s" % GameWorld.ChangeTimeNumToStr(curCrossTime)) GameWorld.Log("updCrossTime=%s" % GameWorld.ChangeTimeNumToStr(updCrossTime)) ChPlayer.Sync_PyServerDataTimeToClient() if befConnState == ShareDefine.ssConn_Normal: #GameWorld.Log("ÊÕµ½Ä¿±ê¿ç·þ·þÎñÆ÷ÐÄÌø£¬Õý³£Á¬½ÓÖÐ: crossServerID=%s,crossServerTime=%s" % (serverID, GameWorld.ChangeTimeNumToStr(serverTime))) return ssServer.SetConnState(ShareDefine.ssConn_Normal) isReconn = True if befConnState == ShareDefine.ssConn_Disconnected else False # ¿ç·þ·þÎñÆ÷ if serverType in [ShareDefine.serverType_CrossCenter, ShareDefine.serverType_Cross]: if serverType == ShareDefine.serverType_CrossCenter: GameWorld.Log("Á¬ÉÏ¿ç·þÖÐÐÄ·þÎñÆ÷: crossServerID=%s,isReconn=%s,crossServerTime=%s" % (serverID, isReconn, GameWorld.ChangeTimeNumToStr(serverTime))) 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: #GameWorld.DebugLog("ûÓпç·þʱ¼ä£¬Ö±½Ó·µ»Ø±¾·þʱ¼ä") 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 GetCrossCenterID(self): return self._crossCenterID # ¿ç·þÖÐÐÄ·þÎñÆ÷ID def GetCrossServerIDList(self): return self._crossServerIDList # ËùÓÐÔËÐÐÖеĿç·þ·þÎñÆ÷ID£¬°üº¬¿ç·þÖÐÐÄ 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: #GameWorld.Log("¼ì²é¶Ï¿ªÊ±ÎªÕý³£Á¬½ÓÖÐ: serverID=%s,serverType=%s,pass=%s" % (ssServer.GetServerID(), ssServer.GetServerType(), curTime - lastHeartTime)) 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