#!/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
|