ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossPlayerData.py
@@ -20,6 +20,7 @@
import SkillCommon
import base64
import ChConfig
import PyGameData
# 发送格式: 类型+(数量)+数据
# 向跨服发送的数据类型
@@ -30,8 +31,17 @@
MergeData_Buff,     # 即时发送
) = range(0, 4)
# 发送主服玩家数据给跨服
# 影响跨服战力属性列表
CrossFightPowerAttrList = [
    [lambda curObj:curObj.GetBaseSTR(), lambda curObj, value:curObj.SetBaseSTR(value)], # 力量
    [lambda curObj:curObj.GetBasePNE(), lambda curObj, value:curObj.SetBasePNE(value)], # 智力
    [lambda curObj:curObj.GetBasePHY(), lambda curObj, value:curObj.SetBasePHY(value)], # 敏捷
    [lambda curObj:curObj.GetBaseCON(), lambda curObj, value:curObj.SetBaseCON(value)], # 体质
    [lambda curObj:curObj.GetOfficialRank(), lambda curObj, value:curObj.SetOfficialRank(value)], # 境界
    [lambda curObj:curObj.GetVIPLv(), lambda curObj, value:curObj.SetVIPLv(value)], # VIP等级
                           ]
# 发送主服玩家数据给跨服
def SendMergeData_Buff(curPlayer, buffID, plusValueList):
    if buffID in [ChConfig.Def_SkillID_LimitSuperBuff,
                  ChConfig.Def_SkillID_TJGSuperBuff]:
@@ -88,9 +98,192 @@
            
        buffType = SkillCommon.GetBuffType(curSkill)
        BuffSkill.AddBuffNoRefreshState(curPlayer, buffType, curSkill, tick, plusValueList)
    elif dataType == MergeData_Player:
        __ReadMainServerSyncPlayerData(curPlayer, curPlayer.GetMergePlayerData(), pos)
        
    return
## ----------------------------------------------------------------------------------------------
def IsNeedProcessCrossPlayer(curPlayer):
    ## 是否需要处理同步跨服中的玩家数据
    if GameWorld.IsCrossServer():
        return
    crossMapID = curPlayer.NomalDictGetProperty(ChConfig.Def_PlayerKey_CrossRegisterMap)
    if not crossMapID:
        crossMapID = PlayerControl.GetCrossMapID(curPlayer)
    if not crossMapID or crossMapID not in ChConfig.Def_CrossMapIDList:
        return
    # 不需要处理的跨服地图
    if crossMapID in [ChConfig.Def_FBMapID_CrossRealmPK]:
        return
    return True
def ClearCrossSyncDataCache(curPlayer):
    ## 清除同步跨服数据的临时缓存
    playerID = curPlayer.GetPlayerID()
    PyGameData.g_crossRegPlayerAttrDict.pop(playerID, None)
    PyGameData.g_crossSyncTickDict.pop(playerID, None)
    PyGameData.g_crossPlayerDictChangeInfo.pop(playerID, None)
    GameWorld.DebugLog("清除同步跨服数据的临时缓存", playerID)
    return
def OnPlayerCrossReg(curPlayer):
    ## 玩家跨服数据注册
    if not IsNeedProcessCrossPlayer(curPlayer):
        return
    ClearCrossSyncDataCache(curPlayer)
    attrList = []
    for attrInfo in CrossFightPowerAttrList:
        attrList.append(attrInfo[0](curPlayer))
    playerID = curPlayer.GetPlayerID()
    PyGameData.g_crossRegPlayerAttrDict[playerID] = attrList
    return
def OnPlayerFightPowerChange(curPlayer):
    ## 玩家战力变更时
    if not IsNeedProcessCrossPlayer(curPlayer):
        return
    playerID = curPlayer.GetPlayerID()
    if playerID in PyGameData.g_crossSyncTickDict:
        return
    tick = GameWorld.GetGameWorld().GetTick()
    PyGameData.g_crossSyncTickDict[playerID] = tick
    #GameWorld.DebugLog("标记需要同步跨服玩家战力变更相关数据! tick=%s" % tick, curPlayer.GetPlayerID())
    return
def ProcessCrossPlayer(curPlayer, tick):
    ## 跨服状态的本服玩家处理
    if not IsNeedProcessCrossPlayer(curPlayer):
        return
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_crossSyncTickDict:
        return
    setTick = PyGameData.g_crossSyncTickDict[playerID]
    if tick - setTick < 5000:
        return
    PyGameData.g_crossSyncTickDict.pop(playerID)
    GameWorld.DebugLog("开始同步本服变更的属性...", playerID)
    # 这里只做可能引起战力变化所需要同步的数据
    data = ""
    data = __WriteSyncPlayerAttrData(curPlayer, data) # 玩家属性
    data = __WriteSyncPlayerDictData(curPlayer, data) # 字典
    # 物品
    # 技能
    #直接用字节流会报错
    data = base64.b64encode(data)
    curPlayer.SendMergePlayerData(data)
    return
