| #!/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  | 
| import ShareDefine  | 
| import md5  | 
| # ·¢Ë͸ñʽ£º ÀàÐÍ+£¨ÊýÁ¿£©+Êý¾Ý  | 
| # Ïò¿ç·þ·¢Ë͵ÄÊý¾ÝÀàÐÍ  | 
| (  | 
| 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())  | 
|         if not pdata:  | 
|             return  | 
|         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.RaiseException('½ÓÊÕ¿ç·þ±ä¸üÍæ¼ÒÊý¾Ý´íÎó \r\n%s' % errorMsg, curPlayer.GetPlayerID())  | 
|     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)  | 
|     PyGameData.g_crossPlayerItemsChangeInfo.pop(playerID, None)  | 
|     PyGameData.g_crossPlayerSkillsChangeInfo.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  | 
|       | 
|     OnPlayerCrossRegItems(curPlayer)     # ÎïÆ·  | 
|     OnPlayerCrossRegSkills(curPlayer)   # ¼¼ÄÜ  | 
|     return  | 
|   | 
| # ÎïÆ·Êý¾Ý¸üР | 
| def OnPlayerCrossRegItems(curPlayer):  | 
|     # Ó°ÏìÕ½Á¦µÄÎïÆ·£¬Ð¹¦ÄÜ×¢ÒâÌí¼Ó£¬Ï´ÎÐèÒª¼ÓÉÏÖïÏÉËþ  | 
|     PyGameData.g_crossPlayerItemsChangeInfo[curPlayer.GetPlayerID()] = GetPlayerCrossRegItems(curPlayer)  | 
|       | 
|     return  | 
|   | 
| def GetPlayerCrossRegItems(curPlayer):  | 
|     itemsDict = {}  | 
|     # Ó°ÏìÕ½Á¦µÄÎïÆ·£¬Ð¹¦ÄÜ×¢ÒâÌí¼Ó£¬Ï´ÎÐèÒª¼ÓÉÏÖïÏÉËþ  | 
|       | 
|     packList = [IPY_GameWorld.rptEquip, ShareDefine.rptPet, ShareDefine.rptDogzEquip]  | 
|     for packIndex in packList:  | 
|         curPack = curPlayer.GetItemManager().GetPack(packIndex)  | 
|         for i in range(curPack.GetCount()):  | 
|             curItem = curPack.GetAt(i)  | 
|             if not curItem or curItem.IsEmpty():  | 
|                 continue  | 
|               | 
|             itemMark = (curItem.GetItemPlaceType(), curItem.GetItemPlaceIndex())  | 
|             itemsDict[itemMark] = md5.md5(curItem.GetB64ItemData()).hexdigest()  | 
|       | 
|     return itemsDict  | 
|   | 
| # ¼¼ÄÜÊý¾Ý¸üР | 
| def OnPlayerCrossRegSkills(curPlayer):  | 
|     PyGameData.g_crossPlayerSkillsChangeInfo[curPlayer.GetPlayerID()] = GetPlayerCrossRegSkills(curPlayer)  | 
|       | 
| def GetPlayerCrossRegSkills(curPlayer):  | 
|     skills = []  | 
|     skillManager = curPlayer.GetSkillManager()  | 
|     for i in range(0 , skillManager.GetSkillCount()):  | 
|         curSkill = skillManager.GetSkillByIndex(i)  | 
|         skills.append(curSkill.GetSkillID())  | 
|           | 
|     return skills  | 
| #===============================================================================  | 
| # def test(curPlayer):  | 
| #    curPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)  | 
| #    curItem = curPack.GetAt(1)  | 
| #    curItem.GetB64ItemData()  | 
| #    curSingleItem = GameWorld.GetItemFactory().AddItem(curItem.GetB64ItemData())  | 
| #    if not curSingleItem:  | 
| #        return  | 
| #      | 
| #    curItem2 = curPack.GetAt(2)  | 
| #    curItem2.AssignItem(curSingleItem)  | 
| #===============================================================================  | 
|       | 
| 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 SendMergePlayerDataNow(curPlayer):  | 
|     ## ÂíÉÏͬ²½Ò»´ÎÍæ¼ÒÊý¾Ýµ½¿ç·þ MergeData_Player  | 
|     GameWorld.DebugLog("SendMergePlayerDataNow")  | 
|     ProcessCrossPlayer(curPlayer, 0)  | 
|     return  | 
|   | 
| def ProcessCrossPlayer(curPlayer, tick):  | 
|     ## ¿ç·þ״̬µÄ±¾·þÍæ¼Ò´¦Àí  | 
|     if not IsNeedProcessCrossPlayer(curPlayer):  | 
|         return  | 
|       | 
|     playerID = curPlayer.GetPlayerID()  | 
|     # tick ´«0ʱ²»¼ì²éCD£¬Á¢¼´Í¬²½  | 
|     if tick:  | 
|         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, None)  | 
|     GameWorld.DebugLog("¿ªÊ¼Í¬²½±¾·þ±ä¸üµÄÊôÐÔ...", playerID)  | 
|       | 
|     try:  | 
|         # ÕâÀïÖ»×ö¿ÉÄÜÒýÆðÕ½Á¦±ä»¯ËùÐèҪͬ²½µÄÊý¾Ý  | 
|         data = ""  | 
|         data = CommFunc.WriteBYTE(data, MergeData_Player)  | 
|         data = __WriteSyncPlayerAttrData(curPlayer, data) # Íæ¼ÒÊôÐÔ  | 
|         data = __WriteSyncPlayerDictData(curPlayer, data) # ×Öµä  | 
|         data = __WriteSyncPlayerDienstgradData(curPlayer, data) # ³ÆºÅ  | 
|         data = __WriteSyncPlayerItems(curPlayer, data)# ÎïÆ·  | 
|         data = __WriteSyncPlayerSkills(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) # ³ÆºÅ  | 
|     pos = __ReadSyncPlayerItems(curPlayer, pdata, pos)  # ÎïÆ·  | 
|     pos = __ReadSyncPlayerSkills(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)  | 
|         if index >= len(CrossFightPowerAttrList):  | 
|             break  | 
|         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  | 
|   | 
| def __WriteSyncPlayerItems(curPlayer, data):  | 
|     ## Ð´ÈëÐèҪͬ²½µÄÍæ¼ÒÎïÆ·£¬°üº¬É¾³ý  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     if playerID not in PyGameData.g_crossPlayerItemsChangeInfo:  | 
|         data = CommFunc.WriteBYTE(data, 0)  # É¾³ý  | 
|         data = CommFunc.WriteBYTE(data, 0)  # Ôö¸Ä  | 
|         return data  | 
|     lastItems = PyGameData.g_crossPlayerItemsChangeInfo[playerID]  | 
|     # ¶Ô±ÈÊý¾ÝÇø·ÖÔö¸ÄºÍɾ³ý  | 
|     nowItems = GetPlayerCrossRegItems(curPlayer)  | 
|       | 
|     delItems = []  | 
|     addItems = []  | 
|     # --ɾ³ýÎïÆ·  | 
|     for indexs in lastItems:  | 
|         if indexs not in nowItems:  | 
|             delItems.append(indexs)  | 
|       | 
|     data = CommFunc.WriteBYTE(data, len(delItems))  # É¾³ýÊýÁ¿    | 
|     for indexs in delItems:  | 
|         data = CommFunc.WriteBYTE(data, indexs[0])  | 
|         data = CommFunc.WriteBYTE(data, indexs[1])  | 
|           | 
|     # --Ìí¼ÓÐÞ¸ÄÎïÆ·  | 
|     for indexs in nowItems:  | 
|         if indexs not in lastItems:  | 
|             addItems.append(indexs)  | 
|         elif lastItems[indexs] != nowItems[indexs]:  | 
|             addItems.append(indexs)  | 
|               | 
|     tmpData = ""  | 
|     cnt = 0  | 
|     for indexs in addItems:  | 
|         curPack = curPlayer.GetItemManager().GetPack(indexs[0])  | 
|         curItem = curPack.GetAt(indexs[1])  | 
|         if not curItem or curItem.IsEmpty():  | 
|             continue  | 
|         itemData = base64.b64decode(curItem.GetB64ItemData())  | 
|         tmpData = CommFunc.WriteWORD(tmpData, len(itemData))    # ÎïÆ·Êý¾Ý³¤¶È  | 
|         tmpData = CommFunc.WriteString(tmpData, len(itemData), itemData)  | 
|         cnt += 1  | 
|       | 
|     data = CommFunc.WriteBYTE(data, cnt)  # Ôö¸ÄÊýÁ¿    | 
|     data += tmpData  | 
|       | 
|     # Í¬²½×îÐÂÎïÆ·Êý¾Ý  | 
|     PyGameData.g_crossPlayerItemsChangeInfo[playerID] = nowItems  | 
|     return data  | 
|   | 
| def __ReadSyncPlayerItems(curPlayer, pdata, pos):  | 
|     ## ¶Áȡͬ²½µÄÍæ¼ÒÎïÆ·  | 
|     pdata = base64.b64decode(pdata)  | 
|     count, pos = CommFunc.ReadBYTE(pdata, pos)  | 
|     GameWorld.DebugLog("ɾ³ýµÄÍæ¼ÒÎïÆ·¸öÊý: %s" % count)  | 
|       | 
|     # É¾³ýÎïÆ·  | 
|     for _ in xrange(count):  | 
|         packType, pos = CommFunc.ReadBYTE(pdata, pos)  | 
|         itemIndex, pos = CommFunc.ReadBYTE(pdata, pos)  | 
|         curPack = curPlayer.GetItemManager().GetPack(packType)  | 
|         curItem = curPack.GetAt(itemIndex)  | 
|         if not curItem or curItem.IsEmpty():  | 
|             continue  | 
|         curItem.Clear()  | 
|           | 
|           | 
|     # Ôö¸ÄÎïÆ·  | 
|     count, pos = CommFunc.ReadBYTE(pdata, pos)  | 
|     GameWorld.DebugLog("Ôö¸ÄµÄÍæ¼ÒÎïÆ·¸öÊý: %s" % count)  | 
|       | 
|     for _ in xrange(count):  | 
|         #def ReadString(buf, pos, _len):  | 
|         itemDataLen, pos = CommFunc.ReadWORD(pdata, pos)  | 
|         itemData, pos = CommFunc.ReadString(pdata, pos, itemDataLen)  | 
|         curSingleItem = GameWorld.GetItemFactory().AddItem(base64.b64encode(itemData))  | 
|         if not curSingleItem or curSingleItem.GetItemTypeID() == 0:  | 
|             continue  | 
|           | 
|         curPack = curPlayer.GetItemManager().GetPack(curSingleItem.GetItemPlaceType())  | 
|         curItem = curPack.GetAt(curSingleItem.GetItemPlaceIndex())  | 
|         curItem.AssignItem(curSingleItem)  | 
|   | 
|     return pos  | 
|   | 
|   | 
| def __WriteSyncPlayerSkills(curPlayer, data):  | 
|     ## Ð´ÈëÐèҪͬ²½µÄÍæ¼Ò¼¼ÄÜ£¬°üº¬É¾³ý  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     if playerID not in PyGameData.g_crossPlayerSkillsChangeInfo:  | 
|         data = CommFunc.WriteBYTE(data, 0)  # É¾³ý  | 
|         data = CommFunc.WriteBYTE(data, 0)  # Ìí¼Ó  | 
|         return data  | 
|       | 
|     # ¶Ô±ÈÊý¾ÝÇø·ÖÌí¼ÓºÍɾ³ý  | 
|     lastSkills = PyGameData.g_crossPlayerSkillsChangeInfo[playerID]  | 
|     nowSkills = GetPlayerCrossRegSkills(curPlayer)  | 
|       | 
|     delSkills = []  | 
|     # --ɾ³ýÎïÆ·  | 
|     for skillID in lastSkills:  | 
|         if skillID not in nowSkills:  | 
|             delSkills.append(skillID)  | 
|       | 
|     data = CommFunc.WriteBYTE(data, len(delSkills))  # É¾³ýÊýÁ¿    | 
|     for skillID in delSkills:  | 
|         data = CommFunc.WriteDWORD(data, skillID)  | 
|           | 
|     # --Ìí¼ÓÐÞ¸ÄÎïÆ·  | 
|     addSkills = []  | 
|     for skillID in nowSkills:  | 
|         if skillID not in lastSkills:  | 
|             addSkills.append(skillID)  | 
|               | 
|     data = CommFunc.WriteBYTE(data, len(addSkills))  # Ôö¼ÓÊýÁ¿    | 
|     for skillID in addSkills:  | 
|         data = CommFunc.WriteDWORD(data, skillID)  | 
|           | 
|       | 
|     # Í¬²½×îм¼ÄÜÊý¾Ý  | 
|     PyGameData.g_crossPlayerSkillsChangeInfo[playerID] = nowSkills  | 
|     return data  | 
|   | 
| def __ReadSyncPlayerSkills(curPlayer, pdata, pos):  | 
|     ## ¶Áȡͬ²½µÄÍæ¼Ò¼¼ÄÜ  | 
|     skillManager = curPlayer.GetSkillManager()  | 
|     pdata = base64.b64decode(pdata)  | 
|     count, pos = CommFunc.ReadBYTE(pdata, pos)  | 
|     GameWorld.DebugLog("ɾ³ýµÄÍæ¼Ò¼¼ÄܸöÊý: %s" % count)  | 
|       | 
|     # É¾³ý¼¼ÄÜ  | 
|     for _ in xrange(count):  | 
|         skillID, pos = CommFunc.ReadDWORD(pdata, pos)  | 
|         skillManager.DeleteSkillBySkillID(skillID, False)  | 
|   | 
|     count, pos = CommFunc.ReadBYTE(pdata, pos)  | 
|     GameWorld.DebugLog("Ôö¼ÓµÄÍæ¼Ò¼¼ÄܸöÊý: %s" % count)  | 
|       | 
|     # Ìí¼Ó¼¼ÄÜ  | 
|     for _ in xrange(count):  | 
|         skillID, pos = CommFunc.ReadDWORD(pdata, pos)  | 
|         skillManager.LearnSkillByID(skillID, False)  | 
|       | 
|     return pos  | 
|   |