5424 【后端】【1.4】跨服竞技场开发(未同步的PK信息增加存储DB,防止服务器维护后数据丢失)
| | |
| | |
|
| | | return
|
| | |
|
| | | #跨服竞技场未通知玩家的比赛结果,注意该类只处理数据逻辑,功能相关逻辑不要写在该类,不然重读脚本不会生效
|
| | | class CrossPKUnNotifyOverInfoManager(object):
|
| | | |
| | | def __init__(self):
|
| | | self.__unNotifyOverInfoDict = {} # {playerID:tagDBCrossPKUnNotifyOverInfo, ...}
|
| | | return
|
| | | |
| | | def AddUnNotifyOverInfo(self, playerID, overInfoData):
|
| | | self.__unNotifyOverInfoDict[playerID] = overInfoData
|
| | | return
|
| | | |
| | | def GetPlayerUnNotifyOverInfo(self, playerID): return self.__unNotifyOverInfoDict.pop(playerID, None)
|
| | | |
| | | # 保存数据 存数据库和realtimebackup
|
| | | def GetSaveData(self):
|
| | | savaData = ""
|
| | | cntData = ""
|
| | | cnt = 0
|
| | | for overInfoData in self.__unNotifyOverInfoDict.values():
|
| | | cnt += 1
|
| | | savaData += overInfoData.getBuffer()
|
| | | |
| | | GameWorld.Log("SaveDBCrossPKUnNotifyOverInfo cnt :%s" % cnt)
|
| | | return CommFunc.WriteDWORD(cntData, cnt) + savaData
|
| | | |
| | | # 从数据库载入数据
|
| | | def LoadPyGameData(self, datas, pos, dataslen):
|
| | | cnt, pos = CommFunc.ReadDWORD(datas, pos)
|
| | | GameWorld.Log("LoadDBCrossPKUnNotifyOverInfo cnt :%s" % cnt)
|
| | | |
| | | for _ in xrange(cnt):
|
| | | overInfoData = PyGameDataStruct.tagDBCrossPKUnNotifyOverInfo()
|
| | | overInfoData.clear()
|
| | | pos += overInfoData.readData(datas, pos, dataslen)
|
| | | self.__unNotifyOverInfoDict[overInfoData.PlayerID] = overInfoData
|
| | | |
| | | return pos
|
| | | |
| | | def CrossServerMsg_PKOverInfo(playerOverDict):
|
| | | ## 子服接收跨服PK结果信息
|
| | |
|
| | |
| | | player = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
|
| | | if not player or PlayerControl.GetIsTJG(player):
|
| | | GameWorld.Log(" 玩家不在线 或脱机中,先缓存,玩家上线后再同步,playerID=%s" % (playerID))
|
| | | PyGameData.g_crossPKUnNotifyOverInfo[playerID] = sendMapOverInfo
|
| | | overInfoData = PyGameDataStruct.tagDBCrossPKUnNotifyOverInfo()
|
| | | overInfoData.clear()
|
| | | overInfoData.ZoneID = zoneID
|
| | | overInfoData.SeasonID = seasonID
|
| | | overInfoData.RoomID = roomID
|
| | | overInfoData.TimeStr = timeStr
|
| | | overInfoData.OverType = overType
|
| | | overInfoData.PlayerID = playerID
|
| | | overInfoData.WinnerID = winnerID
|
| | | overInfoData.RoundWinnerInfo = str(roundWinnerIDList)
|
| | | overInfoData.RoundWinnerLen = len(overInfoData.RoundWinnerInfo)
|
| | | overInfoData.PKScore = pkScore
|
| | | overInfoData.DanLV = danLV
|
| | | overInfoData.CWinCount = cWinCount
|
| | | overInfoData.AddScore = addScore
|
| | | overInfoData.TagPlayerID = tagPlayerID
|
| | | overInfoData.TagPlayerName = tagPlayerName
|
| | | PyDataManager.GetCrossPKUnNotifyOverInfoManager().AddUnNotifyOverInfo(playerID, overInfoData)
|
| | | continue
|
| | |
|
| | | PlayerControl.SetVsRoomId(player, 0)
|
| | |
| | |
|
| | | def __OnLoginNotifyPKOverInfo(curPlayer):
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | if playerID not in PyGameData.g_crossPKUnNotifyOverInfo:
|
| | | overInfoData = PyDataManager.GetCrossPKUnNotifyOverInfoManager().GetPlayerUnNotifyOverInfo(playerID)
|
| | | if not overInfoData:
|
| | | return
|
| | | overInfo = PyGameData.g_crossPKUnNotifyOverInfo.pop(playerID)
|
| | | PlayerControl.SetCrossRealmState(curPlayer, 0)
|
| | | PlayerControl.SetVsRoomId(curPlayer, 0)
|
| | | sysMsg = str(overInfo)
|
| | | |
| | | zoneID = overInfoData.ZoneID
|
| | | seasonID = overInfoData.SeasonID
|
| | | roomID = overInfoData.RoomID
|
| | | timeStr = overInfoData.TimeStr
|
| | | overType = overInfoData.OverType
|
| | | #playerID = overInfoData.PlayerID
|
| | | winnerID = overInfoData.WinnerID
|
| | | roundWinnerIDList = []
|
| | | try:
|
| | | roundWinnerIDList = eval(overInfoData.RoundWinnerInfo)
|
| | | except:
|
| | | GameWorld.ErrLog("__OnLoginNotifyPKOverInfo roundWinnerIDList eval error! RoundWinnerInfo=%s" % overInfoData.RoundWinnerInfo, playerID)
|
| | | pkScore = overInfoData.PKScore
|
| | | danLV = overInfoData.DanLV
|
| | | cWinCount = overInfoData.CWinCount
|
| | | addScore = overInfoData.AddScore
|
| | | tagPlayerID = overInfoData.TagPlayerID
|
| | | tagPlayerName = overInfoData.TagPlayerName
|
| | | notifyState = 0 # 登录才通知的默认未通知
|
| | | sendMapOverInfo = [roomID, zoneID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, pkScore, danLV, cWinCount, addScore, tagPlayerID, tagPlayerName, notifyState]
|
| | | sysMsg = str(sendMapOverInfo)
|
| | | curPlayer.MapServer_QueryPlayerResult(0, 0, "CrossPKOverInfo", sysMsg, len(sysMsg))
|
| | | GameWorld.Log("玩家上线通知地图未结算的跨服PK结算: mapID=%s,overInfo=%s" % (curPlayer.GetMapID(), overInfo), playerID)
|
| | | GameWorld.Log("玩家上线通知地图未结算的跨服PK结算: roomID=%s,zoneID=%s,seasonID=%s,timeStr=%s,overType=%s,winnerID=%s,roundWinnerIDList=%s, pkScore=%s,danLV=%s,cWinCount=%s,addScore=%s,tagPlayerID=%s,notifyState=%s,mapID=%s" |
| | | % (roomID, zoneID, seasonID, timeStr, overType, winnerID, roundWinnerIDList, pkScore, danLV, cWinCount, addScore, tagPlayerID, notifyState, curPlayer.GetMapID()), playerID)
|
| | | return
|
| | |
|
| | |
|
| | |
| | |
|
| | | class PyGameDataManager(object):
|
| | | def __init__(self):
|
| | | self.crossPKUnNotifyOverInfo = CrossRealmPK.CrossPKUnNotifyOverInfoManager()
|
| | | self.crossPKBillboard = CrossRealmPK.CrossPKBillboardManager()
|
| | | self.XMZZManager = PlayerXMZZ.XMZZManager()
|
| | | self.sealDemonManager = PlayerSealDemon.SealDemonManager()
|
| | |
| | |
|
| | | def GetSaveData(self):
|
| | | buff = ""
|
| | | buff += self.crossPKUnNotifyOverInfo.GetSaveData()
|
| | | buff += self.crossPKBillboard.GetSaveData()
|
| | | buff += self.XMZZManager.GetSaveData()
|
| | | buff += self.sealDemonManager.GetSaveData()
|
| | |
| | | return buff
|
| | |
|
| | | def LoadGameData(self, gameBuffer, pos):
|
| | | pos = self.crossPKUnNotifyOverInfo.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
|
| | | pos = self.crossPKBillboard.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
|
| | | pos = self.XMZZManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
|
| | | pos = self.sealDemonManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
|
| | |
| | | pos = self.socialInfoManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
|
| | | return pos
|
| | |
|
| | | # 跨服竞技场未通知玩家的比赛结果
|
| | | def GetCrossPKUnNotifyOverInfoManager():
|
| | | return PyGameData.g_pyGameDataManager.crossPKUnNotifyOverInfo
|
| | |
|
| | | # 跨服竞技场排行榜管理
|
| | | def GetCrossPKBillboardManager():
|
| | | return PyGameData.g_pyGameDataManager.crossPKBillboard
|
| | |
| | | from ctypes import (Structure, memset, memmove, sizeof, addressof, create_string_buffer, string_at)
|
| | | import CommFunc
|
| | |
|
| | | # 跨服竞技场未通知玩家的比赛结果表 #tagDBCrossPKUnNotifyOverInfo
|
| | | class tagDBCrossPKUnNotifyOverInfo(Structure):
|
| | | _pack_ = 1
|
| | | _fields_ = [
|
| | | ('ZoneID', ctypes.c_ubyte),
|
| | | ('SeasonID', ctypes.c_ubyte),
|
| | | ('RoomID', ctypes.c_ushort),
|
| | | ('TimeStr', ctypes.c_char * 19),
|
| | | ('OverType', ctypes.c_ubyte),
|
| | | ('PlayerID', ctypes.c_ulong),
|
| | | ('WinnerID', ctypes.c_ulong),
|
| | | ('RoundWinnerLen', ctypes.c_ubyte),
|
| | | ('RoundWinnerInfo', ctypes.c_char_p),
|
| | | ('PKScore', ctypes.c_ulong),
|
| | | ('DanLV', ctypes.c_ubyte),
|
| | | ('CWinCount', ctypes.c_ushort),
|
| | | ('AddScore', ctypes.c_ushort),
|
| | | ('TagPlayerID', ctypes.c_ulong),
|
| | | ('TagPlayerName', ctypes.c_char * 33),
|
| | | ('ADOResult', ctypes.c_ulong),
|
| | | ]
|
| | |
|
| | | def __init__(self):
|
| | | Structure.__init__(self)
|
| | | self.clear()
|
| | |
|
| | | def clear(self):
|
| | | self.ZoneID = 0
|
| | | self.SeasonID = 0
|
| | | self.RoomID = 0
|
| | | self.TimeStr = ''
|
| | | self.OverType = 0
|
| | | self.PlayerID = 0
|
| | | self.WinnerID = 0
|
| | | self.RoundWinnerLen = 0
|
| | | self.RoundWinnerInfo = ''
|
| | | self.PKScore = 0
|
| | | self.DanLV = 0
|
| | | self.CWinCount = 0
|
| | | self.AddScore = 0
|
| | | self.TagPlayerID = 0
|
| | | self.TagPlayerName = ''
|
| | |
|
| | | def readData(self, buf, pos = 0, length = 0):
|
| | | if not pos <= length:
|
| | | return -1
|
| | | if len(buf) < pos + self.getLength():
|
| | | return -1
|
| | | self.clear()
|
| | | self.ZoneID, pos = CommFunc.ReadBYTE(buf, pos)
|
| | | self.SeasonID, pos = CommFunc.ReadBYTE(buf, pos)
|
| | | self.RoomID, pos = CommFunc.ReadWORD(buf, pos)
|
| | | self.TimeStr, pos = CommFunc.ReadString(buf, pos, 19)
|
| | | self.OverType, pos = CommFunc.ReadBYTE(buf, pos)
|
| | | self.PlayerID, pos = CommFunc.ReadDWORD(buf, pos)
|
| | | self.WinnerID, pos = CommFunc.ReadDWORD(buf, pos)
|
| | | self.RoundWinnerLen, pos = CommFunc.ReadBYTE(buf, pos)
|
| | | tmp, pos = CommFunc.ReadString(buf, pos, self.RoundWinnerLen)
|
| | | self.RoundWinnerInfo = ctypes.c_char_p(tmp)
|
| | | self.PKScore, pos = CommFunc.ReadDWORD(buf, pos)
|
| | | self.DanLV, pos = CommFunc.ReadBYTE(buf, pos)
|
| | | self.CWinCount, pos = CommFunc.ReadWORD(buf, pos)
|
| | | self.AddScore, pos = CommFunc.ReadWORD(buf, pos)
|
| | | self.TagPlayerID, pos = CommFunc.ReadDWORD(buf, pos)
|
| | | self.TagPlayerName, pos = CommFunc.ReadString(buf, pos, 33)
|
| | | return self.getLength()
|
| | |
|
| | | def getBuffer(self):
|
| | | buf = ''
|
| | | buf = CommFunc.WriteBYTE(buf, self.ZoneID)
|
| | | buf = CommFunc.WriteBYTE(buf, self.SeasonID)
|
| | | buf = CommFunc.WriteWORD(buf, self.RoomID)
|
| | | buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 19, self.TimeStr)
|
| | | buf = CommFunc.WriteBYTE(buf, self.OverType)
|
| | | buf = CommFunc.WriteDWORD(buf, self.PlayerID)
|
| | | buf = CommFunc.WriteDWORD(buf, self.WinnerID)
|
| | | buf = CommFunc.WriteBYTE(buf, self.RoundWinnerLen)
|
| | | buf = CommFunc.WriteString(buf, self.RoundWinnerLen, self.RoundWinnerInfo)
|
| | | buf = CommFunc.WriteDWORD(buf, self.PKScore)
|
| | | buf = CommFunc.WriteBYTE(buf, self.DanLV)
|
| | | buf = CommFunc.WriteWORD(buf, self.CWinCount)
|
| | | buf = CommFunc.WriteWORD(buf, self.AddScore)
|
| | | buf = CommFunc.WriteDWORD(buf, self.TagPlayerID)
|
| | | buf = CommFunc.WriteString(buf, sizeof(ctypes.c_char) * 33, self.TagPlayerName)
|
| | | return buf
|
| | |
|
| | | def getLength(self):
|
| | | length = 0
|
| | | length += sizeof(ctypes.c_ubyte)
|
| | | length += sizeof(ctypes.c_ubyte)
|
| | | length += sizeof(ctypes.c_ushort)
|
| | | length += sizeof(ctypes.c_char) * 19
|
| | | length += sizeof(ctypes.c_ubyte)
|
| | | length += sizeof(ctypes.c_ulong)
|
| | | length += sizeof(ctypes.c_ulong)
|
| | | length += sizeof(ctypes.c_ubyte)
|
| | | length += self.RoundWinnerLen
|
| | | length += sizeof(ctypes.c_ulong)
|
| | | length += sizeof(ctypes.c_ubyte)
|
| | | length += sizeof(ctypes.c_ushort)
|
| | | length += sizeof(ctypes.c_ushort)
|
| | | length += sizeof(ctypes.c_ulong)
|
| | | length += sizeof(ctypes.c_char) * 33
|
| | | return length
|
| | |
|
| | | def outputString(self):
|
| | | output = '''// 跨服竞技场未通知玩家的比赛结果表 #tagDBCrossPKUnNotifyOverInfo:
|
| | | ZoneID = %s,
|
| | | SeasonID = %s,
|
| | | RoomID = %s,
|
| | | TimeStr = %s,
|
| | | OverType = %s,
|
| | | PlayerID = %s,
|
| | | WinnerID = %s,
|
| | | RoundWinnerLen = %s,
|
| | | RoundWinnerInfo = %s,
|
| | | PKScore = %s,
|
| | | DanLV = %s,
|
| | | CWinCount = %s,
|
| | | AddScore = %s,
|
| | | TagPlayerID = %s,
|
| | | TagPlayerName = %s,
|
| | | ADOResult = %s,
|
| | | '''%(
|
| | | self.ZoneID,
|
| | | self.SeasonID,
|
| | | self.RoomID,
|
| | | self.TimeStr,
|
| | | self.OverType,
|
| | | self.PlayerID,
|
| | | self.WinnerID,
|
| | | self.RoundWinnerLen,
|
| | | self.RoundWinnerInfo,
|
| | | self.PKScore,
|
| | | self.DanLV,
|
| | | self.CWinCount,
|
| | | self.AddScore,
|
| | | self.TagPlayerID,
|
| | | self.TagPlayerName,
|
| | | self.ADOResult,
|
| | | )
|
| | | return output
|
| | |
|
| | | #Char数组类型Set接口,使用该接口对此类型数据赋值,防止赋值的数据过长报错
|
| | | def SetTimeStr(self,Str):
|
| | | if len(Str)<=19:
|
| | | self.TimeStr = Str
|
| | | else:
|
| | | self.TimeStr = Str[:19]
|
| | | |
| | | def SetTagPlayerName(self,Str):
|
| | | if len(Str)<=33:
|
| | | self.TagPlayerName = Str
|
| | | else:
|
| | | self.TagPlayerName = Str[:33]
|
| | | |
| | |
|
| | | # 跨服竞技场PK排行榜 #tagDBCrossPKBillboard
|
| | | class tagDBCrossPKBillboard(Structure):
|
| | | _pack_ = 1
|