ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerRecData.py
@@ -15,9 +15,14 @@
#"""Version = 2024-07-02 16:30"""
#-------------------------------------------------------------------------------
import CommFunc
import ChConfig
import ShareDefine
import PyDataManager
import PyGameDataStruct
import ChPyNetSendPack
import NetPackCommon
import GameWorld
import CommFunc
import time
@@ -27,11 +32,13 @@
        if not dbRecData:
            dbRecData = PyGameDataStruct.tagDBPlayerRecData()
        self.dbRecData = dbRecData
        self.evalUserData = None
        self.__userDataDict = None
        self.__userDataChange = False
        return
    def clear(self):
        self.dbRecData.clear()
        self.evalUserData = None
        self.__userDataDict = None
        self.__userDataChange = False
        return
    def GetPlayerID(self): return self.dbRecData.PlayerID
    def SetPlayerID(self, playerID): self.dbRecData.PlayerID = playerID
@@ -55,24 +62,47 @@
    def SetValue7(self, value7): self.dbRecData.Value7 = value7
    def GetValue8(self): return self.dbRecData.Value8
    def SetValue8(self, value8): self.dbRecData.Value8 = value8
    def GetUserData(self): return self.dbRecData.UserData
    def SetUserData(self, userData):
        if type(userData) != str:
            userData = str(userData).replace(" ", "")
        self.dbRecData.UserData = userData
        self.dbRecData.UserDataLen = len(self.dbRecData.UserData)
        if self.evalUserData != None:
            self.evalUserData = None
        return
    def GetEvalUserData(self, defValue={}):
        if self.evalUserData == None:
    def __GetUserDataDict(self):
        if self.__userDataDict == None:
            try:
                self.evalUserData = eval(self.dbRecData.UserData)
                self.__userDataDict = eval(self.dbRecData.UserData)
            except:
                self.evalUserData = defValue
        return self.evalUserData
    def SetEvalUserData(self, eValue):
        self.evalUserData = eValue
                self.__userDataDict = {}
        return self.__userDataDict
    def GetUserDataByKey(self, key, defaultValue=None):
        userDataDict = self.__GetUserDataDict()
        if key in userDataDict:
            return userDataDict[key]
        return defaultValue
    def SetUserDataByKey(self, key, value, noneDelKey=False):
        if not value and noneDelKey:
            self.DelUserDataByKey(key)
            return
        userDataDict = self.__GetUserDataDict()
        userDataDict[key] = value
        self.__userDataChange = True
        return
    def DelUserDataByKey(self, key):
        userDataDict = self.__GetUserDataDict()
        userDataDict.pop(key, None)
        self.__userDataChange = True
        return
    def GetUserData(self):
        if self.__userDataChange:
            self.SaveUserData()
        return self.dbRecData.UserData
    def SetUserData(self, userData):
        ## 支持直接保存任意格式数据,或者按字典方式读取kv值
        if type(userData) != str:
            userData = str(userData)
        self.dbRecData.UserData = userData.replace(" ", "")
        self.dbRecData.UserDataLen = len(self.dbRecData.UserData)
        self.__userDataDict = None
        self.__userDataChange = False
        return
    def SaveUserData(self):
        if self.__userDataChange:
            self.SetUserData(self.__userDataDict)
        return
    
    def IsMatchValue(self, valueList):
@@ -88,6 +118,12 @@
            curValue = getattr(self, "GetValue%s" % i)()
            if curValue != value:
                return False
        return True
    def IsEmpty(self):
        if self.GetValue1() or self.GetValue2() or self.GetValue3() or self.GetUserData() not in ["", "{}"] or self.GetValue4() \
            or self.GetValue5() or self.GetValue6() or self.GetValue7() or self.GetValue8():
            return False
        return True
    
    def GetString(self):
@@ -117,9 +153,12 @@
    
    def DelRecDataByType(self, recType):
        ## 删除某个记录类型所有玩家记录
        GameWorld.DebugLog("删除所有玩家指定记录类型: recType=%s" % recType)
        self.recTypeDict.pop(recType, None)
        return
        recDict = self.recTypeDict.pop(recType, {})
        delCount = 0
        for recList in recDict.values():
            delCount += len(recList)
        GameWorld.DebugLog("删除所有玩家指定记录类型: recType=%s,delCount=%s" % (recType, delCount))
        return delCount
    
    def DelRecDataByTypePlayer(self, recType, delPlayerID):
        ## 删除玩家某个类型记录
@@ -200,12 +239,14 @@
        playerRecDataList.append(recData)
        return
    
    def GetPlayerRecDataFirst(self, recType, playerID):
    def GetPlayerRecDataFirst(self, recType, playerID, isAddNew):
        ## 获取玩家记录类型对应的第一条记录,适用于仅需一条的记录类型
        # @param isAddNew: 没有记录时是否添加一条新记录,一般获取后需要更新数据的可以设置为True,仅判断用的建议设置为False,减少产生多余空数据
        recData = None
        recDataList = self.GetPlayerRecDataList(recType, playerID)
        if recDataList:
            recData = recDataList[0]
        else:
        elif isAddNew:
            recData = self.AddPlayerRecData(recType, playerID)
        return recData
