ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/CrossServerPackLogic.py
@@ -7,16 +7,163 @@
# 跨服服务器间的封包 既是收包也是发包
import GameWorld
import ChServerToServerPyPack
import ShareDefine
import NetPackCommon
import ChServerToServerPyPack
import TurnAttack
import PyGameData
import ChPlayer
import traceback
import cPickle
import time
def OnTest(netPack):
    GameWorld.Log("收到跨服包 " + str(netPack.Data))
def SendTest():
def SendTest(dirType, serverList):
    pack = ChServerToServerPyPack.tagSSTest()
    pack.Data = 12
    #0全广播,1通知主服务器排除合服子服,2通知服务器包含合服子服, 3通知跨服服务器 
    NetPackCommon.SendCrossServerToServerPack(1, "[501]", pack.GetBuffer())
    NetPackCommon.SendCrossServerToServerPack(dirType, serverList, pack.GetBuffer())
    return
def GetCrossServerID():
    ## 获取本服务器所属的跨服中心服务器
    return 0
def SendToCrossServer(msgType, dataMsg):
    ## 发送信息到跨服服务器
    if GameWorld.IsCrossServer():
        return
    if not dataMsg:
        return
    if msgType not in [ShareDefine.ClientServerMsg_ServerInitOK]:
        isOpen = GameWorld.GetGameWorld().GetDictByKey(ShareDefine.Def_Notify_WorldKey_CrossServerOpen)
        if not isOpen:
            GameWorld.Log("跨服服务器未开启或维护中不发送消息! SendMsgToCrossServer => %s" % msgType)
            return
    crossServerID = GetCrossServerID()
    if not crossServerID:
        return
    playerID = 0
    if isinstance(dataMsg, dict):
        playerID = dataMsg.get("playerID", 0)
        if not playerID:
            playerID = dataMsg.get("PlayerID", 0)
    GameWorld.Log("SendMsgToCrossServer => %s, %s, %s" % (msgType, crossServerID, dataMsg), playerID)
    SendToServer(msgType, dataMsg, [crossServerID], ShareDefine.dirType_Cross, playerID, isLog=False)
    return
def SendToClientServer(msgType, dataMsg, serverIDList=None):
    ''' 发送信息到子服务器
        @param serverGroupIDList: 发送指定的服务器组ID列表,内部已经针对列表中组ID去重,
        所以外部逻辑可直接添加,不用考虑组ID重复问题,没有指定服务器组ID时,默认广播所有子服
    '''
    if not GameWorld.IsCrossServer():
        return
    if not PyGameData.g_serverInitOK:
        GameWorld.ErrLog("跨服服务器未启动好,不允许向子服发送数据! %s, %s, %s" % (msgType, serverIDList, dataMsg))
        return
    playerID = 0
    if isinstance(dataMsg, dict):
        playerID = dataMsg.get("playerID", 0)
        if not playerID:
            playerID = dataMsg.get("PlayerID", 0)
    GameWorld.Log("SendToClientServer => %s, %s, %s" % (msgType, serverIDList, dataMsg), playerID)
    SendToServer(msgType, dataMsg, serverIDList, ShareDefine.dirType_Main, playerID, isLog=False) # 默认发给主服即可
    return
def SendToBattleServer(msgType, dataMsg, playerID=0):
    SendToServer(msgType, dataMsg, dirType=ShareDefine.dirType_Battle, playerID=playerID)
    return
def SendToServer(msgType, dataMsg, serverIDList=None, dirType=ShareDefine.dirType_Main, playerID=0, isLog=True):
    '''发送给其他服务器
    @param msgType: 功能信息类型字符定义
    @param dataMsg: 发送的数据,任意格式,由功能自行决定
    @param serverIDList: 指定目标服务器ID 或   服务器ID列表
    '''
    if isinstance(serverIDList, int):
        serverIDList = [serverIDList]
    elif not isinstance(serverIDList, list):
        serverIDList = []
    else:
        serverIDList = list(set(serverIDList)) # 去重
    if isLog:
        GameWorld.Log("SendToServer => %s, %s, %s" % (msgType, serverIDList, dataMsg), playerID)
    # 协议要用最高级2,可减少长度
    sendMsg = cPickle.dumps(dataMsg, 2)
    pack = ChServerToServerPyPack.tagSSCommMsg()
    pack.FromServerID = GameWorld.GetGameWorld().GetServerID()
    pack.ServerTime = int(time.time())
    pack.MsgType = msgType
    pack.TypeLen = len(pack.MsgType)
    pack.Data = sendMsg
    pack.Len = len(pack.Data)
    NetPackCommon.SendCrossServerToServerPack(dirType, serverIDList, pack.GetBuffer())
    return
def OnSSCommMsg(netPack):
    ## 收到其他服务器发来的消息
    fromServerID = netPack.FromServerID
    fromServerTime = netPack.ServerTime
    msgType = netPack.MsgType
    recvMsg = netPack.Data
    if not PyGameData.g_serverInitOK:
        GameWorld.Log("服务器未启动好,不处理其他服务器信息! %s, fromServerID=%s" % (msgType, fromServerID))
        return
    try:
        dataMsg = cPickle.loads(recvMsg)
        if GameWorld.IsCrossServer():
            GameWorld.Log("OnCrossServerReceiveMsg: %s, fromServerID=%s, %s" % (msgType, fromServerID, dataMsg))
        else:
            GameWorld.Log("OnClientServerReceiveMsg: %s, fromServerID=%s, %s" % (msgType, fromServerID, dataMsg))
            crossServerID = GetCrossServerID()
            if crossServerID == fromServerID:
                __fixCrossServerTime(msgType, fromServerTime)
        if msgType == ShareDefine.SSMsg_BattleRequest:
            TurnAttack.SSMsg_BattleRequest(dataMsg, fromServerID)
        elif msgType == ShareDefine.SSMsg_BattleResult:
            TurnAttack.SSMsg_BattleResult(dataMsg, fromServerID)
    except:
        GameWorld.RaiseException("服务器接收信息处理报错 \r\n%s" % str(traceback.format_exc()))
    return
def __fixCrossServerTime(msgType, crossServerTime):
    # 子服矫正跨服服务器时间
    curServerTime = int(time.time())
    curServerCrossServerTime = GameWorld.ChangeTimeStrToNum(GameWorld.GetCrossServerTimeStr())
    diffSeconds = curServerCrossServerTime - crossServerTime # 本服计算误差
    PyGameData.g_crossServerTimeInfo = [crossServerTime, curServerTime] # 覆盖更新
    # 误差超过30秒 或强制同步时间的
    if abs(diffSeconds) >= 30 or msgType == ShareDefine.CrossServerMsg_CrossServerTime:
        GameWorld.DebugLog("同步跨服服务器时间,本服与跨服服务器时间计算误差! diffSeconds=%s" % (diffSeconds))
        playerManager = GameWorld.GetPlayerManager()
        for i in xrange(playerManager.GetPlayerCount()):
            curPlayer = playerManager.GetPlayerByIndex(i)
            if not GameWorld.IsNormalPlayer(curPlayer):
                continue
            ChPlayer.Sync_PyServerDataTimeToClient(curPlayer)
    return