5563 【英文】【BT】跨服服务器维护优化(打包数据改为db自己管理存取)
| | |
| | | # GameWorld.GetGameWorld().SendDBLogic(BYTE queryType, DWORD id, char* sData, int nDataLen)
|
| | | # GameServer请求db逻辑类型,db接受 OnGameServerToDBLogic,回调 RecvDGDBLogicResult
|
| | | (
|
| | | gstDBLogic_PlayerPackData, # 请求打包玩家数据 0
|
| | | ) = range(1)
|
| | | gstDBLogic_PlayerPackDataReq, # 请求打包玩家数据,仅子服用 0
|
| | | gstDBLogic_PlayerPackDataUpd, # 更新打包玩家数据,仅子服用,跨服通过拦截消息处理即可 1
|
| | | gstDBLogic_GMCmd, # 更新打包玩家数据 2
|
| | | ) = range(3)
|
| | |
|
| | | #GM工具回复值
|
| | | Def_GMTool_Succeed = 1
|
| | |
| | | #"""Version = 2024-12-26 17:00"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import ChConfig
|
| | | import ShareDefine
|
| | | import PyDataManager
|
| | | import PlayerPackData
|
| | | import ReadChConfig
|
| | | import PlayerViewCache
|
| | | import GameWorld
|
| | |
|
| | | import base64
|
| | | import random
|
| | | import PyDataManager
|
| | |
|
| | | ## 执行逻辑
|
| | | # @param curPlayer 当前玩家
|
| | | # @param gmList []
|
| | | # @return None
|
| | | def OnExec(curPlayer, gmList):
|
| | | if not gmList:
|
| | | return
|
| | | value = gmList[0]
|
| | | if value == "a":
|
| | | __addFackPackData(gmList[1:])
|
| | | elif value == "d":
|
| | | __delFackPackData()
|
| | | elif value == "p":
|
| | | __printPackData(gmList[1:])
|
| | | return
|
| | | isSendToDB = True
|
| | | return isSendToDB
|
| | |
|
| | | def OnGetMergeParam(curPlayer):
|
| | | return []
|
| | |
| | | return
|
| | |
|
| | | def __addFackPackData(gmList):
|
| | | ## 添加假的打包数据,一般用于开发测试功能用
|
| | | FakeName = "假名字".decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding())
|
| | | packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
|
| | | #GameWorld.DebugAnswer(curPlayer, "添加镜像: PlayerMirror a 个数 [起始ID 战力 区服ID 模版key]")
|
| | | ## 添加假的打包数据,一般用于开发测试功能用,打包数据在db添加,GameServer添加查看缓存
|
| | | #GameWorld.DebugAnswer(None, "跨服GameServer玩家查看数据数:%s" % PyDataManager.GetPlayerViewCachePyManager().GetCount())
|
| | | #return
|
| | | addCount = gmList[0] if len(gmList) > 0 else 1
|
| | | startID = gmList[1] if len(gmList) > 1 else 1
|
| | | fightPower = gmList[2] if len(gmList) > 2 else 0
|
| | | serverID = gmList[3] if len(gmList) > 3 else 0
|
| | | packDataTempKey = gmList[4] if len(gmList) > 4 else ""
|
| | | |
| | | jobFackPackDataDict = ReadChConfig.GetEvalChConfig("FackPackData")
|
| | | #packDataTempKey = gmList[4] if len(gmList) > 4 else ""
|
| | |
|
| | | addOKCount = 0
|
| | | for index in range(addCount):
|
| | | fackID = startID + index
|
| | | if packDataMgr.IsPlayerIn(fackID):
|
| | | curCache = PlayerViewCache.FindViewCache(fackID, True)
|
| | | if not curCache:
|
| | | continue
|
| | | propDict = PlayerViewCache.GetCachePropDataDict(curCache)
|
| | |
|
| | | job = random.randint(1, 2)
|
| | | tempKey = packDataTempKey if packDataTempKey else "job%s" % job
|
| | | if tempKey not in jobFackPackDataDict:
|
| | | GameWorld.DebugAnswer(None, "配置FackPackData.txt没有该模版key:%s" % tempKey)
|
| | | return
|
| | | packDataTeam = jobFackPackDataDict[tempKey]
|
| | | packDataTeamBuff = base64.b64decode(packDataTeam)
|
| | | if serverID:
|
| | | propDict["AccID"] = "fake%s@test@s%s" % (fackID, serverID)
|
| | |
|
| | | tempDBPlayer = PlayerPackData.GetDBPlayerByPackData(packDataTeam)
|
| | | tempDBPlayer.PlayerID = fackID
|
| | | tempDBPlayer.PlayerName = "%s%s" % (FakeName, fackID)
|
| | | curServerID = serverID if serverID else fackID / 100
|
| | | if not curServerID:
|
| | | curServerID = 9999
|
| | | tempDBPlayer.AccID = "fack%s@test@s%s" % (fackID, curServerID)
|
| | | # 没有指定模版,则随机数据
|
| | | if not packDataTempKey:
|
| | | tempDBPlayer.Job = job
|
| | | tempDBPlayer.LV = random.randint(tempDBPlayer.LV, tempDBPlayer.LV + 2)
|
| | | tempDBPlayer.OfficialRank = random.randint(tempDBPlayer.OfficialRank, tempDBPlayer.OfficialRank + 2)
|
| | | if fightPower:
|
| | | propDict["FightPower"] = fightPower + index
|
| | |
|
| | | curFightPower = fightPower if fightPower else (tempDBPlayer.FightPowerEx * ChConfig.Def_PerPointValue + tempDBPlayer.FightPower)
|
| | | curFightPower += index
|
| | | tempDBPlayer.FightPower = curFightPower % ChConfig.Def_PerPointValue
|
| | | tempDBPlayer.FightPowerEx = curFightPower / ChConfig.Def_PerPointValue
|
| | | |
| | | updBuff = tempDBPlayer.getBuffer() + packDataTeamBuff[tempDBPlayer.getLength():]
|
| | | updPackData = base64.b64encode(updBuff)
|
| | | packDataMgr.UpdPlayerPackData(fackID, updPackData)
|
| | | addOKCount += 1
|
| | |
|
| | | packDataMgr.Sort()
|
| | | |
| | | GameWorld.DebugAnswer(None, "添加假玩家打包数据数:%s,总:%s" % (addOKCount, packDataMgr.GetCount()))
|
| | | GameWorld.DebugAnswer(None, "跨服GameServer添加假玩家查看数据数:%s,%s~%s,总:%s" |
| | | % (addOKCount, startID, fackID, PyDataManager.GetPlayerViewCachePyManager().GetCount()))
|
| | | return
|
| | |
|
| | | def __delFackPackData():
|
| | |
|
| | | delCount = 0
|
| | | packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
|
| | | for index in range(packDataMgr.GetCount())[::-1]:
|
| | | packObj = packDataMgr.At(index)
|
| | | if packObj.playerID >= 10000:
|
| | | cacheMgr = PyDataManager.GetPlayerViewCachePyManager()
|
| | | for index in range(cacheMgr.GetCount())[::-1]:
|
| | | viewCache = cacheMgr.At(index)
|
| | | if viewCache.PlayerID >= 10000:
|
| | | continue
|
| | | packDataMgr.DelPlayerPackData(packObj.playerID)
|
| | | cacheMgr.DelPlayerViewCache(viewCache.PlayerID)
|
| | | delCount += 1
|
| | |
|
| | | GameWorld.DebugAnswer(None, "删除假玩家打包数据数:%s,剩:%s" % (delCount, packDataMgr.GetCount()))
|
| | | GameWorld.DebugAnswer(None, "删除假玩家数据数:%s" % delCount)
|
| | | return
|
| | |
|
| | | def __printPackData(gmList):
|
| | | startIndex = gmList[0] if len(gmList) > 0 else 0
|
| | | printCount = gmList[1] if len(gmList) > 1 else 100
|
| | | packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
|
| | | packDataMgr.Sort()
|
| | | dataCount = packDataMgr.GetCount()
|
| | | GameWorld.DebugLog("=== 打包数据总数: dataCount=%s,startIndex=%s" % (dataCount, startIndex))
|
| | | for index in range(startIndex, startIndex + printCount):
|
| | | if index >= dataCount:
|
| | | break
|
| | | packObj = packDataMgr.At(index)
|
| | | playerID = packObj.playerID
|
| | | fightPower = packObj.fightPower
|
| | | serverID = packObj.serverID
|
| | | GameWorld.DebugLog("index=%s,playerID=%s,serverID=%s,fightPower=%s,%s" % (index, playerID, serverID, fightPower, packObj.GetBaseDict()))
|
| | | GameWorld.DebugAnswer(None, "输出完毕详见GameServer日志!总:%s" % (dataCount))
|
| | | GameWorld.DebugAnswer(None, "跨服GameServer缓存条数:%s,打包条数:%s" |
| | | % (PyDataManager.GetPlayerViewCachePyManager().GetCount(), |
| | | PyDataManager.GetDBPlayerPackDataManager().GetCount()
|
| | | ))
|
| | | return
|
| | |
|
| | |
| | | callFunc = GameWorld.GetExecFunc(Commands, "%s.%s"%(callFunName, "OnGetMergeParam"))
|
| | | if callFunc != None:
|
| | | extendParamList = callFunc(curPlayer)
|
| | | CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_GMCMD, alist + extendParamList)
|
| | | CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_GMCMD, {"cmdMsgList":alist + extendParamList})
|
| | |
|
| | | callFunc = GameWorld.GetExecFunc(Commands, "%s.%s"%(callFunName, "OnExec"))
|
| | | if callFunc == None:
|
| | |
| | | GameWorld.DebugAnswer(curPlayer, 'no cmd !!!')
|
| | | return
|
| | |
|
| | | callFunc(curPlayer, alist[1:])
|
| | | isSendToDB = callFunc(curPlayer, alist[1:])
|
| | | if isSendToDB:
|
| | | msg = str(alist)
|
| | | GameWorld.GetGameWorld().SendDBLogic(ChConfig.gstDBLogic_GMCmd, 0, msg, len(msg))
|
| | |
|
| | | except BaseException:
|
| | | GameWorld.DebugAnswer(curPlayer, "执行GM命令错误, 请查看GameServer日志!")
|
| | |
| | | return cmdDict
|
| | |
|
| | | ## 收到子服务器发送的GM命令
|
| | | def ClientServerMsg_GMCMD(cmdMsgList, tick):
|
| | | def ClientServerMsg_GMCMD(msgData, tick):
|
| | | cmdMsgList = msgData["cmdMsgList"]
|
| | | dbAnswerList = msgData.get("dbAnswerList", [])
|
| | | for dbAnswer in dbAnswerList:
|
| | | GameWorld.DebugAnswer(None, dbAnswer)
|
| | | |
| | | if len(cmdMsgList) == 0:
|
| | | return
|
| | |
|
| | |
| | | text = text.decode(ShareDefine.Def_Game_Character_Encoding).encode(GetCharacterEncoding())
|
| | | if curPlayer:
|
| | | curPlayer.DebugAnswer(text)
|
| | | else:
|
| | | playerManager = GetPlayerManager()
|
| | | for i in xrange(playerManager.GetActivePlayerCount()):
|
| | | player = playerManager.GetActivePlayerAt(i)
|
| | | if player == None:
|
| | | continue
|
| | | player.DebugAnswer(text)
|
| | | return
|
| | |
|
| | | def CrossServerMsg_DebugAnswer(msgData):
|
| | |
| | | if not obj or not hasattr(obj, "playerName"):
|
| | | return
|
| | |
|
| | | packDataObj = PyDataManager.GetDBPlayerPackDataManager().GetPlayerPackObj(playerID)
|
| | | # 如果有打包数据,以打包数据为准
|
| | | if packDataObj:
|
| | | obj.accID = packDataObj.accID
|
| | | obj.playerName = packDataObj.playerName
|
| | | obj.job = packDataObj.job
|
| | | obj.lv = packDataObj.lv
|
| | | obj.fightPower = packDataObj.fightPower
|
| | | obj.realmLV = packDataObj.realmLV
|
| | | obj.face = packDataObj.face
|
| | | obj.facePic = packDataObj.facePic
|
| | | return
|
| | | |
| | | if playerID < 10000:
|
| | | if obj.playerName:
|
| | | return
|
| | |
| | | import ChPyNetSendPack
|
| | | import PyGameDataStruct
|
| | | import PlayerDBGSEvent
|
| | | import PlayerViewCache
|
| | | import CrossBillboard
|
| | | import PyDataManager
|
| | | import NetPackCommon
|
| | |
| | | playerID = playerInfoDict["playerID"] # 角色ID
|
| | | fightPower = playerInfoDict["fightPower"]
|
| | | requestType = playerInfoDict.get("requestType", 0)
|
| | | gmMatchIDList = playerInfoDict.get("gmMatchIDList", [])
|
| | |
|
| | | isRefresh = requestType == 1
|
| | | OnRefreshPKMatch(zoneID, seasonID, playerID, fightPower, serverGroupID, isRefresh)
|
| | | OnRefreshPKMatch(zoneID, seasonID, playerID, fightPower, serverGroupID, isRefresh, gmMatchIDList)
|
| | | return
|
| | |
|
| | | def ClientServerMsg_PKOver(serverGroupID, playerInfoDict, tick):
|
| | |
| | |
|
| | | # 通知子服
|
| | | pkScore = updScore
|
| | | packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
|
| | | tagPackObj = packDataMgr.GetPlayerPackObj(tagPlayerID)
|
| | | tagPlayerName = tagPackObj.playerName if tagPackObj else ""
|
| | | tagCacheDict = PlayerViewCache.GetCachePropDataDict(PlayerViewCache.FindViewCache(tagPlayerID))
|
| | | tagPlayerName = tagCacheDict.get("Name", "")
|
| | | winnerID = playerID if isWinner else tagPlayerID
|
| | | timeStr = GameWorld.GetCurrentDataTimeStr()
|
| | | playerOverDict = {}
|
| | |
| | | OnRefreshPKMatch(zoneID, seasonID, playerID, fightPower, serverGroupID, True)
|
| | | return
|
| | |
|
| | | def OnRefreshPKMatch(zoneID, seasonID, playerID, fightPower, serverGroupID, isRefresh):
|
| | | def OnRefreshPKMatch(zoneID, seasonID, playerID, fightPower, serverGroupID, isRefresh, gmMatchIDList=None):
|
| | | # 刷新匹配数据
|
| | | # @param isRefresh: 是否强制重新刷新
|
| | |
|
| | | if isRefresh or playerID not in PyGameData.g_crossPKMatchDict:
|
| | | # 执行匹配逻辑
|
| | | matchIDList = __DoPKMatch(zoneID, seasonID, playerID, fightPower)
|
| | | if matchIDList: # 有新结果才替换
|
| | | PyGameData.g_crossPKMatchDict[playerID] = matchIDList
|
| | | __DoPKMatch(zoneID, seasonID, playerID, fightPower, gmMatchIDList)
|
| | |
|
| | | packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
|
| | | matchIDList = PyGameData.g_crossPKMatchDict.get(playerID, [])
|
| | | matchInfoDict = {}
|
| | | for matchID in matchIDList:
|
| | | packObj = packDataMgr.GetPlayerPackObj(matchID)
|
| | | if not packObj:
|
| | | viewCache = PlayerViewCache.FindViewCache(matchID)
|
| | | if not viewCache:
|
| | | continue
|
| | | matchInfoDict[matchID] = packObj.GetBaseDict()
|
| | | matchInfoDict[matchID] = viewCache.getBuffer()
|
| | |
|
| | | dataMsg = {"playerID":playerID, "matchIDList":matchIDList, "matchInfoDict":matchInfoDict}
|
| | | CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PKMatchReqRet, dataMsg, [serverGroupID])
|
| | | return
|
| | |
|
| | | def __DoPKMatch(zoneID, seasonID, playerID, fightPower):
|
| | | def __DoPKMatch(zoneID, seasonID, playerID, fightPower, gmMatchIDList=None):
|
| | | ## 执行匹配
|
| | |
|
| | | if not IsCrossRealmPKMatchState():
|
| | |
| | | matchIDList[-1] = robotID
|
| | | GameWorld.DebugLog("没有匹配到机器人,概率直接匹配到机器人: robotID=%s" % robotID, playerID)
|
| | |
|
| | | #GM指定匹配
|
| | | if gmMatchIDList:
|
| | | GameWorld.DebugLog("GM指定匹配目标玩家ID: gmMatchIDList=%s" % gmMatchIDList, playerID)
|
| | | for gmMatchID in gmMatchIDList:
|
| | | if matchIDList:
|
| | | matchIDList.pop(0)
|
| | | matchIDList.append(gmMatchID)
|
| | | |
| | | GameWorld.DebugLog("最终匹配结果: matchIDList=%s" % str(matchIDList), playerID)
|
| | | if matchIDList: # 有新结果才替换
|
| | | PyGameData.g_crossPKMatchDict[playerID] = matchIDList
|
| | | return matchIDList
|
| | |
|
| | | def __addRandMatchID(playerID, matchIndex, rankRange, randIDList, matchIDList, loopPlayerIDList, sign):
|
| | | ## 根据所有可循环玩家ID列表,添加对应匹配轮次可随机匹配的玩家
|
| | | packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
|
| | | pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager()
|
| | | indexStart = matchIndex * rankRange
|
| | | indexEnd = indexStart + rankRange - 1
|
| | | loopIDCount = len(loopPlayerIDList)
|
| | |
| | | if dataID in matchIDList:
|
| | | GameWorld.DebugLog(" 不可添加已匹配过玩家: dataID=%s,randIDList=%s,matchIDList=%s" % (dataID, randIDList, matchIDList), playerID)
|
| | | continue
|
| | | if not packDataMgr.IsPlayerIn(dataID):
|
| | | GameWorld.DebugLog(" 不匹配无打包数据玩家: dataID=%s,randIDList=%s" % (dataID, randIDList), playerID)
|
| | | if not pyViewCacheMgr.IsPlayerIn(dataID):
|
| | | GameWorld.DebugLog(" 不匹配无缓存数据玩家: dataID=%s,randIDList=%s" % (dataID, randIDList), playerID)
|
| | | continue
|
| | | randIDList.append(dataID)
|
| | | GameWorld.DebugLog(" 添加可以随机匹配玩家: dataID=%s,randIDList=%s" % (dataID, randIDList), playerID)
|
| | |
| | | crossZoneName = GameWorld.GetCrossZoneName()
|
| | | zoneIpyData = IpyGameDataPY.GetIpyGameData("CrossZonePK", crossZoneName, zoneID)
|
| | | if zoneIpyData:
|
| | | packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
|
| | | packDataMgr.Sort()
|
| | | serverIDList = zoneIpyData.GetServerGroupIDList()
|
| | | zonePackPlayerIDList = packDataMgr.GetPlayerIDListByServerIDInfo(zoneIpyData.GetServerGroupIDList())
|
| | | pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager()
|
| | | zonePackPlayerIDList = pyViewCacheMgr.GetPlayerIDListByServerIDInfo(serverIDList)
|
| | | GameWorld.DebugLog(" 获得赛区活跃打包数据玩家: zoneID=%s,serverIDList=%s,%s,%s"
|
| | | % (zoneID, serverIDList, len(zonePackPlayerIDList), zonePackPlayerIDList), playerID)
|
| | | return zonePackPlayerIDList
|
| | |
| | | matchOKPack.MatchPlayer = []
|
| | | for matchID in matchIDList:
|
| | | matchPlayer = ChPyNetSendPack.tagGCCrossRealmPKMatchPlayer()
|
| | | if matchID not in matchInfoDict:
|
| | | matchPlayer.PlayerID = matchID
|
| | | matchOKPack.MatchPlayer.append(matchPlayer)
|
| | | if matchID not in matchInfoDict:
|
| | | continue
|
| | | matchInfo = matchInfoDict[matchID]
|
| | | matchPlayer.PlayerID = matchInfo["playerID"]
|
| | | matchPlayer.PlayerName = matchInfo["playerName"]
|
| | | cacheBuffer = matchInfoDict[matchID]
|
| | | curCache = PlayerViewCache.ReadCacheBufferToCacheObj(matchID, cacheBuffer)
|
| | | if not curCache:
|
| | | continue
|
| | | PlayerViewCache.Sync_PlayerCache(curPlayer, curCache)
|
| | | cacheDict = PlayerViewCache.GetCachePropDataDict(curCache) |
| | | matchPlayer.PlayerID = matchID
|
| | | matchPlayer.PlayerName = cacheDict.get("Name", "")
|
| | | matchPlayer.NameLen = len(matchPlayer.PlayerName)
|
| | | matchPlayer.Job = matchInfo["job"]
|
| | | matchPlayer.LV = matchInfo["lv"]
|
| | | matchPlayer.RealmLV = matchInfo["realmLV"]
|
| | | matchPlayer.Face = matchInfo["face"]
|
| | | matchPlayer.FacePic = matchInfo["facePic"]
|
| | | matchPlayer.FightPower = matchInfo["fightPower"] % ChConfig.Def_PerPointValue
|
| | | matchPlayer.FightPowerEx = matchInfo["fightPower"] / ChConfig.Def_PerPointValue
|
| | | matchOKPack.MatchPlayer.append(matchPlayer)
|
| | | matchPlayer.Job = cacheDict.get("Job", 1)
|
| | | matchPlayer.LV = cacheDict.get("LV", 1)
|
| | | matchPlayer.RealmLV = cacheDict.get("RealmLV", 0)
|
| | | matchPlayer.Face = cacheDict.get("Face", 0)
|
| | | matchPlayer.FacePic = cacheDict.get("FacePic", 0)
|
| | | matchPlayer.FightPower = cacheDict.get("FightPower", 0) % ChConfig.Def_PerPointValue
|
| | | matchPlayer.FightPowerEx = cacheDict.get("FightPower", 0) / ChConfig.Def_PerPointValue
|
| | | #matchOKPack.MatchPlayer.append(matchPlayer)
|
| | | matchOKPack.MatchPlayerCount = len(matchOKPack.MatchPlayer)
|
| | | NetPackCommon.SendFakePack(curPlayer, matchOKPack)
|
| | | return
|
| | |
| | | import PlayerPackData
|
| | | import IPY_GameServer
|
| | | import ChConfig
|
| | | import GameWorld
|
| | |
|
| | | #-------------------------------------------------------------------------
|
| | |
|
| | |
| | | return
|
| | | queryType = dbResultPack.GetQueryType()
|
| | |
|
| | | if queryType == ChConfig.gstDBLogic_PlayerPackData:
|
| | | if queryType == ChConfig.gstDBLogic_PlayerPackDataReq:
|
| | | mirrorID = dbResultPack.GetID()
|
| | | playerData = dbResultPack.GetResultSet()
|
| | | msgInfo = eval(dbResultPack.GetData())
|
| | | PlayerPackData.OnDBPlayerPackData(mirrorID, playerData, msgInfo)
|
| | |
|
| | | elif queryType == ChConfig.gstDBLogic_GMCmd:
|
| | | dbAnswerList = eval(dbResultPack.GetResultSet())
|
| | | for dbAnswer in dbAnswerList:
|
| | | GameWorld.DebugAnswer(None, dbAnswer)
|
| | | |
| | | return
|
| | |
|
| | |
| | | # 如切磋一下,玩家可以在任意场景对任意本服或跨服玩家发起切磋,与其镜像进行一场友谊PK,纯娱乐
|
| | | # 这种为被动式,即目标玩家可能不存在打包数据表中,需要取拉取
|
| | | #
|
| | | # 由于打包数据较大,影响开关服及备档的速度,还会导致内存不足,故改为db直接管理打包数据获取及入库
|
| | | # GameServer仅保留单次启动后有同步/获取的玩家数据,一般比db少,只保留打包数据信息,玩家基本信息改为从ViewCahce中获取
|
| | | #-------------------------------------------------------------------------------
|
| | | #"""Version = 2024-10-17 15:00"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import CommFunc
|
| | | import GameWorld
|
| | | import PyDataManager
|
| | | import PlayerViewCache
|
| | | import PyGameDataStruct
|
| | | import CrossChampionship
|
| | | import CrossRealmMsg
|
| | | import PlayerControl
|
| | | import ShareDefine
|
| | | import PyGameData
|
| | | import ChConfig
|
| | |
|
| | | import time
|
| | | import base64
|
| | |
|
| | | Def_CahceCountMax = 100 # 最大缓存个数,注:GameServer缓不缓存这个数据都无所谓(改为在db缓存),保留原取数据逻辑不变,暂时缓存个x条,方便本服的直接取
|
| | | TempDBPlayer = PyGameDataStruct.tagDBPlayer()
|
| | |
|
| | | def GetDBPlayerByPackData(packData):
|
| | |
| | | TempDBPlayer.readData(base64.b64decode(packData))
|
| | | return TempDBPlayer
|
| | |
|
| | | class PlayerPackDataObj():
|
| | | |
| | | def __init__(self):
|
| | | self.dbPlayerPackData = None
|
| | | self.playerID = 0
|
| | | self.playerName = ""
|
| | | self.accID = ""
|
| | | self.lv = 0
|
| | | self.job = 0
|
| | | self.realmLV = 0
|
| | | self.face = 0
|
| | | self.facePic = 0
|
| | | self.fightPower = 0
|
| | | self.serverID = 0
|
| | | return
|
| | | |
| | | def GetBaseDict(self):
|
| | | return {"playerID":self.playerID, "playerName":self.playerName, "lv":self.lv, "job":self.job, |
| | | "realmLV":self.realmLV, "face":self.face, "facePic":self.facePic, "fightPower":self.fightPower}
|
| | | |
| | | def UpdPackData(self, packData):
|
| | | if not packData:
|
| | | return
|
| | | if not self.dbPlayerPackData:
|
| | | self.dbPlayerPackData = PyGameDataStruct.tagDBPlayerPackData()
|
| | | self.dbPlayerPackData.PlayerID = self.playerID
|
| | | self.dbPlayerPackData.PackData = packData
|
| | | self.dbPlayerPackData.PackDataSize = len(self.dbPlayerPackData.PackData)
|
| | | self.dbPlayerPackData.UpdTime = int(time.time())
|
| | | self.Unpack()
|
| | | return
|
| | | |
| | | def Unpack(self):
|
| | | if not self.dbPlayerPackData:
|
| | | return
|
| | | dbPlayer = GetDBPlayerByPackData(self.dbPlayerPackData.PackData)
|
| | | self.playerID = dbPlayer.PlayerID
|
| | | self.accID = dbPlayer.AccID
|
| | | self.playerName = dbPlayer.PlayerName
|
| | | self.lv = dbPlayer.LV
|
| | | self.job = dbPlayer.Job
|
| | | self.realmLV = dbPlayer.OfficialRank
|
| | | self.face = dbPlayer.Face
|
| | | self.facePic = dbPlayer.FacePic
|
| | | self.fightPower = dbPlayer.FightPowerEx * ChConfig.Def_PerPointValue + dbPlayer.FightPower
|
| | | self.serverID = GameWorld.GetAccIDServerID(self.accID)
|
| | | return
|
| | | |
| | | def GetPackData(self): return self.dbPlayerPackData.PackData if self.dbPlayerPackData else ""
|
| | | def GetUpdTime(self): return self.dbPlayerPackData.UpdTime if self.dbPlayerPackData else 0
|
| | | |
| | | class DBPlayerPackDataManager():
|
| | | ## 玩家打包数据管理
|
| | | ## 玩家打包数据管理 - 这里仅管理本次启动后的热数据缓存,不入库
|
| | |
|
| | | def __init__(self):
|
| | | self.Clear()
|
| | | return
|
| | |
|
| | | def Clear(self):
|
| | | self.__packDataList = [] # [PlayerPackDataObj, ...]
|
| | | self.__idIndexDict = {} # {playerID:index, ...}
|
| | | self.__needSort = False
|
| | | self.__serverIDRangePlayerIDDict = {} # {serverIDRangeTuple:[playerID, ...], ....}
|
| | | self.__packDataDcit = {} # {playerID:packData, ...}
|
| | | self.__packDataPlayerIDList = [] # [playerID, ...] # 限制缓存数,先进先出
|
| | | return
|
| | |
|
| | | def GetPlayerPackObj(self, playerID, isAddNew=False):
|
| | | packDataObj = None
|
| | | self.__refreshIDIndex()
|
| | | if playerID in self.__idIndexDict:
|
| | | index = self.__idIndexDict[playerID]
|
| | | if index < len(self.__packDataList):
|
| | | packDataObj = self.__packDataList[index]
|
| | | |
| | | if not packDataObj and isAddNew:
|
| | | packDataObj = PlayerPackDataObj()
|
| | | packDataObj.playerID = playerID
|
| | | self.__packDataList.append(packDataObj)
|
| | | self.__idIndexDict[playerID] = len(self.__packDataList) - 1
|
| | | self.__needSort = True
|
| | | |
| | | return packDataObj
|
| | | |
| | | def GetPlayerIDListByServerIDInfo(self, serverIDList):
|
| | | ## 根据服务器ID列表信息获取对应服务器ID范围的玩家ID战力排序列表
|
| | | self.Sort()
|
| | | key = tuple(serverIDList)
|
| | | if key not in self.__serverIDRangePlayerIDDict:
|
| | | playerIDList = []
|
| | | for dataObj in self.__packDataList:
|
| | | playerID = dataObj.playerID
|
| | | serverID = dataObj.serverID
|
| | | for idInfo in serverIDList:
|
| | | if (isinstance(idInfo, int) and serverID == idInfo) \
|
| | | or ((isinstance(idInfo, tuple) or isinstance(idInfo, list)) \
|
| | | and len(idInfo) == 2 and idInfo[0] <= serverID <= idInfo[1]):
|
| | | playerIDList.append(playerID)
|
| | | GameWorld.DebugLog("重新加载区服打包玩家ID列表: %s, %s, %s" % (key, len(playerIDList), playerIDList))
|
| | | self.__serverIDRangePlayerIDDict[key] = playerIDList
|
| | | return self.__serverIDRangePlayerIDDict[key]
|
| | | |
| | | def IsPlayerIn(self, playerID):
|
| | | self.__refreshIDIndex()
|
| | | return playerID in self.__idIndexDict
|
| | | return playerID in self.__packDataDcit
|
| | |
|
| | | def __refreshIDIndex(self):
|
| | | if not self.__idIndexDict:
|
| | | self.__idIndexDict = {}
|
| | | for index, dataObj in enumerate(self.__packDataList):
|
| | | self.__idIndexDict[dataObj.playerID] = index
|
| | | return self.__idIndexDict
|
| | | def GetCount(self): return len(self.__packDataDcit)
|
| | | |
| | | def GetPlayerPackdata(self, playerID):
|
| | | if playerID not in self.__packDataDcit:
|
| | | return ""
|
| | | # 恢复数据热度
|
| | | if playerID in self.__packDataPlayerIDList:
|
| | | self.__packDataPlayerIDList.remove(playerID)
|
| | | self.__packDataPlayerIDList.append(playerID)
|
| | | GameWorld.DebugLog("获取打包数据缓存数更新: %s,%s" % (len(self.__packDataPlayerIDList), self.__packDataPlayerIDList))
|
| | | return self.__packDataDcit[playerID]
|
| | |
|
| | | def UpdPlayerPackData(self, playerID, packData):
|
| | | if not packData:
|
| | | return
|
| | | packObj = self.GetPlayerPackObj(playerID, True)
|
| | | packObj.UpdPackData(packData)
|
| | | self.__needSort = True
|
| | | return packObj
|
| | | |
| | | def DelPlayerPackData(self, playerID):
|
| | | self.__refreshIDIndex()
|
| | | index = self.__idIndexDict.pop(playerID, -1)
|
| | | if index >= 0 and index < len(self.__packDataList):
|
| | | self.__packDataList.pop(index)
|
| | | for playerIDList in self.__serverIDRangePlayerIDDict.values():
|
| | | if playerID in playerIDList:
|
| | | playerIDList.remove(playerID)
|
| | | |
| | | #只要有删除,需重置index映射
|
| | | self.__idIndexDict = {}
|
| | | self.__serverIDRangePlayerIDDict = {}
|
| | | return
|
| | | |
| | | def GetCount(self): return len(self.__packDataList) |
| | | def At(self, index):
|
| | | dataObj = self.__packDataList[index]
|
| | | if not dataObj and False:
|
| | | dataObj = PlayerPackDataObj() # 不会执行到,只为了.出代码提示
|
| | | return dataObj
|
| | | |
| | | def Sort(self):
|
| | | ## 默认按战力倒序排
|
| | | if not self.__needSort:
|
| | | return
|
| | | self.__needSort = False
|
| | | self.__packDataList.sort(key=lambda d: (d.fightPower), reverse=True)
|
| | | self.__idIndexDict = {}
|
| | | self.__serverIDRangePlayerIDDict = {}
|
| | | self.__refreshIDIndex()
|
| | | return
|
| | | |
| | | # 保存数据 存数据库和realtimebackup
|
| | | def GetSaveData(self):
|
| | | savaData = ""
|
| | | cntData = ""
|
| | | cnt = 0
|
| | | |
| | | for index in xrange(self.GetCount()):
|
| | | dataObj = self.At(index)
|
| | | if not dataObj.dbPlayerPackData:
|
| | | continue
|
| | | cnt += 1
|
| | | savaData += dataObj.dbPlayerPackData.getBuffer()
|
| | | if cnt >= 10:
|
| | | break
|
| | | |
| | | GameWorld.Log("Save DBPlayerPackData count :%s len=%s" % (cnt, len(savaData)))
|
| | | return CommFunc.WriteDWORD(cntData, cnt) + savaData
|
| | | |
| | | # 从数据库载入数据
|
| | | def LoadPyGameData(self, datas, pos, dataslen):
|
| | | cnt, pos = CommFunc.ReadDWORD(datas, pos)
|
| | | GameWorld.Log("Load DBPlayerPackData count :%s" % cnt)
|
| | | |
| | | self.Clear()
|
| | | |
| | | for _ in xrange(cnt):
|
| | | dbData = PyGameDataStruct.tagDBPlayerPackData()
|
| | | pos += dbData.readData(datas, pos, dataslen)
|
| | | playerID = dbData.PlayerID
|
| | | |
| | | packObj = self.GetPlayerPackObj(playerID, True)
|
| | | packObj.dbPlayerPackData = dbData
|
| | | packObj.Unpack()
|
| | | |
| | | self.Sort()
|
| | | return pos
|
| | |
|
| | | def IsSaveDB(packDataObj):
|
| | | ## 是否入库
|
| | | if not packDataObj:
|
| | | return False
|
| | | |
| | | playerID = packDataObj.playerID
|
| | | |
| | | if CrossChampionship.IsChampionshipPlayer(playerID):
|
| | | return True
|
| | | |
| | | #跨服榜单上的默认保留
|
| | | if GameWorld.IsCrossServer():
|
| | | billboardMgr = PyDataManager.GetCrossBillboardManager()
|
| | | for billboardType in ShareDefine.CrossBillboardTypeList:
|
| | | groupList = billboardMgr.GetBillboardGroupList(billboardType)
|
| | | for billboardType, groupValue1, groupValue2 in groupList:
|
| | | billboardObj = billboardMgr.GetCrossBillboard(billboardType, groupValue1, groupValue2)
|
| | | if billboardObj.FindByID(playerID):
|
| | | return True
|
| | | |
| | | else:
|
| | | pass
|
| | | # NeedCheckBillBoardType = IpyGameDataPY.GetFuncEvalCfg("PlayerViewCache", 2)
|
| | | # #校验玩家是否上排行榜
|
| | | # billboardMgr = GameWorld.GetBillboard()
|
| | | # for BillBoardType in NeedCheckBillBoardType:
|
| | | # curBillboard = billboardMgr.FindBillboard(BillBoardType)
|
| | | # if not curBillboard:
|
| | | # continue
|
| | | # if curBillboard.FindByID(playerID):
|
| | | # return True
|
| | | |
| | | # 以上是相关功能需要用到的数据,必定不能删除的
|
| | | |
| | | maxDays = 7 # 默认7天
|
| | | MaxTime = maxDays * 3600 * 24
|
| | | curTime = int(time.time())
|
| | | passTime = curTime - packDataObj.GetUpdTime()
|
| | | if passTime < MaxTime:
|
| | | return True
|
| | | |
| | | return False
|
| | |
|
| | | def DelOutofTimePackData():
|
| | | ## 删除过期
|
| | | |
| | | packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
|
| | | for index in range(packDataMgr.GetCount())[::-1]: # 可能删数据,倒序遍历
|
| | | packDataObj = packDataMgr.At(index)
|
| | | if IsSaveDB(packDataObj):
|
| | | continue
|
| | | packDataMgr.DelPlayerPackData(packDataObj.playerID)
|
| | | |
| | | self.__packDataDcit[playerID] = packData
|
| | | if playerID in self.__packDataPlayerIDList:
|
| | | # 添加热度,重复更新的不影响热度
|
| | | self.__packDataPlayerIDList.append(playerID)
|
| | | if len(self.__packDataPlayerIDList) > Def_CahceCountMax:
|
| | | delPlayerID = self.__packDataPlayerIDList.pop(0)
|
| | | if delPlayerID in self.__packDataDcit:
|
| | | del self.__packDataDcit[delPlayerID]
|
| | | GameWorld.DebugLog("删除打包数据缓存: delPlayerID=%s" % delPlayerID)
|
| | | GameWorld.DebugLog("添加打包数据缓存数更新: %s,%s" % (len(self.__packDataPlayerIDList), self.__packDataPlayerIDList))
|
| | | return
|
| | |
|
| | | def IsPackDataPlayer(playerID):
|
| | |
| | |
|
| | | # pullFrom 0-跨服拉子服; >0-子服通过跨服拉子服
|
| | | if GameWorld.IsCrossServer():
|
| | | PlayerViewCache.SetNeedViewCache(pullPlayerIDList) # 拉打包数据的时候默认需要缓存数据
|
| | | # 广播给子服拉数据
|
| | | msgInfo["pullFrom"] = 0
|
| | | dataMsg = {"pullPlayerIDList":pullPlayerIDList, "msgInfo":msgInfo}
|
| | |
| | | if not curPlayer:
|
| | | GameWorld.DebugLog("玩家不在线的调用打包db数据! playerID=%s" % (playerID), playerID)
|
| | | data = str(msgInfo)
|
| | | GameWorld.GetGameWorld().SendDBLogic(ChConfig.gstDBLogic_PlayerPackData, playerID, data, len(data))
|
| | | GameWorld.GetGameWorld().SendDBLogic(ChConfig.gstDBLogic_PlayerPackDataReq, playerID, data, len(data))
|
| | | return
|
| | | GameWorld.DebugLog("玩家在线的发给地图打包数据! playerID=%s" % (playerID), playerID)
|
| | | # 在线的转发给地图
|
| | |
| | | ## 收到子服同步的玩家打包数据
|
| | | playerID = msgData["playerID"]
|
| | | packData = msgData["packData"]
|
| | | cacheBase = msgData.get("cacheBase", {})
|
| | | if cacheBase:
|
| | | PlayerViewCache.UpdCrossCacheBase(playerID, cacheBase)
|
| | | PyDataManager.GetDBPlayerPackDataManager().UpdPlayerPackData(playerID, packData)
|
| | |
|
| | | msgInfo = msgData.get("msgInfo", {})
|
| | |
| | |
|
| | | msgInfo = msgData["msgInfo"]
|
| | | pullPlayerIDList = msgData["pullPlayerIDList"]
|
| | | dbPackDataIDList = msgData.get("dbPackDataIDList", []) # db标记的有打包数据的玩家ID
|
| | |
|
| | | otherServerPlayerIDList = []
|
| | | packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
|
| | | for playerID in pullPlayerIDList:
|
| | | packObj = packDataMgr.GetPlayerPackObj(playerID)
|
| | | packData = packDataMgr.GetPlayerPackdata(playerID)
|
| | | # 已经有的数据先推送回去
|
| | | if packObj:
|
| | | GameWorld.DebugLog("跨服有缓存玩家打包数据,直接推给子服! playerID=%s" % playerID)
|
| | | dataMsg = {"playerID":playerID, "packData":packObj.GetPackData(), "msgInfo":msgInfo}
|
| | | if packData or playerID in dbPackDataIDList:
|
| | | GameWorld.DebugLog("跨服GameServer或db有缓存玩家打包数据,直接推给子服! playerID=%s" % playerID)
|
| | | dataMsg = {"playerID":playerID, "packData":packData, "msgInfo":msgInfo}
|
| | | CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PushPlayerPackData, dataMsg, [serverGroupID])
|
| | | else:
|
| | | otherServerPlayerIDList.append(playerID)
|
| | |
|
| | | # 还没有数据的,广播给其他子服拉数据
|
| | | if otherServerPlayerIDList:
|
| | | PlayerViewCache.SetNeedViewCache(otherServerPlayerIDList) # 拉打包数据的时候默认需要缓存数据
|
| | | dataMsg = {"pullPlayerIDList":otherServerPlayerIDList, "msgInfo":msgInfo}
|
| | | CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PullPlayerPackData, dataMsg)
|
| | |
|
| | |
| | |
|
| | | packDataMgr = PyDataManager.GetDBPlayerPackDataManager()
|
| | | for playerID in pullPlayerIDList:
|
| | | packObj = packDataMgr.GetPlayerPackObj(playerID)
|
| | | if packObj:
|
| | | packData = packDataMgr.GetPlayerPackdata(playerID)
|
| | | if packData:
|
| | | GameWorld.DebugLog("本服有缓存玩家打包数据,直接推给跨服! playerID=%s" % playerID)
|
| | | dataMsg = {"playerID":playerID, "packData":packObj.GetPackData(), "msgInfo":msgInfo}
|
| | | dataMsg = {"playerID":playerID, "packData":packData, "msgInfo":msgInfo}
|
| | | CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PlayerPackData, dataMsg)
|
| | | else:
|
| | | DoPullPlayerPackData(playerID, msgInfo)
|
| | |
| | | if not packDataSyncState or not packData:
|
| | | return
|
| | |
|
| | | # 本服需要,先更新数据
|
| | | if packDataSyncState&pow(2, 0):
|
| | | # 本服需要,先更新数据;跨服需要则也默认本服需要
|
| | | if packDataSyncState&pow(2, 0) or packDataSyncState&pow(2, 1):
|
| | | PyDataManager.GetDBPlayerPackDataManager().UpdPlayerPackData(playerID, packData)
|
| | | GameWorld.GetGameWorld().SendDBLogic(ChConfig.gstDBLogic_PlayerPackDataUpd, playerID, packData, len(packData))
|
| | |
|
| | | # 跨服需要,同步给跨服,由跨服服务器再进一步处理
|
| | | if packDataSyncState&pow(2, 1):
|
| | | cacheBase = PlayerViewCache.GetSyncCrossCacheBase(curPlayer) if curPlayer else {}
|
| | | dataMsg = {"playerID":playerID, "packData":packData, "cacheBase":cacheBase, "msgInfo":msgInfo}
|
| | | dataMsg = {"playerID":playerID, "packData":packData, "msgInfo":msgInfo}
|
| | | CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PlayerPackData, dataMsg)
|
| | |
|
| | | # 本服需要的功能
|
| | |
| | | requestID = msgInfo["requestID"]
|
| | | mirrorIDList = msgInfo["mirrorIDList"]
|
| | | for mirrorID in mirrorIDList:
|
| | | packObj = packDataMgr.GetPlayerPackObj(mirrorID)
|
| | | if packObj:
|
| | | packDataDict[mirrorID] = packObj.GetPackData()
|
| | | packData = packDataMgr.GetPlayerPackdata(mirrorID)
|
| | | if packData:
|
| | | packDataDict[mirrorID] = packData
|
| | | continue
|
| | | pullPlayerIDList.append(mirrorID)
|
| | |
|
| | |
| | | import CrossRealmMsg
|
| | | import ShareDefine
|
| | | import PyGameData
|
| | | import CommFunc
|
| | | import ChPlayer
|
| | | import ChConfig
|
| | |
|
| | |
| | | import random
|
| | |
|
| | | TempCache = PyGameDataStruct.tagPlayerViewCachePy()
|
| | |
|
| | | #玩家缓存管理,该类只做数据缓存存取,不写功能逻辑,防止重读脚本时功能逻辑脚本不生效
|
| | | class PlayerViewCachePyManager(object):
|
| | | |
| | | def __init__(self):
|
| | | self.__viewCacheList = [] # [tagPlayerViewCachePy, ...]
|
| | | self.__idIndexDict = {} # {playerID:index, ...}
|
| | | self.__needSort = False
|
| | | self.__serverIDRangePlayerIDDict = {} # {serverIDRangeTuple:[playerID, ...], ....}
|
| | | return
|
| | | |
| | | def GetPlayerViewCache(self, playerID):
|
| | | self.__refreshIDIndex()
|
| | | viewCache = None
|
| | | if playerID in self.__idIndexDict:
|
| | | index = self.__idIndexDict[playerID]
|
| | | if index < len(self.__viewCacheList):
|
| | | viewCache = self.__viewCacheList[index]
|
| | | |
| | | return viewCache
|
| | | |
| | | def AddPlayerViewCache(self, playerID, viewCache):
|
| | | self.__refreshIDIndex()
|
| | | if playerID in self.__idIndexDict:
|
| | | return
|
| | | viewCache.PlayerID = playerID
|
| | | self.__viewCacheList.append(viewCache)
|
| | | self.__idIndexDict[playerID] = len(self.__viewCacheList) - 1
|
| | | self.__needSort = True
|
| | | return
|
| | | |
| | | def GetPlayerIDListByServerIDInfo(self, serverIDList):
|
| | | ## 根据服务器ID列表信息获取对应服务器ID范围的玩家ID战力排序列表
|
| | | if serverIDList == None:
|
| | | return []
|
| | | self.Sort()
|
| | | key = tuple(serverIDList)
|
| | | if key not in self.__serverIDRangePlayerIDDict:
|
| | | playerIDList = []
|
| | | for viewCache in self.__viewCacheList:
|
| | | playerID = viewCache.PlayerID
|
| | | cacheDict = GetCachePropDataDict(viewCache)
|
| | | if not cacheDict:
|
| | | continue
|
| | | serverID = GameWorld.GetAccIDServerID(cacheDict["AccID"])
|
| | | for idInfo in serverIDList:
|
| | | if (isinstance(idInfo, int) and serverID == idInfo) \
|
| | | or ((isinstance(idInfo, tuple) or isinstance(idInfo, list)) \
|
| | | and len(idInfo) == 2 and idInfo[0] <= serverID <= idInfo[1]):
|
| | | playerIDList.append(playerID)
|
| | | GameWorld.DebugLog("重新加载区服玩家查看缓存ID列表: %s, %s, %s" % (key, len(playerIDList), playerIDList))
|
| | | self.__serverIDRangePlayerIDDict[key] = playerIDList
|
| | | return self.__serverIDRangePlayerIDDict[key]
|
| | | |
| | | def IsPlayerIn(self, playerID):
|
| | | self.__refreshIDIndex()
|
| | | return playerID in self.__idIndexDict
|
| | | |
| | | def __refreshIDIndex(self):
|
| | | if not self.__idIndexDict:
|
| | | self.__idIndexDict = {}
|
| | | for index, viewCache in enumerate(self.__viewCacheList):
|
| | | self.__idIndexDict[viewCache.PlayerID] = index
|
| | | return self.__idIndexDict
|
| | | |
| | | def DelPlayerViewCache(self, playerID):
|
| | | self.__refreshIDIndex()
|
| | | index = self.__idIndexDict.pop(playerID, -1)
|
| | | if index >= 0 and index < len(self.__viewCacheList):
|
| | | self.__viewCacheList.pop(index)
|
| | | for playerIDList in self.__serverIDRangePlayerIDDict.values():
|
| | | if playerID in playerIDList:
|
| | | playerIDList.remove(playerID)
|
| | | |
| | | self.__idIndexDict = {}
|
| | | self.__serverIDRangePlayerIDDict = {}
|
| | | return
|
| | | |
| | | def GetCount(self): return len(self.__viewCacheList) |
| | | def At(self, index):
|
| | | viewCache = self.__viewCacheList[index]
|
| | | if not viewCache and False:
|
| | | viewCache = PyGameDataStruct.tagPlayerViewCachePy() # 不会执行到,只为了.出代码提示
|
| | | return viewCache
|
| | | |
| | | def Sort(self):
|
| | | ## 默认按战力倒序排
|
| | | if not self.__needSort:
|
| | | return
|
| | | self.__needSort = False
|
| | | self.__viewCacheList.sort(cmp=self.__cmp)
|
| | | self.__idIndexDict = {}
|
| | | self.__serverIDRangePlayerIDDict = {}
|
| | | self.__refreshIDIndex()
|
| | | return
|
| | | |
| | | def __cmp(self, a, b):
|
| | | ## 按战力倒序, cmp模式排序效率较低,如果需要再改为key模式
|
| | | aFightPower = 0
|
| | | cacheDict = GetCachePropDataDict(a)
|
| | | if cacheDict:
|
| | | aFightPower = cacheDict.get("FightPower", 0)
|
| | | |
| | | bFightPower = 0
|
| | | cacheDict = GetCachePropDataDict(b)
|
| | | if cacheDict:
|
| | | bFightPower = cacheDict.get("FightPower", 0)
|
| | | |
| | | return cmp(bFightPower, aFightPower)
|
| | | |
| | | # 保存数据 存数据库和realtimebackup
|
| | | def GetSaveData(self):
|
| | | savaData = ""
|
| | | cntData = ""
|
| | | cnt = 0
|
| | | |
| | | for dbData in self.__viewCacheList:
|
| | | #if dbData.PlayerID < 10000:
|
| | | # 假人玩家不存储
|
| | | # continue
|
| | | cnt += 1
|
| | | savaData += dbData.getBuffer()
|
| | | |
| | | GameWorld.Log("Save PlayerViewCachePy count :%s len=%s" % (cnt, len(savaData)))
|
| | | return CommFunc.WriteDWORD(cntData, cnt) + savaData
|
| | | |
| | | # 从数据库载入数据
|
| | | def LoadPyGameData(self, datas, pos, dataslen):
|
| | | cnt, pos = CommFunc.ReadDWORD(datas, pos)
|
| | | GameWorld.Log("Load PlayerViewCachePy count :%s" % cnt)
|
| | | |
| | | for _ in xrange(cnt):
|
| | | dbData = PyGameDataStruct.tagPlayerViewCachePy()
|
| | | dbData.clear()
|
| | | pos += dbData.readData(datas, pos, dataslen)
|
| | | |
| | | self.AddPlayerViewCache(dbData.PlayerID, dbData)
|
| | | |
| | | self.Sort()
|
| | | return pos
|
| | |
|
| | | def DoOnDayEx():
|
| | | DelOutofTimeViewCacheData()
|
| | |
| | | def DelOutofTimeViewCacheData():
|
| | | ## 删除过期的查看缓存数据
|
| | |
|
| | | PlayerPackData.DelOutofTimePackData()
|
| | | |
| | | pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager()
|
| | | playerViewCachePyDict = pyViewCacheMgr.playerViewCachePyDict
|
| | | for playerID, viewCache in playerViewCachePyDict.items():
|
| | | for index in range(pyViewCacheMgr.GetCount())[::-1]: # 有删除需倒序遍历
|
| | | viewCache = pyViewCacheMgr.At(index)
|
| | | if IsSaveDBViewCache(viewCache):
|
| | | continue
|
| | | playerViewCachePyDict.pop(playerID)
|
| | | pyViewCacheMgr.DelPlayerViewCache(viewCache.PlayerID)
|
| | |
|
| | | PyGameData.g_crossPlayerViewCache = {} # 每日直接清空跨服玩家查看缓存
|
| | | return
|
| | |
| | | def DeleteViewCache(playerID):
|
| | | ## 删除玩家缓存
|
| | | pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager()
|
| | | playerViewCachePyDict = pyViewCacheMgr.playerViewCachePyDict
|
| | | playerViewCachePyDict.pop(playerID, None)
|
| | | pyViewCacheMgr.DelPlayerViewCache(playerID)
|
| | | GameWorld.DebugLog("删除查看缓存!", playerID)
|
| | | return
|
| | |
|
| | | def FindViewCache(playerID, isAddNew=False, newPropData={}):
|
| | | def FindViewCache(playerID, isAddNew=False, newPropData=None):
|
| | | ## 查找玩家缓存
|
| | | # @param newPropData: 新数据初始PropData {}, key: LV,RealmLV,Job,VIPLV,Name,FamilyID,FamilyName,FightPower
|
| | | curCache = None
|
| | | pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager()
|
| | | playerViewCachePyDict = pyViewCacheMgr.playerViewCachePyDict
|
| | | if playerID in playerViewCachePyDict:
|
| | | curCache = playerViewCachePyDict[playerID]
|
| | | curCache = pyViewCacheMgr.GetPlayerViewCache(playerID)
|
| | | if curCache:
|
| | | pass
|
| | | elif isAddNew or playerID < 10000:
|
| | | # 内网测试假玩家
|
| | | if playerID < 10000 and not newPropData:
|
| | | openJobList = IpyGameDataPY.GetFuncEvalCfg("OpenJob", 1)
|
| | | if playerID < 10000:
|
| | | if not newPropData:
|
| | | newPropData = {}
|
| | | fakeName = newPropData.get("Name", "")
|
| | | if not fakeName:
|
| | | fakeName = "神秘道友".decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding())
|
| | | fakeName = "%s%s" % (fakeName, playerID)
|
| | | serverID = playerID % 200 + 1 # 1 ~ 200 服
|
| | | accID = newPropData.get("AccID", "")
|
| | | if not accID:
|
| | | serverID = playerID % 100 + 1 # 1 ~ 100 服
|
| | | accID = "fake%s@test@s%s" % (playerID, serverID)
|
| | | else:
|
| | | serverID = GameWorld.GetAccIDServerID(accID)
|
| | | serverGroupID = serverID
|
| | | if serverID < 50:
|
| | | serverGroupID = serverGroupID / 10 + 1 # 前50服每10服1主服
|
| | | isOnline = True if playerID % 2 == 0 else False
|
| | | olMgr = ChPlayer.GetOnlinePlayerMgr()
|
| | | olMgr.SetOnlineState(playerID, isOnline, serverGroupID)
|
| | | accID = "fake%s@test@s%s" % (playerID, serverID)
|
| | | newPropData = {
|
| | | "AccID":accID, |
| | | "PlayerID":playerID, |
| | | "Name":fakeName, |
| | | "Job":random.choice(openJobList) if openJobList else 1, |
| | | "LV":random.randint(100, 200), |
| | | "RealmLV":random.randint(5, 15),
|
| | | "FightPower":random.randint(1000000, 100000000), |
| | | "ServerGroupID":serverGroupID,
|
| | | }
|
| | | |
| | | job = newPropData.get("Job", 0)
|
| | | if not job:
|
| | | openJobList = IpyGameDataPY.GetFuncEvalCfg("OpenJob", 1)
|
| | | job = random.choice(openJobList) if openJobList else 1
|
| | | lv = newPropData.get("LV", random.randint(100, 200))
|
| | | realmLV = newPropData.get("RealmLV", random.randint(5, 15))
|
| | | fightPower = newPropData.get("FightPower", random.randint(1000000, 100000000))
|
| | | |
| | | newPropData.update({"AccID":accID, "PlayerID":playerID, "Name":fakeName, "Job":job, "LV":lv, |
| | | "RealmLV":realmLV, "FightPower":fightPower, "ServerGroupID":serverGroupID,})
|
| | | curCache = PyGameDataStruct.tagPlayerViewCachePy()
|
| | | curCache.PlayerID = playerID
|
| | | curCache.OffTime = int(time.time())
|
| | | if newPropData:
|
| | | curCache.PropData = json.dumps(newPropData, ensure_ascii=False).replace(" ", "")
|
| | | curCache.PropDataSize = len(curCache.PropData)
|
| | | playerViewCachePyDict[playerID] = curCache
|
| | | pyViewCacheMgr.AddPlayerViewCache(playerID, curCache)
|
| | | return curCache
|
| | |
|
| | | def GetCachePropDataDict(curCache):
|
| | |
| | | "RealmLV":curPlayer.GetOfficialRank(),
|
| | | "Job":curPlayer.GetJob(),
|
| | | "VIPLV":curPlayer.GetVIPLv(),
|
| | | "Name":CrossRealmPlayer.GetCrossPlayerName(curPlayer),
|
| | | "Name":curPlayer.GetName(), # 此处不用跨服名称,如前端需要展示跨服名称,可通过ServerID或AccID取得ServerID展示
|
| | | "Face":curPlayer.GetFace(),
|
| | | "FacePic":curPlayer.GetFacePic(),
|
| | | "FamilyID":curPlayer.GetFamilyID(),
|
| | |
| | | OnQueryPlayerCache(curPlayer, tagPlayerID, isShort=1)
|
| | | return
|
| | |
|
| | | def SetNeedViewCache(playerIDList):
|
| | | ## 设置需要缓存数据,跨服专用
|
| | | if not GameWorld.IsCrossServer():
|
| | | return
|
| | | |
| | | for playerID in playerIDList:
|
| | | curCache = FindViewCache(playerID)
|
| | | if curCache:
|
| | | continue
|
| | | dataMsg = {"tagPlayerID":playerID}
|
| | | CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PullPlayerViewCache, dataMsg)
|
| | | return
|
| | |
|
| | | def OnQueryPlayerCache(curPlayer, tagPlayerID, equipClassLV=0, isShort=0):
|
| | | '''查询玩家缓存,支持直接在本服或跨服查询任意服务器玩家
|
| | | @param tagPlayerID: 目标玩家ID
|
| | |
| | | GameWorld.DebugLog("子服推送的玩家缓存数据为空! playerID=%s" % playerID, serverGroupID)
|
| | | else:
|
| | | curCache = FindViewCache(playerID, True)
|
| | | __updCacheBufferToCacheObj(playerID, cacheBuffer, curCache)
|
| | | ReadCacheBufferToCacheObj(playerID, cacheBuffer, curCache)
|
| | |
|
| | | if not msgInfo:
|
| | | return
|
| | |
| | | Sync_PlayerCache(curPlayer, curCache, equipClassLV, isShort)
|
| | | return
|
| | |
|
| | | def __updCacheBufferToCacheObj(playerID, cacheBuffer, cacheObj):
|
| | | def ReadCacheBufferToCacheObj(playerID, cacheBuffer, cacheObj=None):
|
| | | try:
|
| | | TempCache.clear()
|
| | | setattr(TempCache, "PropDataDict", {})
|
| | | if TempCache.readData(cacheBuffer) == -1:
|
| | | GameWorld.ErrLog("玩家缓存数据readData失败! playerID=%s" % playerID)
|
| | | return
|
| | |
| | | if TempCache.PlayerID != playerID:
|
| | | GameWorld.ErrLog("玩家缓存数据readData后玩家ID不一致! playerID=%s != cachePlayerID=%s" % (playerID, TempCache.PlayerID))
|
| | | return
|
| | | |
| | | if not cacheObj:
|
| | | return TempCache
|
| | |
|
| | | cacheObj.PropDataDict = {} # 每次更新数据时,重置字典缓存,下次获取时重新eval缓存
|
| | | cacheObj.PlayerID = TempCache.PlayerID
|
| | |
| | | setattr(cacheObj, "ItemData%s" % classLV, itemData)
|
| | | setattr(cacheObj, "ItemDataSize%s" % classLV, itemDataSize)
|
| | |
|
| | | return True
|
| | | return cacheObj
|
| | |
|
| | | def CrossServerMsg_ViewPlayerCacheRet(msgData, tick):
|
| | | ## 收到跨服服务器回复的查看玩家信息
|
| | |
| | | curCache = PyGameData.g_crossPlayerViewCache[tagPlayerID][0]
|
| | | else:
|
| | | curCache = PyGameDataStruct.tagPlayerViewCachePy()
|
| | | if __updCacheBufferToCacheObj(tagPlayerID, cacheBuffer, curCache):
|
| | | if ReadCacheBufferToCacheObj(tagPlayerID, cacheBuffer, curCache):
|
| | | PyGameData.g_crossPlayerViewCache[tagPlayerID] = [curCache, tick] # 更新信息
|
| | |
|
| | | curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
|
| | |
| | |
|
| | | def CrossServerMsg_PullPlayerViewCache(msgData):
|
| | | ## 收到跨服服务器拉取玩家玩家缓存数据
|
| | | msgInfo = msgData["msgInfo"]
|
| | | msgInfo = msgData.get("msgInfo", {})
|
| | | tagPlayerID = msgData["tagPlayerID"]
|
| | | DoPullPlayerViewCache(tagPlayerID, msgInfo)
|
| | | return
|
| | |
| | | underList2, aboveList2 = [], [] #大范围
|
| | |
|
| | | pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager()
|
| | | playerViewCachePyDict = pyViewCacheMgr.playerViewCachePyDict
|
| | | for playerID, curCache in playerViewCachePyDict.items():
|
| | | for index in range(pyViewCacheMgr.GetCount()):
|
| | | curCache = pyViewCacheMgr.At(index)
|
| | | playerID = curCache.PlayerID
|
| | | if myPlayerID == playerID:
|
| | | #不和自己pk
|
| | | continue
|
| | |
| | | import PlayerAssist
|
| | | import GameRecData
|
| | | import PlayerRecData
|
| | | import PlayerViewCache
|
| | | import GameWorldMineArea
|
| | | import PyGameDataStruct
|
| | | import PlayerPackData
|
| | |
| | | self.playerAssistDict[PlayerID] = []
|
| | | playerAssistList = self.playerAssistDict[PlayerID]
|
| | | playerAssistList.append(dbData)
|
| | | |
| | | return pos
|
| | | |
| | | #玩家缓存管理,该类只做数据缓存存取,不写功能逻辑,防止重读脚本时功能逻辑脚本不生效
|
| | | class PlayerViewCachePyManager(object):
|
| | | |
| | | def __init__(self):
|
| | | self.playerViewCachePyDict = {} # 玩家缓存 {playerID:tagPlayerViewCachePy, ...}
|
| | | return
|
| | | |
| | | # 保存数据 存数据库和realtimebackup
|
| | | def GetSaveData(self):
|
| | | savaData = ""
|
| | | cntData = ""
|
| | | cnt = 0
|
| | | |
| | | for dbData in self.playerViewCachePyDict.values():
|
| | | if dbData.PlayerID < 10000:
|
| | | # 假人玩家不存储
|
| | | continue
|
| | | cnt += 1
|
| | | savaData += dbData.getBuffer()
|
| | | |
| | | GameWorld.Log("Save PlayerViewCachePy count :%s len=%s" % (cnt, len(savaData)))
|
| | | return CommFunc.WriteDWORD(cntData, cnt) + savaData
|
| | | |
| | | # 从数据库载入数据
|
| | | def LoadPyGameData(self, datas, pos, dataslen):
|
| | | cnt, pos = CommFunc.ReadDWORD(datas, pos)
|
| | | GameWorld.Log("Load PlayerViewCachePy count :%s" % cnt)
|
| | | |
| | | for _ in xrange(cnt):
|
| | | dbData = PyGameDataStruct.tagPlayerViewCachePy()
|
| | | dbData.clear()
|
| | | pos += dbData.readData(datas, pos, dataslen)
|
| | | |
| | | self.playerViewCachePyDict[dbData.PlayerID] = dbData
|
| | |
|
| | | return pos
|
| | |
|
| | |
| | |
|
| | | class PyGameDataManager(object):
|
| | | def __init__(self):
|
| | | self.DBPlayerPackDataManager = PlayerPackData.DBPlayerPackDataManager()
|
| | | self.DBPlayerPackDataManager = PlayerPackData.DBPlayerPackDataManager() # 该表GameServer只做内存处理,不从db取,也不发db入库,由db自行处理
|
| | | self.DBGameRecDataManager = GameRecData.DBGameRecDataManager()
|
| | | self.DBPyFuncTeamManager = PlayerFuncTeam.DBPyFuncTeamManager()
|
| | | self.DBPyFuncTeamMemManager = PlayerFuncTeam.DBPyFuncTeamMemManager()
|
| | |
| | | self.CrossBillboardManager = CrossBillboard.CrossBillboardManager()
|
| | | self.PlayerAssistThanksPyManager = PlayerAssistThanksPyManager()
|
| | | self.PlayerAssistPyManager = PlayerAssistPyManager()
|
| | | self.PlayerViewCachePyManager = PlayerViewCachePyManager()
|
| | | self.PlayerViewCachePyManager = PlayerViewCache.PlayerViewCachePyManager()
|
| | | self.AuctionAttentionManager = AuctionAttentionManager()
|
| | | self.AuctionRecordManager = AuctionRecordManager()
|
| | | self.AuctionItemManager = AuctionItemManager()
|
| | |
| | |
|
| | | def GetSaveData(self):
|
| | | buff = ""
|
| | | buff += self.DBPlayerPackDataManager.GetSaveData()
|
| | | buff += self.DBGameRecDataManager.GetSaveData()
|
| | | buff += self.DBPyFuncTeamManager.GetSaveData()
|
| | | buff += self.DBPyFuncTeamMemManager.GetSaveData()
|
| | |
| | | return buff
|
| | |
|
| | | def LoadGameData(self, gameBuffer, pos):
|
| | | pos = self.DBPlayerPackDataManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
|
| | | pos = self.DBGameRecDataManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
|
| | | pos = self.DBPyFuncTeamManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
|
| | | pos = self.DBPyFuncTeamMemManager.LoadPyGameData(gameBuffer, pos, len(gameBuffer))
|
| | |
| | | import PlayerState
|
| | | import SkillShell
|
| | | import CommFunc
|
| | | import FBCommon
|
| | | import PlayerFB
|
| | | import GameMap
|
| | | import FBLogic
|
| | |
| | | self.stateTick = tick
|
| | | self.stateTickRemain = self.GetStateTickMax()
|
| | | self.SyncFBStepTime(tick)
|
| | | FBCommon.SetFBStep(state, tick)
|
| | | return
|
| | |
|
| | | def CaclStateTick(self, tick):
|
| | |
| | | if not curPlayer or curPlayer.IsEmpty() or not curPlayer.GetMapLoadOK():
|
| | | return
|
| | |
|
| | | fbStep = GameWorld.GetGameFB().GetFBStep()
|
| | | if fbStep != ChConfig.Def_MirrorBatState_Init:
|
| | | GameWorld.ErrLog("镜像战斗该阶段已经不能初始化了! fbStep=%s" % fbStep, curPlayer.GetPlayerID())
|
| | | return
|
| | | |
| | | battle = GetMirrorBattle(curPlayer)
|
| | | if battle:
|
| | | GameWorld.DebugLog("镜像战斗玩家断线重连成功!", curPlayer.GetPlayerID())
|
| | |
| | | GameWorld.DebugAnswer(curPlayer, "更新镜像: PlayerMirror 5")
|
| | | GameWorld.DebugAnswer(curPlayer, "加假数据: PlayerMirror a 个数 [起始ID 战力 区服ID 模版key]")
|
| | | GameWorld.DebugAnswer(curPlayer, "删假数据: PlayerMirror d")
|
| | | GameWorld.DebugAnswer(curPlayer, "输出数据: PlayerMirror p [起始索引 个数 ]")
|
| | | #GameWorld.DebugAnswer(curPlayer, "导入数据: PlayerMirror i 模版key账号")
|
| | | #GameWorld.DebugAnswer(curPlayer, "输出数据: PlayerMirror p [起始索引 个数 ]")
|
| | | GameWorld.DebugAnswer(curPlayer, "多对多阵营分配ID为前后前后即AABB")
|
| | | GameWorld.DebugAnswer(curPlayer, "后台战斗时ID阵营分配为[AABB]")
|
| | | GameWorld.DebugAnswer(curPlayer, "切图战斗时ID阵营分配为[自己ABB]")
|
| | | GameWorld.DebugAnswer(curPlayer, "玩家ID不填时默认自己跟自己打")
|
| | | GameWorld.DebugAnswer(curPlayer, "模版key:在db/TestPackData文件夹下")
|
| | | |
| | | return
|
| | |
|
| | | tick = GameWorld.GetGameWorld().GetTick()
|
| | |
| | | __PrintHelp(curPlayer)
|
| | | return
|
| | |
|
| | | if msgList[0] == "m":
|
| | | gmMatchIDList = msgList[1:]
|
| | | dataMsg = {
|
| | | "requestType":1,
|
| | | "seasonID":GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKSeasonID), # 赛季ID
|
| | | "zoneID":GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_CrossPKZoneID), # PK赛区
|
| | | "playerID":curPlayer.GetPlayerID(),
|
| | | "fightPower":PlayerControl.GetFightPower(curPlayer),
|
| | | "gmMatchIDList":gmMatchIDList,
|
| | | }
|
| | | GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_PKMatch, dataMsg)
|
| | | return
|
| | | |
| | | if msgList[0] == "b":
|
| | | zoneID = msgList[1] if len(msgList) > 1 else 0
|
| | | seasonID = msgList[2] if len(msgList) > 2 else 0
|
| | |
| | | GameWorld.DebugAnswer(curPlayer, "设置数据: SetCrossPK 类型 值")
|
| | | GameWorld.DebugAnswer(curPlayer, "类型:0-积分,2-段位,3-PK次数,4-胜利次数,5-连胜次数,6-连败次数")
|
| | | GameWorld.DebugAnswer(curPlayer, "7-今日PK次数,8-今日胜利次数,9-今日购买次数,10-今日刷新次数")
|
| | | GameWorld.DebugAnswer(curPlayer, "设置历史记录: SetCrossPK 赛季ID 类型 数值")
|
| | | GameWorld.DebugAnswer(curPlayer, "设置历史: SetCrossPK 赛季ID 类型 数值")
|
| | | GameWorld.DebugAnswer(curPlayer, "类型:0-段位,1-名次,2-积分,3-奖励等级")
|
| | | GameWorld.DebugAnswer(curPlayer, "当前连败次数: %s" % curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CrossPK_CLoseCount))
|
| | | GameWorld.DebugAnswer(curPlayer, "设置上榜: SetCrossPK b 分区 赛季 段位 [积分 连胜]")
|
| | | GameWorld.DebugAnswer(curPlayer, "指定匹配: SetCrossPK m [playerID ...]")
|
| | | return
|
| | |
|
| | |
|
| | |
| | | import PlayerControl
|
| | | import IpyGameDataPY
|
| | | import PlayerCrossRealmPK
|
| | | import GameWorldProcess
|
| | | import CrossRealmPlayer
|
| | | import PlayerArena
|
| | | import GameWorld
|
| | |
| | | MirrorAttack.DoPlayerLeaveFB(curPlayer, tick)
|
| | | return
|
| | |
|
| | | ## 副本定时器
|
| | | def OnProcess(tick):
|
| | | fbStep = GameWorld.GetGameFB().GetFBStep()
|
| | |
|
| | | # 等待镜像初始化阶段
|
| | | if fbStep == ChConfig.Def_MirrorBatState_Init:
|
| | | if tick - GameWorld.GetGameFB().GetFBStepTick() < 20 * 1000:
|
| | | return
|
| | | FBCommon.SetFBStep(ChConfig.Def_MirrorBatState_Over, tick)
|
| | | GameWorld.ErrLog("没有等到镜像创建,直接关闭副本!")
|
| | | GameWorldProcess.CloseFB(tick)
|
| | | |
| | | return
|
| | |
|
| | | def CheckPlayersRelation_IsFriend(curPlayer, curTagPlayer):
|
| | | return not CanAttackPlayer(curPlayer, curTagPlayer)
|
| | |
|
New file |
| | |
| | | #!/usr/bin/python
|
| | | # -*- coding: GBK -*-
|
| | | #-------------------------------------------------------------------------------
|
| | | #
|
| | | ##@package PyMongoDataServer.GM.Commands.PlayerMirror
|
| | | #
|
| | | # @todo:玩家镜像数据
|
| | | # @author hxp
|
| | | # @date 2025-03-04
|
| | | # @version 1.0
|
| | | #
|
| | | # 详细描述: 玩家镜像数据
|
| | | #
|
| | | #-------------------------------------------------------------------------------
|
| | | #"""Version = 2025-03-04 16:30"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | from Common import mylog
|
| | | import DBCommon.CommonDefine as CommonDefine
|
| | | from Collections import DataServerPlayerData
|
| | | from LogicProcess import CtrlDBManager
|
| | | from DBCommon import GlobalFunctions
|
| | | import PyGameData
|
| | | import base64
|
| | | import os
|
| | |
|
| | | def OnDBExec(gmList, dbAnswerList):
|
| | | ## db收到GameServer同步的命令处理
|
| | | #mylog.debug("db打包数据: %s" % gmList)
|
| | | dbAnswerList.append("db收到GM命令测试回复")
|
| | | return
|
| | |
|
| | | def OnCrossDBExec(gmList, dbAnswerList):
|
| | | ## 跨服db收到子服同步的命令处理
|
| | | if not gmList:
|
| | | return
|
| | | value = gmList[0]
|
| | | if value == "a":
|
| | | __addFackPackData(gmList[1:], dbAnswerList)
|
| | | elif value == "d":
|
| | | __delFackPackData(dbAnswerList)
|
| | | return
|
| | |
|
| | | def __addFackPackData(gmList, dbAnswerList):
|
| | | ## 添加假的打包数据,一般用于开发测试功能用
|
| | | |
| | | addCount = gmList[0] if len(gmList) > 0 else 1
|
| | | startID = gmList[1] if len(gmList) > 1 else 1
|
| | | #fightPower = gmList[2] if len(gmList) > 2 else 0
|
| | | serverID = gmList[3] if len(gmList) > 3 else 0
|
| | | packDataTempKey = gmList[4] if len(gmList) > 4 else ""
|
| | | |
| | | appPath = GlobalFunctions.getAppPath()
|
| | | fullPath = os.path.join(appPath, "TestPackData", packDataTempKey, "PackData.json")
|
| | | if not os.path.isfile(fullPath):
|
| | | dbAnswerList.append("跨服db/TestPackData不存在该模版文件夹:%s" % packDataTempKey)
|
| | | return
|
| | | mylog.debug("打包数据模板文件:%s" % fullPath)
|
| | | |
| | | fileObj = open(fullPath, 'rb')
|
| | | content = fileObj.read()
|
| | | fileObj.close()
|
| | | packDataDict = eval(content)
|
| | | packData = packDataDict.get("PackData", "")
|
| | | if not packData:
|
| | | dbAnswerList.append("跨服db/TestPackData/%s没有打包数据" % (packDataTempKey))
|
| | | return
|
| | | |
| | | packDataTeamBuff = base64.b64decode(packData)
|
| | | tempDBPlayer = DataServerPlayerData.tagDBPlayer()
|
| | | tempDBPlayer.readData(packDataTeamBuff)
|
| | | otherDataBuff = packDataTeamBuff[tempDBPlayer.getLength():]
|
| | | |
| | | userCtrlDB = CtrlDBManager.getCtrlMgr().getCtrlDBByName('UserCtrlDB')
|
| | | |
| | | FakeName = "FakeName"
|
| | | addOKCount = 0
|
| | | for index in range(addCount):
|
| | | playerID = fackID = startID + index
|
| | | |
| | | tempDBPlayer.PlayerID = fackID
|
| | | tempDBPlayer.PlayerName = "%s%s" % (FakeName, fackID)
|
| | | curServerID = serverID if serverID else (playerID % 100 + 1) # 1 ~ 100 服
|
| | | tempDBPlayer.AccID = "fack%s@test@s%s" % (fackID, curServerID)
|
| | | |
| | | updBuff = tempDBPlayer.getBuffer() + otherDataBuff
|
| | | updPackData = base64.b64encode(updBuff)
|
| | | |
| | | #mylog.debug("updPackData:%s" % updPackData)
|
| | | userCtrlDB.updPlayerPackData(playerID, updPackData)
|
| | | addOKCount += 1
|
| | | |
| | | mylog.debug("添加假玩家打包数据数:%s" % addOKCount)
|
| | | dbAnswerList.append("跨服db添加假玩家打包数据数:%s,总:%s" % (addOKCount, len(PyGameData.g_packDataDict)))
|
| | | return
|
| | |
|
| | | def __delFackPackData(dbAnswerList):
|
| | | delCount = 0
|
| | | for playerID in PyGameData.g_packDataDict.keys():
|
| | | if playerID > 10000:
|
| | | continue
|
| | | del PyGameData.g_packDataDict[playerID]
|
| | | delCount += 1
|
| | | mylog.debug("删除假打包数据: delCount:%s" % delCount)
|
| | | dbAnswerList.append("跨服db删除假玩家打包数据数:%s,剩:%s" % (delCount, len(PyGameData.g_packDataDict)))
|
| | | return
|
| | |
|
| | |
|
New file |
| | |
| | | #!/usr/bin/python
|
| | | # -*- coding: GBK -*-
|
| | | #-------------------------------------------------------------------------------
|
| | | #
|
| | | ##@package PyMongoDataServer.GM.GMShell
|
| | | #
|
| | | # @todo:db执行GM命令
|
| | | # @author hxp
|
| | | # @date 2025-03-04
|
| | | # @version 1.0
|
| | | #
|
| | | # 详细描述: db执行GM命令
|
| | | #
|
| | | #-------------------------------------------------------------------------------
|
| | | #"""Version = 2025-03-04 16:30"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | |
|
| | | from DBCommon import GlobalFunctions
|
| | | from Common import mylog
|
| | | import Commands
|
| | | import os
|
| | |
|
| | | ## 导入GM全部命令
|
| | | # @param importDir 路径名
|
| | | # @return None
|
| | | # @remarks 函数详细说明.
|
| | | def ImportCommandAll(importDir):
|
| | | curPath = GlobalFunctions.getAppPath()
|
| | | for root, dirs, files in os.walk("%s\\%s"%(curPath, importDir)):
|
| | | for file in files:
|
| | | fileName = os.path.join(root, file)
|
| | | fileName = fileName.replace(curPath, "")
|
| | | fileName = fileName[1:len(fileName)]
|
| | | if fileName.find("__init__") >= 0:
|
| | | continue
|
| | | |
| | | curFileList = fileName.split(".")
|
| | | fileName = curFileList[0]
|
| | | ext = curFileList[1]
|
| | | if ext not in ['pyc', 'py']:
|
| | | continue
|
| | | |
| | | fileName = fileName.replace("\\",".")
|
| | | __import__(fileName)
|
| | |
|
| | | ImportCommandAll("GM\\Commands")
|
| | |
|
| | | ## 函数调用
|
| | | # @param curCallObj 实例(可能是某个文件名) |
| | | # @param callName 实例的某个属性
|
| | | # @return 属性
|
| | | def ParseNameGetObj(curCallObj, callName):
|
| | | callList = callName.split(".")
|
| | | if len(callList) <= 1:
|
| | | return None
|
| | | |
| | | for curCallName in callList:
|
| | | if hasattr(curCallObj, curCallName) != True:
|
| | | #无此属性
|
| | | return None
|
| | | |
| | | curCallObj = getattr(curCallObj, curCallName)
|
| | | |
| | | return curCallObj
|
| | |
|
| | | ## 外部调用的获取属性,且是可以call的
|
| | | # @param curCallObj 实例(可能是某个文件名) |
| | | # @param callName 实例的某个属性
|
| | | # @return 可以call的属性
|
| | | # @remarks 函数详细说明.
|
| | | def GetExecFunc(curCallObj, callName):
|
| | | curCallObj = ParseNameGetObj(curCallObj, callName)
|
| | | |
| | | if curCallObj == None:
|
| | | return None
|
| | | |
| | | if callable(curCallObj) != True:
|
| | | #不可调用
|
| | | return None
|
| | | |
| | | return curCallObj |
| | |
|
| | | def ClientGMCommand(msgData):
|
| | | mylog.debug('跨服DB收到子服GM命令: %s' % msgData)
|
| | | cmdMsgList = msgData.get("cmdMsgList", [])
|
| | | if not cmdMsgList:
|
| | | return []
|
| | | dbAnswerList = []
|
| | | cmdName = cmdMsgList[0]
|
| | | callName = "%s.%s"%(cmdName, "OnCrossDBExec")
|
| | | callFunc = GetExecFunc(Commands, callName)
|
| | | if callFunc != None:
|
| | | callFunc(cmdMsgList[1:], dbAnswerList)
|
| | | return dbAnswerList
|
| | |
|
| | | def DBGMCommand(cmdMsg):
|
| | | mylog.debug('DB收到GameServer的GM命令: %s' % cmdMsg)
|
| | | if not cmdMsg:
|
| | | return []
|
| | | dbAnswerList = []
|
| | | try:
|
| | | cmdMsgList = eval(cmdMsg)
|
| | | cmdName = cmdMsgList[0]
|
| | | callName = "%s.%s"%(cmdName, "OnDBExec")
|
| | | callFunc = GetExecFunc(Commands, callName)
|
| | | if callFunc != None:
|
| | | callFunc(cmdMsgList[1:], dbAnswerList)
|
| | | except:
|
| | | pass
|
| | | return dbAnswerList
|
| | |
|