def __ReadMainServerSyncPlayerData(curPlayer, pdata, pos):
    ## 读取子服同步的玩家战力变更相关属性
    GameWorld.DebugLog("收到子服同步的玩家变更数据:", curPlayer.GetPlayerID())
    pos = __ReadSyncPlayerAttrData(curPlayer, pdata, pos) # 玩家属性
    pos = __ReadSyncPlayerDictData(curPlayer, pdata, pos) # 字典
    # 物品
    # 技能
    # 强刷一次属性
    PlayerControl.PlayerControl(curPlayer).ReCalcAllState()
    return
def __WriteSyncPlayerAttrData(curPlayer, data):
    ## 写入需要同步的玩家属性
    data = CommFunc.WriteBYTE(data, MergeData_Player)
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_crossRegPlayerAttrDict:
        return CommFunc.WriteBYTE(data, 0)
    attrList = PyGameData.g_crossRegPlayerAttrDict[playerID]
    if len(attrList) != len(CrossFightPowerAttrList):
        return CommFunc.WriteBYTE(data, 0)
    changeAttrList = []
    for i, attrInfo in enumerate(CrossFightPowerAttrList):
        befValue = attrList[i]
        curValue = attrInfo[0](curPlayer)
        if befValue == curValue:
            continue
        changeAttrList.append([i, curValue])
        attrList[i] = curValue # 更新记录的值
    if not changeAttrList:
        return CommFunc.WriteBYTE(data, 0)
    count = len(changeAttrList)
    GameWorld.DebugLog("变更的玩家属性个数: %s" % count)
    data = CommFunc.WriteBYTE(data, count)
    for index, curValue in changeAttrList:
        data = CommFunc.WriteBYTE(data, index)
        data = CommFunc.WriteDWORD(data, curValue)
        GameWorld.DebugLog("    index=%s,value=%s" % (index, curValue))
    return data
def __ReadSyncPlayerAttrData(curPlayer, pdata, pos):
    ## 读取同步的玩家属性
    pdata = base64.b64decode(pdata)
    count, pos = CommFunc.ReadBYTE(pdata, pos)
    GameWorld.DebugLog("变更的玩家属性个数: %s" % count)
    for _ in range(count):
        index, pos = CommFunc.ReadBYTE(pdata, pos)
        value, pos = CommFunc.ReadDWORD(pdata, pos)
        CrossFightPowerAttrList[index][1](curPlayer, value) # 设置更新值
        GameWorld.DebugLog("    index=%s,value=%s" % (index, value))
    return pos
def __WriteSyncPlayerDictData(curPlayer, data):
    ## 写入需要同步的玩家字典
    playerID = curPlayer.GetPlayerID()
    if playerID not in PyGameData.g_crossPlayerDictChangeInfo:
        return CommFunc.WriteBYTE(data, 0)
    changeDict = PyGameData.g_crossPlayerDictChangeInfo.pop(playerID)
    count = len(changeDict)
    GameWorld.DebugLog("变更的玩家字典个数: %s" % count)
    data = CommFunc.WriteWORD(data, count)
    for keyInfo, value in changeDict.items():
        key, dType = keyInfo
        keyLen = len(key)
        data = CommFunc.WriteBYTE(data, keyLen)
        data = CommFunc.WriteString(data, keyLen, key)
        data = CommFunc.WriteDWORD(data, value)
        data = CommFunc.WriteBYTE(data, dType)
        GameWorld.DebugLog("    key=%s, value=%s, dType=%s" % (key, value, dType))
    return data
def __ReadSyncPlayerDictData(curPlayer, pdata, pos):
    ## 读取同步的玩家字典
    pdata = base64.b64decode(pdata)
    count, pos = CommFunc.ReadWORD(pdata, pos)
    GameWorld.DebugLog("变更的玩家字典个数: %s" % count)
    for _ in xrange(count):
        keyLen, pos = CommFunc.ReadBYTE(pdata, pos)
        key, pos = CommFunc.ReadString(pdata, pos, keyLen)
        value, pos = CommFunc.ReadDWORD(pdata, pos)
        dType, pos = CommFunc.ReadBYTE(pdata, pos)
        PlayerControl.NomalDictSetProperty(curPlayer, key, value, dType)
        GameWorld.DebugLog("    key=%s, value=%s, dType=%s" % (key, value, dType))
    return pos