@@ -223,17 +264,22 @@
    def GetPlayerRecDataList(self, recType, playerID):
        ## 获取玩家记录类型对应记录列表 [recData, ...]
        if recType not in self.recTypeDict:
            return []
            self.recTypeDict[recType] = {}
        playerRecDataDict = self.recTypeDict[recType]
        if playerID not in playerRecDataDict:
            return []
        return playerRecDataDict[playerID]
            playerRecDataDict[playerID] = []
        playerRecDataList = playerRecDataDict[playerID]
        return playerRecDataList
    
    def GetPlayerRecDataDict(self, recType):
        ## 获取记录类型对应所有玩家的记录字典 {playerID:[recData, ...], ...}
        if recType not in self.recTypeDict:
            return {}
        return self.recTypeDict[recType]
    def SortRecDataList(self, recDataList):
        recDataList.sort(key=lambda r: (r.GetTime()), reverse=False)
        return
    
    # 保存数据 存数据库和realtimebackup
    def GetSaveData(self):
@@ -244,9 +290,10 @@
        for playerRecDataDict in self.recTypeDict.values():
            for recDataList in playerRecDataDict.values():
                for recData in recDataList:
                    recData.SaveUserData()
                    if recData.IsEmpty():
                        continue
                    cnt += 1
                    if recData.evalUserData != None:
                        recData.SetUserData(recData.evalUserData)
                    savaData += recData.dbRecData.getBuffer()
                    
        GameWorld.Log("Save DBPlayerRecData count :%s len=%s" % (cnt, len(savaData)))
@@ -269,3 +316,81 @@
        return pos
    
PlayerRecDataTemp = PlayerRecData()
def OnPlayerLogin(curPlayer):
    playerID = curPlayer.GetPlayerID()
    playerRecMgr = PyDataManager.GetDBPlayerRecDataManager()
    for recType in ChConfig.Def_PlayerRecLoginNotifyList:
        recDataList = playerRecMgr.GetPlayerRecDataList(recType, playerID)
        if not recDataList:
            continue
        SyncPlayerRecInfo(curPlayer, recType, recDataList)
    return
def MapServer_AddPlayerRec(curPlayer, recType, valueList, userData="", notifyType=0):
    '''
    @todo: 添加玩家记录
    @param recType: 通用记录类型, 对应 ShareDefine.Def_PlayerRecTypeList
    @param valueList: 数值列表[value1, value2, ...], 按顺序, 支持value1 ~ value8
    @param userData: 自定义字符信息
    @param notifyType: 0-不通知; 1-通知单条; 2-通知全部
    '''
    if not curPlayer:
        return
    playerID = curPlayer.GetPlayerID()
    if recType not in ShareDefine.Def_PlayerRecTypeList:
        GameWorld.ErrLog("玩家记录类型错误: recType=%s" % recType, playerID)
        return
    playerRecMgr = PyDataManager.GetDBPlayerRecDataManager()
    recDataList = playerRecMgr.GetPlayerRecDataList(recType, playerID)
    if recDataList and len(recDataList) >= ChConfig.Def_PlayerRecCountDict.get(recType, 50):
        playerRecMgr.SortRecDataList(recDataList)
        recDataList.pop(0) # 删除第一个
    recData = playerRecMgr.AddPlayerRecData(recType, playerID)
    for num, value in enumerate(valueList, 1):
        if num > 8:
            break
        getattr(recData, "SetValue%s" % num)(min(ChConfig.Def_UpperLimit_DWord, value))
    if userData:
        recData.SetUserData(userData)
    if notifyType == 1:
        SyncPlayerRecInfo(curPlayer, recType, [recData])
    elif notifyType == 2:
        SyncPlayerRecInfo(curPlayer, recType, recDataList)
    return recData
def SyncPlayerRecInfo(curPlayer, recType, recDataList):
    if not recDataList:
        return
    playerRecList = []
    for recData in recDataList:
        if not recData:
            continue
        rec = ChPyNetSendPack.tagGCPlayerRec()
        rec.Time = recData.GetTime()
        rec.Value1 = recData.GetValue1()
        rec.Value2 = recData.GetValue2()
        rec.Value3 = recData.GetValue3()
        rec.Value4 = recData.GetValue4()
        rec.Value5 = recData.GetValue5()
        rec.Value6 = recData.GetValue6()
        rec.Value7 = recData.GetValue7()
        rec.Value8 = recData.GetValue8()
        rec.UserData = recData.GetUserData()
        rec.UserDataLen = len(rec.UserData)
        playerRecList.append(rec)
    clientPack = ChPyNetSendPack.tagGCPlayerRecInfo()
    clientPack.Clear()
    clientPack.Type = recType
    clientPack.PlayerRecList = playerRecList
    clientPack.Count = len(clientPack.PlayerRecList)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return