5563 【英文】【BT】跨服服务器维护优化(打包数据改为db自己管理存取)
15个文件已修改
5个文件已添加
1056 ■■■■■ 已修改文件
ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/PlayerMirror.py 101 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GM/GMShell.py 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmPK.py 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/QueryDBLogicResult.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py 293 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py 228 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerXMZZ.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/MirrorAttack.py 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PlayerMirror.py 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetCrossPK.py 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MirrorBattle.py 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/db/PyMongoDataServer/GM/Commands/PlayerMirror.py 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/db/PyMongoDataServer/GM/Commands/__init__.py 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/db/PyMongoDataServer/GM/GMShell.py 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/db/PyMongoDataServer/GM/__init__.py 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/db/PyMongoDataServer/__init__.py 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
@@ -448,8 +448,10 @@
# 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
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/PlayerMirror.py
@@ -15,31 +15,20 @@
#"""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 []
@@ -56,89 +45,53 @@
    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
ServerPython/CoreServerGroup/GameServer/Script/GM/GMShell.py
@@ -102,7 +102,7 @@
            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:
@@ -111,7 +111,10 @@
            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日志!")
@@ -241,7 +244,12 @@
    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 
    
ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
@@ -1248,6 +1248,13 @@
    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):
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossChampionship.py
@@ -353,19 +353,6 @@
    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
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmPK.py
@@ -22,6 +22,7 @@
import ChPyNetSendPack
import PyGameDataStruct
import PlayerDBGSEvent
import PlayerViewCache
import CrossBillboard
import PyDataManager
import NetPackCommon
@@ -450,9 +451,10 @@
    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):
@@ -512,9 +514,8 @@
    
    # 通知子服
    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 = {}
@@ -526,30 +527,27 @@
    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():
@@ -630,12 +628,22 @@
        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)
@@ -653,8 +661,8 @@
        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)
@@ -666,10 +674,9 @@
    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
@@ -824,22 +831,27 @@
    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
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/QueryDBLogicResult.py
@@ -9,6 +9,7 @@
import PlayerPackData
import IPY_GameServer
import ChConfig
import GameWorld
#-------------------------------------------------------------------------
@@ -36,11 +37,16 @@
        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
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerPackData.py
@@ -24,25 +24,25 @@
#            如切磋一下,玩家可以在任意场景对任意本服或跨服玩家发起切磋,与其镜像进行一场友谊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):
@@ -52,247 +52,46 @@
        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):
@@ -341,6 +140,7 @@
    
    # pullFrom 0-跨服拉子服; >0-子服通过跨服拉子服
    if GameWorld.IsCrossServer():
        PlayerViewCache.SetNeedViewCache(pullPlayerIDList) # 拉打包数据的时候默认需要缓存数据
        # 广播给子服拉数据
        msgInfo["pullFrom"] = 0
        dataMsg = {"pullPlayerIDList":pullPlayerIDList, "msgInfo":msgInfo}
@@ -371,7 +171,7 @@
    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)
    # 在线的转发给地图
@@ -442,9 +242,6 @@
    ## 收到子服同步的玩家打包数据
    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", {})
@@ -469,21 +266,23 @@
    
    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)
        
@@ -508,10 +307,10 @@
    
    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)
@@ -541,14 +340,14 @@
    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)
        
    # 本服需要的功能
@@ -585,9 +384,9 @@
    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)
        
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
@@ -37,6 +37,7 @@
import CrossRealmMsg
import ShareDefine
import PyGameData
import CommFunc
import ChPlayer
import ChConfig
@@ -45,6 +46,146 @@
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()
@@ -129,14 +270,12 @@
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
@@ -144,50 +283,56 @@
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):
@@ -241,7 +386,7 @@
                 "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(),
@@ -421,6 +566,19 @@
        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
@@ -564,7 +722,7 @@
        GameWorld.DebugLog("子服推送的玩家缓存数据为空! playerID=%s" % playerID, serverGroupID)
    else:
        curCache = FindViewCache(playerID, True)
        __updCacheBufferToCacheObj(playerID, cacheBuffer, curCache)
        ReadCacheBufferToCacheObj(playerID, cacheBuffer, curCache)
        
    if not msgInfo:
        return
@@ -587,9 +745,10 @@
    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
@@ -599,6 +758,9 @@
    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
@@ -618,7 +780,7 @@
        setattr(cacheObj, "ItemData%s" % classLV, itemData)
        setattr(cacheObj, "ItemDataSize%s" % classLV, itemDataSize)
        
    return True
    return cacheObj
def CrossServerMsg_ViewPlayerCacheRet(msgData, tick):
    ## 收到跨服服务器回复的查看玩家信息
@@ -634,7 +796,7 @@
            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)
@@ -644,7 +806,7 @@
def CrossServerMsg_PullPlayerViewCache(msgData):
    ## 收到跨服服务器拉取玩家玩家缓存数据
    msgInfo = msgData["msgInfo"]
    msgInfo = msgData.get("msgInfo", {})
    tagPlayerID = msgData["tagPlayerID"]
    DoPullPlayerViewCache(tagPlayerID, msgInfo)
    return
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerXMZZ.py
@@ -648,8 +648,9 @@
        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
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
@@ -28,6 +28,7 @@
import PlayerAssist
import GameRecData
import PlayerRecData
import PlayerViewCache
import GameWorldMineArea
import PyGameDataStruct
import PlayerPackData
@@ -134,43 +135,6 @@
                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
    
@@ -317,7 +281,7 @@
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()
@@ -333,7 +297,7 @@
        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()
@@ -354,7 +318,6 @@
    def GetSaveData(self):
        buff = ""
        buff += self.DBPlayerPackDataManager.GetSaveData()
        buff += self.DBGameRecDataManager.GetSaveData()
        buff += self.DBPyFuncTeamManager.GetSaveData()
        buff += self.DBPyFuncTeamMemManager.GetSaveData()
@@ -390,7 +353,6 @@
        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))
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/MirrorAttack.py
@@ -37,6 +37,7 @@
import PlayerState
import SkillShell
import CommFunc
import FBCommon
import PlayerFB
import GameMap
import FBLogic
@@ -115,6 +116,7 @@
        self.stateTick = tick        
        self.stateTickRemain = self.GetStateTickMax()
        self.SyncFBStepTime(tick)
        FBCommon.SetFBStep(state, tick)
        return
        
    def CaclStateTick(self, tick):
@@ -574,6 +576,11 @@
    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())
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PlayerMirror.py
@@ -34,11 +34,14 @@
        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()
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetCrossPK.py
@@ -35,6 +35,19 @@
        __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
@@ -139,10 +152,11 @@
    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
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MirrorBattle.py
@@ -21,6 +21,7 @@
import PlayerControl
import IpyGameDataPY
import PlayerCrossRealmPK
import GameWorldProcess
import CrossRealmPlayer
import PlayerArena
import GameWorld
@@ -45,6 +46,20 @@
    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)
ServerPython/db/PyMongoDataServer/GM/Commands/PlayerMirror.py
New file
@@ -0,0 +1,108 @@
#!/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
ServerPython/db/PyMongoDataServer/GM/Commands/__init__.py
ServerPython/db/PyMongoDataServer/GM/GMShell.py
New file
@@ -0,0 +1,112 @@
#!/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
ServerPython/db/PyMongoDataServer/GM/__init__.py
ServerPython/db/PyMongoDataServer/__init__.py