#!/usr/bin/python
|
# -*- coding: GBK -*-
|
#
|
##@package
|
#
|
# @todo:
|
#
|
# @author: Alee
|
# @date 2019-1-14 ÏÂÎç11:30:12
|
# @version 1.0
|
#
|
# @note:
|
#
|
#---------------------------------------------------------------------
|
import GameWorld
|
import CommFunc
|
import PlayerControl
|
import IPY_GameWorld
|
import BuffSkill
|
import SkillCommon
|
import base64
|
import ChConfig
|
import PyGameData
|
import PlayerDienstgrad
|
import IpyGameDataPY
|
import PlayerHorse
|
import PlayerPet
|
import traceback
|
|
# ·¢Ë͸ñʽ£º ÀàÐÍ+£¨ÊýÁ¿£©+Êý¾Ý
|
# Ïò¿ç·þ·¢Ë͵ÄÊý¾ÝÀàÐÍ
|
(
|
MergeData_Player, # ¶Ô±È´¦Àí
|
MergeData_Item, # ¶Ô±È´¦Àí Ö»ËãÊôÐԵı³°ü ×°±¸ ³èÎï
|
MergeData_Skill, # Ö»´¦ÀíID
|
MergeData_Buff, # ¼´Ê±·¢ËÍ
|
CrossData_PetState, # ¼´Ê±·¢ËÍ ³èÎï³öÕ½
|
CrossData_HorseChange, # ¼´Ê±·¢ËÍ Æï³Ë×øÆï±ä¸ü
|
CrossData_RideHorse, # ¼´Ê±·¢ËÍ ÉÏÏÂÂí
|
) = range(0, 7)
|
|
## дÊý¾ÝÀàÐͶ¨Òå
|
(
|
WDT_BYTE,
|
WDT_WORD,
|
WDT_DWORD,
|
WDT_String,
|
) = range(4)
|
|
CrossDataInfo = {
|
CrossData_PetState:[[WDT_DWORD, WDT_BYTE, WDT_BYTE], lambda curObj, valueList:PlayerPet.CrossServer_DoChangePetState(curObj, valueList)],
|
CrossData_HorseChange:[[WDT_DWORD], lambda curObj, valueList:PlayerHorse.CrossServer_ChangeHorse(curObj, valueList)],
|
CrossData_RideHorse:[[WDT_BYTE], lambda curObj, valueList:PlayerHorse.CrossServer_RideHorse(curObj, valueList)],
|
}
|
|
# Ó°Ïì¿ç·þÕ½Á¦ÊôÐÔÁбí
|
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.GetLV(), lambda curObj, value:curObj.SetLV(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]:
|
# ²»ÐèÒª´¦ÀíµÄbuff
|
return
|
if curPlayer.GetGameObjType() != IPY_GameWorld.gotPlayer:
|
return
|
|
if GameWorld.IsCrossServer():
|
# ·ÇÖ÷·þ
|
return
|
|
if not PlayerControl.GetCrossMapID(curPlayer):
|
# ·Ç¿ç·þÖÐ
|
return
|
|
data = ''
|
data = CommFunc.WriteBYTE(data, MergeData_Buff)
|
data = CommFunc.WriteDWORD(data, buffID)
|
data = CommFunc.WriteBYTE(data, len(plusValueList))
|
for value in plusValueList:
|
data = CommFunc.WriteDWORD(data, value)
|
|
|
#Ö±½ÓÓÃ×Ö½ÚÁ÷»á±¨´í
|
data = base64.b64encode(data)
|
curPlayer.SendMergePlayerData(data)
|
return
|
|
|
# ½ÓÊÕ×Ó·þÍæ¼ÒÊý¾Ý
|
def OnMergePlayerData(index, tick):
|
if not GameWorld.IsCrossServer():
|
# ·Ç¿ç·þ
|
return
|
|
try:
|
# ¿ç·þ·þÎñÆ÷´¦Àí
|
curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
|
pdata = base64.b64decode(curPlayer.GetMergePlayerData())
|
|
pos = 0
|
dataType, pos = CommFunc.ReadBYTE(pdata, pos)
|
if dataType == MergeData_Buff:
|
buffID, pos = CommFunc.ReadDWORD(pdata, pos)
|
curSkill = GameWorld.GetGameData().GetSkillBySkillID(buffID)
|
if not curSkill:
|
return
|
|
plusValueList = []
|
cnt, pos = CommFunc.ReadBYTE(pdata, pos)
|
for i in range(cnt):
|
value, pos = CommFunc.ReadDWORD(pdata, pos)
|
plusValueList.append(value)
|
|
buffType = SkillCommon.GetBuffType(curSkill)
|
BuffSkill.AddBuffNoRefreshState(curPlayer, buffType, curSkill, tick, plusValueList)
|
|
elif dataType == MergeData_Player:
|
__ReadMainServerSyncPlayerData(curPlayer, curPlayer.GetMergePlayerData(), pos)
|
|
else:
|
__ReadCrossData(curPlayer, dataType, curPlayer.GetMergePlayerData(), pos)
|
|
except BaseException:
|
errorMsg = str(traceback.format_exc())
|
GameWorld.ErrLog('½ÓÊÕ¿ç·þ±ä¸üÍæ¼ÒÊý¾Ý´íÎó - > %s' % errorMsg, curPlayer.GetPlayerID())
|
if GameWorld.GetGameWorld().GetDebugLevel():
|
raise Exception(errorMsg)
|
|
return
|
|
## ----------------------------------------------------------------------------------------------
|
|
def SendDataToCrossServer(curPlayer, dataType, dataList):
|
## ͨÓõĸù¾ÝÀàÐÍÏò¿ç·þ·¢ËÍÊý¾Ý
|
if dataType not in CrossDataInfo:
|
return
|
|
if not IsNeedProcessCrossPlayer(curPlayer):
|
return
|
|
dataInfo = CrossDataInfo[dataType][0]
|
if len(dataList) != len(dataInfo):
|
return
|
|
data = ''
|
data = CommFunc.WriteBYTE(data, dataType)
|
for i, wDType in enumerate(dataInfo):
|
value = dataList[i]
|
if wDType == WDT_BYTE:
|
data = CommFunc.WriteBYTE(data, value)
|
elif wDType == WDT_WORD:
|
data = CommFunc.WriteWORD(data, value)
|
elif wDType == WDT_DWORD:
|
data = CommFunc.WriteDWORD(data, value)
|
elif wDType == WDT_String:
|
sLen = len(value)
|
data = CommFunc.WriteBYTE(data, sLen)
|
data = CommFunc.WriteString(data, sLen, value)
|
|
#Ö±½ÓÓÃ×Ö½ÚÁ÷»á±¨´í
|
data = base64.b64encode(data)
|
curPlayer.SendMergePlayerData(data)
|
GameWorld.DebugLog("·¢ËÍÊý¾Ýµ½¿ç·þ·þÎñÆ÷: dataType=%s,dataList=%s" % (dataType, dataList), curPlayer.GetPlayerID())
|
return
|
|
def __ReadCrossData(curPlayer, dataType, pdata, pos):
|
if dataType not in CrossDataInfo:
|
return
|
dataInfo, callFunc = CrossDataInfo[dataType]
|
|
if not callFunc:
|
return
|
|
dataList = []
|
pdata = base64.b64decode(pdata)
|
|
for wDType in dataInfo:
|
if wDType == WDT_BYTE:
|
value, pos = CommFunc.ReadBYTE(pdata, pos)
|
elif wDType == WDT_WORD:
|
value, pos = CommFunc.ReadWORD(pdata, pos)
|
elif wDType == WDT_DWORD:
|
value, pos = CommFunc.ReadDWORD(pdata, pos)
|
elif wDType == WDT_String:
|
sLen, pos = CommFunc.ReadBYTE(pdata, pos)
|
value, pos = CommFunc.ReadString(pdata, pos, sLen)
|
else:
|
continue
|
dataList.append(value)
|
|
GameWorld.DebugLog("ÊÕµ½Ö÷·þÊý¾Ý: dataType=%s,dataList=%s" % (dataType, dataList), curPlayer.GetPlayerID())
|
callFunc(curPlayer, dataList)
|
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
|
|
if not IpyGameDataPY.GetFuncCfg("CrossSyncPlayerData", 1):
|
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)
|
PyGameData.g_crossPlayerDienstgradChangeInfo.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 OnDienstgradChange(curPlayer, dienstgradID, state):
|
## ³ÆºÅ±ä¸ü
|
if not IsNeedProcessCrossPlayer(curPlayer):
|
return
|
playerID = curPlayer.GetPlayerID()
|
dienstgradStateDict = PyGameData.g_crossPlayerDienstgradChangeInfo.get(playerID, {})
|
dienstgradStateDict[dienstgradID] = state
|
PyGameData.g_crossPlayerDienstgradChangeInfo[playerID] = dienstgradStateDict
|
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 < IpyGameDataPY.GetFuncCfg("CrossSyncPlayerData", 1) * 1000:
|
return
|
PyGameData.g_crossSyncTickDict.pop(playerID)
|
GameWorld.DebugLog("¿ªÊ¼Í¬²½±¾·þ±ä¸üµÄÊôÐÔ...", playerID)
|
|
try:
|
# ÕâÀïÖ»×ö¿ÉÄÜÒýÆðÕ½Á¦±ä»¯ËùÐèҪͬ²½µÄÊý¾Ý
|
data = ""
|
data = CommFunc.WriteBYTE(data, MergeData_Player)
|
data = __WriteSyncPlayerAttrData(curPlayer, data) # Íæ¼ÒÊôÐÔ
|
data = __WriteSyncPlayerDictData(curPlayer, data) # ×Öµä
|
data = __WriteSyncPlayerDienstgradData(curPlayer, data) # ³ÆºÅ
|
# ÎïÆ·
|
|
# ¼¼ÄÜ
|
|
#Ö±½ÓÓÃ×Ö½ÚÁ÷»á±¨´í
|
data = base64.b64encode(data)
|
curPlayer.SendMergePlayerData(data)
|
except BaseException:
|
errorMsg = str(traceback.format_exc())
|
GameWorld.ErrLog('´ò°ü¿ç·þ±ä¸üÍæ¼ÒÊý¾Ý´íÎó - > %s' % errorMsg, curPlayer.GetPlayerID())
|
if GameWorld.GetGameWorld().GetDebugLevel():
|
raise Exception(errorMsg)
|
|
return
|
|
def __ReadMainServerSyncPlayerData(curPlayer, pdata, pos):
|
## ¶ÁÈ¡×Ó·þͬ²½µÄÍæ¼ÒÕ½Á¦±ä¸üÏà¹ØÊôÐÔ
|
|
GameWorld.DebugLog("ÊÕµ½×Ó·þͬ²½µÄÍæ¼Ò±ä¸üÊý¾Ý:", curPlayer.GetPlayerID())
|
|
pos = __ReadSyncPlayerAttrData(curPlayer, pdata, pos) # Íæ¼ÒÊôÐÔ
|
pos = __ReadSyncPlayerDictData(curPlayer, pdata, pos) # ×Öµä
|
pos = __ReadSyncPlayerDienstgradData(curPlayer, pdata, pos) # ³ÆºÅ
|
# ÎïÆ·
|
|
# ¼¼ÄÜ
|
|
# ǿˢһ´ÎÊôÐÔ
|
PlayerControl.PlayerControl(curPlayer).ReCalcAllState()
|
return
|
|
def __WriteSyncPlayerAttrData(curPlayer, data):
|
## дÈëÐèҪͬ²½µÄÍæ¼ÒÊôÐÔ
|
|
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.WriteWORD(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
|
|
def __WriteSyncPlayerDienstgradData(curPlayer, data):
|
## дÈëÐèҪͬ²½µÄÍæ¼Ò³ÆºÅ
|
playerID = curPlayer.GetPlayerID()
|
if playerID not in PyGameData.g_crossPlayerDienstgradChangeInfo:
|
return CommFunc.WriteBYTE(data, 0)
|
changeDienstgradDict = PyGameData.g_crossPlayerDienstgradChangeInfo.pop(playerID)
|
|
count = len(changeDienstgradDict)
|
GameWorld.DebugLog("±ä¸üµÄÍæ¼Ò³ÆºÅ¸öÊý: %s" % count)
|
data = CommFunc.WriteBYTE(data, count)
|
for dienstgradID, state in changeDienstgradDict.items():
|
data = CommFunc.WriteDWORD(data, dienstgradID)
|
data = CommFunc.WriteBYTE(data, state)
|
GameWorld.DebugLog(" dienstgradID=%s, state=%s" % (dienstgradID, state))
|
|
return data
|
|
def __ReadSyncPlayerDienstgradData(curPlayer, pdata, pos):
|
## ¶Áȡͬ²½µÄÍæ¼Ò³ÆºÅ
|
pdata = base64.b64decode(pdata)
|
count, pos = CommFunc.ReadBYTE(pdata, pos)
|
GameWorld.DebugLog("±ä¸üµÄÍæ¼Ò³ÆºÅ¸öÊý: %s" % count)
|
for _ in xrange(count):
|
dienstgradID, pos = CommFunc.ReadDWORD(pdata, pos)
|
state, pos = CommFunc.ReadBYTE(pdata, pos)
|
GameWorld.DebugLog(" dienstgradID=%s, state=%s" % (dienstgradID, state))
|
if state:
|
PlayerDienstgrad.PlayerAddDienstgrad(curPlayer, dienstgradID, isRefreshAttr=False)
|
else:
|
PlayerDienstgrad.PlayerDelDienstgrad(curPlayer, dienstgradID, False)
|
|
return pos
|
|
|
|
|
|
|