8280 【主干】拍卖行系统上架优化(服务器可动态根据配置动态补充拍品)
4个文件已修改
255 ■■■■ 已修改文件
PySysDB/PySysDBG.h 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/AuctionHouse.py 203 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBG.h
@@ -63,12 +63,18 @@
    char        EndDate;    //结束日期
    char        StartTime;    //开启时间
    char        EndTime;    //结束时间
    BYTE        AuctionCount;    //上架次数
    list        RandMinuteRange;    //上架随机间隔分钟下限|上限
    list        ItemCountWeightList;    //上架随机件数权重列表, [[权重, 件数], ...]
    list        WorldLVRange;    //世界等级范围限制
    list        AddRandSecondRange;    //每件拍品随机间隔上架秒数 上限|下限
    list        AuctionItemWeightList;    //上架物品随机权重, [[权重, 物品ID],[权重, [阶,颜色,部位集合,是否套装,星级]] ...]
    list        RandMailKeyList;    //上架随机邮件列表,有配置时上架的时候在线玩家会收到一封上架邮件提醒
    WORD        ReplenishCDMinutes;    //动态补充拍品间隔分钟
    BYTE        ReplenishAuctionCount;    //动态补充拍品保底数
    DWORD        ReplenishItemID;    //动态补充物品ID
    list        ReplenishEquipInfo;    //动态补充装备信息 [阶,颜色,是否套装]
    list        ReplenishEquipPlaces;    //动态补充上架装备位列表
    BYTE        AuctionCount;    //指定上架次数
    list        RandMinuteRange;    //指定上架随机间隔分钟下限|上限
    list        ItemCountWeightList;    //指定上架随机件数权重列表, [[权重, 件数], ...]
    list        AuctionItemWeightList;    //指定上架物品随机权重, [[权重, 物品ID],[权重, [阶,颜色,部位集合,是否套装,星级]] ...]
    list        RandMailKeyList;    //指定上架随机邮件列表,有配置时上架的时候在线玩家会收到一封上架邮件提醒
};
//日常活动表
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/AuctionHouse.py
@@ -248,6 +248,7 @@
    
    if dbData.AuctionType == AuctionType_World:
        pyAuctionItemMgr.worldAuctionItemList.append(dbData)
        __OnCalcWorldAuctionItemCount(dbData, 1)
        
    if familyID:
        familyItemList = pyAuctionItemMgr.familyAuctionItemDict.get(familyID, [])
@@ -407,6 +408,37 @@
            return True
    return False
def __OnCalcWorldAuctionItemCount(auctionItem, changeCount):
    ## 世界拍品数量变更统计处理
    if auctionItem.AuctionType != AuctionType_World:
        return
    auctionItemMgr = PyDataManager.GetAuctionItemManager()
    itemID = auctionItem.ItemID
    #GameWorld.DebugLog("世界拍品数量变更统计: itemID=%s,changeCount=%s" % (itemID, changeCount))
    itemIDStr = str(itemID)
    classLV = auctionItem.ItemClassLV
    jobLimit = auctionItem.ItemJobLimit
    # 统计有职业限制的境界装备
    if jobLimit and classLV and len(itemIDStr) == 7:
        color = int(itemIDStr[3:4])
        isSuit = int(itemIDStr[-1])
        jobEquipKey = (jobLimit, classLV, color, isSuit) # 职业,阶,颜色,是否套装
        befCount = auctionItemMgr.worldAuctionJobEquipCountDict.get(jobEquipKey, 0)
        updCount = max(befCount + changeCount, 0)
        auctionItemMgr.worldAuctionJobEquipCountDict[jobEquipKey] = updCount
        #GameWorld.DebugLog("    职业境界装备数量变更: jobLimit=%s,classLV=%s,color=%s,isSuit=%s,befCount=%s,updCount=%s"
        #                   % (jobLimit, classLV, color, isSuit, befCount, updCount))
    # 其他的直接用itemID统计
    else:
        befCount = auctionItemMgr.worldAuctionItemCountDict.get(itemID, 0)
        updCount = max(befCount + changeCount, 0)
        auctionItemMgr.worldAuctionItemCountDict[itemID] = updCount
        #GameWorld.DebugLog("    物品ID数量变更: itemID=%s,befCount=%s,updCount=%s" % (itemID, befCount, updCount))
    return
def __GetAuctionSystemItemInfo():
    key = "AuctionSystemItem"
@@ -435,9 +467,10 @@
        endTimeStr = ipyData.GetEndTime()
        auctionCount = ipyData.GetAuctionCount()
        randMinuteRange = ipyData.GetRandMinuteRange()
        replenishAuctionCount = ipyData.GetReplenishAuctionCount()
        
        GameWorld.DebugLog("cfgID=%s,startDateStr=%s,endDateStr=%s,startTimeStr=%s,endTimeStr=%s,auctionCount=%s,randMinuteRange=%s"
                           % (cfgID, startDateStr, endDateStr, startTimeStr, endTimeStr, auctionCount, randMinuteRange))
        GameWorld.DebugLog("cfgID=%s,startDateStr=%s,endDateStr=%s,startTimeStr=%s,endTimeStr=%s,auctionCount=%s,randMinuteRange=%s,replenishAuctionCount=%s"
                           % (cfgID, startDateStr, endDateStr, startTimeStr, endTimeStr, auctionCount, randMinuteRange, replenishAuctionCount))
        
        if not startDateStr:
            startDateStr = curDateStr
@@ -486,10 +519,15 @@
            GameWorld.DebugLog("    添加上架系统拍品时间: nextAddMinutes=%s %s" % (nextAddMinutes, nextAddAuctionItemDatetime))
            addAuctionItemDatetimeList.append(nextAddAuctionItemDatetime)
            
        if not addAuctionItemDatetimeList:
        # 动态补充拍品模式
        if replenishAuctionCount:
            GameWorld.DebugLog("    添加动态补充系统拍品计划: %s" % replenishAuctionCount)
        # 指定上架拍品模式
        elif addAuctionItemDatetimeList:
            GameWorld.DebugLog("    添加上架系统拍品时间计划: %s" % addAuctionItemDatetimeList)
        else:
            continue
        GameWorld.DebugLog("    添加上架系统拍品时间: %s" % addAuctionItemDatetimeList)
        addSystemAuctionItemInfo.append([cfgID, ipyData, addAuctionItemDatetimeList])
        addSystemAuctionItemInfo.append([cfgID, ipyData, startDatetime, endDatetime, addAuctionItemDatetimeList])
        
    AuctionSystemItem = IpyGameDataPY.SetConfigEx(key, [reloadSign, addSystemAuctionItemInfo])
    GameWorld.Log("本日系统拍品信息加载完毕!reloadSign=%s" % (reloadSign))
@@ -506,39 +544,98 @@
                                                                    curDateTime.hour, curDateTime.minute), ChConfig.TYPE_Time_Format)
    
    randMailKey = ""
    addItemTick = tick
    sysAuctionItemList = IpyGameDataPY.GetConfigEx("SysWaitAuctionItemList") # 系统等待上架的拍品列表
    if not sysAuctionItemList:
        sysAuctionItemList = []
    addSystemAuctionItemInfo = __GetAuctionSystemItemInfo()
    for cfgID, ipyData, addAuctionItemDatetimeList in addSystemAuctionItemInfo:
        if curDateTime not in addAuctionItemDatetimeList:
            continue
        #cfgID = ipyData.GetCfgID()
        addCountWeightList = ipyData.GetItemCountWeightList()
        auctionItemWeightList = ipyData.GetAuctionItemWeightList()
        randSecondRange = ipyData.GetAddRandSecondRange()
    sysAuctionItemListDict = IpyGameDataPY.GetConfigEx("SysWaitAuctionItemListDict") # 系统等待上架的拍品列表字典 {cfgID:[待上架拍品列表], ...}
    if not sysAuctionItemListDict:
        sysAuctionItemListDict = {}
        
        addCount = GameWorld.GetResultByWeightList(addCountWeightList)
        GameWorld.Log("增加等待上架的系统拍品信息: cfgID=%s,addCount=%s,addItemTick=%s" % (cfgID, addCount, addItemTick))
        for _ in xrange(addCount):
            itemInfo = GameWorld.GetResultByWeightList(auctionItemWeightList)
            if itemInfo != None:
                randSeconds = 0
                if len(randSecondRange) == 2:
                    randSeconds = random.randint(randSecondRange[0], randSecondRange[1])
                elif len(randSecondRange) == 1:
                    randSeconds = randSecondRange[0]
                addItemTick = addItemTick + randSeconds * 1000
                sysAuctionItemList.append([addItemTick, itemInfo])
                GameWorld.Log("    增加等待上架的系统拍品: randSeconds=%s,addItemTick=%s,itemInfo=%s" % (randSeconds, addItemTick, itemInfo))
        randMailKeyList = ipyData.GetRandMailKeyList()
        if randMailKeyList:
            randMailKey = random.choice(randMailKeyList)
    curTime = int(time.time())
    addItemTime = curTime
    openJobList = IpyGameDataPY.GetFuncEvalCfg("OpenJob", 1)
    auctionItemMgr = PyDataManager.GetAuctionItemManager()
    curWorldLV = PlayerDBGSEvent.GetDBGSTrig_ByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
    addSystemAuctionItemInfo = __GetAuctionSystemItemInfo()
    for cfgID, ipyData, startDatetime, endDatetime, addAuctionItemDatetimeList in addSystemAuctionItemInfo:
        #cfgID = ipyData.GetCfgID()
        if cfgID in sysAuctionItemListDict:
            #GameWorld.DebugLog("    队列中还有未处理的拍品时不处理,防止重复添加!cfgID=%s" % (cfgID))
            continue
        worldLVRange = ipyData.GetWorldLVRange()
        if worldLVRange and len(worldLVRange) == 2:
            worldLVMin, worldLVMax = worldLVRange
            if curWorldLV < worldLVMin or curWorldLV > worldLVMax:
                #GameWorld.DebugLog("    不满足当前世界等级范围条件,不处理该系统上架拍品计划!cfgID=%s,curWorldLV=%s" % (cfgID, curWorldLV))
                continue
            
    IpyGameDataPY.SetConfigEx("SysWaitAuctionItemList", sysAuctionItemList)
    #GameWorld.DebugLog("等待系统上架的拍品列表: %s" % sysAuctionItemList)
        if curDateTime < startDatetime or curDateTime > endDatetime:
            #GameWorld.DebugLog("    不在规定的时间内,不处理该系统上架拍品计划!cfgID=%s" % (cfgID))
            continue
        randSecondRange = ipyData.GetAddRandSecondRange()
        if len(randSecondRange) != 2:
            #GameWorld.DebugLog("    随机上架秒数格式错误,不处理该系统上架拍品计划!cfgID=%s" % (cfgID))
            continue
        addItemInfoList = []
        replenishAuctionCount = ipyData.GetReplenishAuctionCount()
        # 动态模式
        if replenishAuctionCount:
            replenishCDSeconds = ipyData.GetReplenishCDMinutes() * 60
            lastReplenishTime = auctionItemMgr.worldAuctionReplenishTimeDict.get(cfgID, 0)
            if curTime - lastReplenishTime < replenishCDSeconds:
                continue
            auctionItemMgr.worldAuctionReplenishTimeDict[cfgID] = curTime
            replenishItemID = ipyData.GetReplenishItemID()
            if replenishItemID:
                curItemIDCount = auctionItemMgr.worldAuctionItemCountDict.get(replenishItemID, 0)
                if curItemIDCount >= replenishAuctionCount:
                    continue
                addItemIDCount = replenishAuctionCount - curItemIDCount
                GameWorld.DebugLog("    动态补充拍品队列: cfgID=%s,replenishItemID=%s,addItemIDCount=%s" % (cfgID, replenishItemID, addItemIDCount))
                for _ in xrange(addItemIDCount):
                    addItemInfoList.append(replenishItemID)
            else:
                replenishEquipPlaces = ipyData.GetReplenishEquipPlaces()
                rpClassLV, rpColor, rpIsSuit = ipyData.GetReplenishEquipInfo()
                rpStar = 0
                for job in openJobList:
                    jobEquipKey = (job, rpClassLV, rpColor, rpIsSuit)
                    curJobEquipCount = auctionItemMgr.worldAuctionJobEquipCountDict.get(jobEquipKey, 0)
                    if curJobEquipCount >= replenishAuctionCount:
                        continue
                    addEquipCount = replenishAuctionCount - curJobEquipCount
                    GameWorld.DebugLog("    动态补充拍品队列: cfgID=%s,addEquipCount=%s,job=%s" % (cfgID, addEquipCount, job))
                    for _ in xrange(addEquipCount):
                        addItemInfoList.append([rpClassLV, rpColor, replenishEquipPlaces, rpIsSuit, rpStar, [job]])
            random.shuffle(addItemInfoList) # 动态模式待添加拍品打乱下顺序,防止批量添加同一职业物品
        # 指定模式
        elif curDateTime in addAuctionItemDatetimeList:
            addCountWeightList = ipyData.GetItemCountWeightList()
            auctionItemWeightList = ipyData.GetAuctionItemWeightList()
            addCount = GameWorld.GetResultByWeightList(addCountWeightList)
            GameWorld.DebugLog("    指定补充拍品队列: cfgID=%s,addCount=%s" % (cfgID, addCount))
            for _ in xrange(addCount):
                itemInfo = GameWorld.GetResultByWeightList(auctionItemWeightList)
                if itemInfo != None:
                    addItemInfoList.append(itemInfo)
            randMailKeyList = ipyData.GetRandMailKeyList()
            if randMailKeyList:
                randMailKey = random.choice(randMailKeyList)
        sysWaitAuctionItemList = []
        for itemInfo in addItemInfoList:
            randSeconds = random.randint(randSecondRange[0], randSecondRange[1])
            addItemTime = addItemTime + randSeconds
            sysWaitAuctionItemList.append([addItemTime, itemInfo])
        sysAuctionItemListDict[cfgID] = sysWaitAuctionItemList
    IpyGameDataPY.SetConfigEx("SysWaitAuctionItemListDict", sysAuctionItemListDict)
    #GameWorld.DebugLog("等待系统上架的拍品列表: %s" % sysAuctionItemListDict)
    
    # 随机邮件通知 
    if randMailKey:
@@ -557,21 +654,26 @@
    return
def __DoSysWaitAddAuctionItem(tick):
    sysAuctionItemList = IpyGameDataPY.GetConfigEx("SysWaitAuctionItemList") # 系统等待上架的拍品列表
    if not sysAuctionItemList:
    SysWaitAuctionItemListDict = IpyGameDataPY.GetConfigEx("SysWaitAuctionItemListDict") # 系统等待上架的拍品列表
    if not SysWaitAuctionItemListDict:
        return
    
    doCount = len(sysAuctionItemList)
    while doCount > 0 and sysAuctionItemList:
        doCount -= 1
        addItemTick, itemInfo = sysAuctionItemList[0]
        if tick < addItemTick:
            #GameWorld.DebugLog("未到系统等待上架的拍品tick,不处理! tick=%s,sysAuctionItemList=%s" % (tick, sysAuctionItemList))
            break
        sysAuctionItemList.pop(0)
        GameWorld.DebugLog("系统等待上架的拍品tick已到,可上架! tick=%s >= addItemTick=%s,itemInfo=%s,sysAuctionItemList=%s" % (tick, addItemTick, itemInfo, sysAuctionItemList))
        DoAddSystemAuctionItem([itemInfo])
    curTime = int(time.time())
    for cfgID, sysAuctionItemList in SysWaitAuctionItemListDict.items():
        doCount = len(sysAuctionItemList)
        while doCount > 0 and sysAuctionItemList:
            doCount -= 1
            addItemTime, itemInfo = sysAuctionItemList[0]
            if curTime < addItemTime:
                #GameWorld.DebugLog("未到系统等待上架的拍品时间,不处理! curTime=%s,sysAuctionItemList=%s" % (curTime, sysAuctionItemList))
                break
            sysAuctionItemList.pop(0)
            GameWorld.DebugLog("系统等待上架的拍品时间已到,可上架! curTime=%s >= addItemTime=%s,itemInfo=%s,sysAuctionItemList=%s" % (curTime, addItemTime, itemInfo, sysAuctionItemList))
            DoAddSystemAuctionItem([itemInfo])
        if not sysAuctionItemList:
            SysWaitAuctionItemListDict.pop(cfgID)
    return
def OnAuctionItemTimeProcess(curTime, tick):
@@ -716,6 +818,7 @@
        
        auctionItemMgr.allAuctionItemByEndTimeList.append(auctionItem)
        auctionItemMgr.worldAuctionItemList.append(auctionItem)
        __OnCalcWorldAuctionItemCount(auctionItem, 1)
        notifyWorldAddItemList.append([itemGUID, itemID, playerID])
        
        AddAuctionRecord(auctionItem, AuctionRecordResult_MoveToWorld)
@@ -876,6 +979,7 @@
            
        if auctionItem in auctionItemMgr.worldAuctionItemList:
            auctionItemMgr.worldAuctionItemList.remove(auctionItem)
            __OnCalcWorldAuctionItemCount(auctionItem, -1)
            
        for queryItemList in auctionItemMgr.worldAuctionItemQueryDict.values():
            if auctionItem in queryItemList:
@@ -1085,6 +1189,7 @@
        auctionItemMgr.familyAuctionItemDict[familyID] = familyItemList
    else:
        auctionItemMgr.worldAuctionItemList.append(auctionItem)
        __OnCalcWorldAuctionItemCount(auctionItem, 1)
        
        # 添加进我的拍卖
        if playerID:
ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -79,10 +79,16 @@
                        ("char", "EndDate", 0),
                        ("char", "StartTime", 0),
                        ("char", "EndTime", 0),
                        ("list", "WorldLVRange", 0),
                        ("list", "AddRandSecondRange", 0),
                        ("WORD", "ReplenishCDMinutes", 0),
                        ("BYTE", "ReplenishAuctionCount", 0),
                        ("DWORD", "ReplenishItemID", 0),
                        ("list", "ReplenishEquipInfo", 0),
                        ("list", "ReplenishEquipPlaces", 0),
                        ("BYTE", "AuctionCount", 0),
                        ("list", "RandMinuteRange", 0),
                        ("list", "ItemCountWeightList", 0),
                        ("list", "AddRandSecondRange", 0),
                        ("list", "AuctionItemWeightList", 0),
                        ("list", "RandMailKeyList", 0),
                        ),
@@ -651,10 +657,16 @@
        self.EndDate = ""
        self.StartTime = ""
        self.EndTime = ""
        self.WorldLVRange = []
        self.AddRandSecondRange = []
        self.ReplenishCDMinutes = 0
        self.ReplenishAuctionCount = 0
        self.ReplenishItemID = 0
        self.ReplenishEquipInfo = []
        self.ReplenishEquipPlaces = []
        self.AuctionCount = 0
        self.RandMinuteRange = []
        self.ItemCountWeightList = []
        self.AddRandSecondRange = []
        self.AuctionItemWeightList = []
        self.RandMailKeyList = []
        return
@@ -664,12 +676,18 @@
    def GetEndDate(self): return self.EndDate # 结束日期
    def GetStartTime(self): return self.StartTime # 开启时间
    def GetEndTime(self): return self.EndTime # 结束时间
    def GetAuctionCount(self): return self.AuctionCount # 上架次数
    def GetRandMinuteRange(self): return self.RandMinuteRange # 上架随机间隔分钟下限|上限
    def GetItemCountWeightList(self): return self.ItemCountWeightList # 上架随机件数权重列表, [[权重, 件数], ...]
    def GetWorldLVRange(self): return self.WorldLVRange # 世界等级范围限制
    def GetAddRandSecondRange(self): return self.AddRandSecondRange # 每件拍品随机间隔上架秒数 上限|下限
    def GetAuctionItemWeightList(self): return self.AuctionItemWeightList # 上架物品随机权重, [[权重, 物品ID],[权重, [阶,颜色,部位集合,是否套装,星级]] ...]
    def GetRandMailKeyList(self): return self.RandMailKeyList # 上架随机邮件列表,有配置时上架的时候在线玩家会收到一封上架邮件提醒
    def GetReplenishCDMinutes(self): return self.ReplenishCDMinutes # 动态补充拍品间隔分钟
    def GetReplenishAuctionCount(self): return self.ReplenishAuctionCount # 动态补充拍品保底数
    def GetReplenishItemID(self): return self.ReplenishItemID # 动态补充物品ID
    def GetReplenishEquipInfo(self): return self.ReplenishEquipInfo # 动态补充装备信息 [阶,颜色,是否套装]
    def GetReplenishEquipPlaces(self): return self.ReplenishEquipPlaces # 动态补充上架装备位列表
    def GetAuctionCount(self): return self.AuctionCount # 指定上架次数
    def GetRandMinuteRange(self): return self.RandMinuteRange # 指定上架随机间隔分钟下限|上限
    def GetItemCountWeightList(self): return self.ItemCountWeightList # 指定上架随机件数权重列表, [[权重, 件数], ...]
    def GetAuctionItemWeightList(self): return self.AuctionItemWeightList # 指定上架物品随机权重, [[权重, 物品ID],[权重, [阶,颜色,部位集合,是否套装,星级]] ...]
    def GetRandMailKeyList(self): return self.RandMailKeyList # 指定上架随机邮件列表,有配置时上架的时候在线玩家会收到一封上架邮件提醒
# 日常活动表
class IPY_DailyAction():
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
@@ -171,6 +171,10 @@
        self.hisBiddingAuctionItemDict = {} # 玩家曾经参与过竞价的拍品,含所有拍品 {playerID:[tagDBAuctionItem, ...], ...}
        self.myAuctionItemDict = {} # 玩家拍卖中的物品 ,不包含仙盟拍品,由前端界面自行整合数据 {playerID:[tagDBAuctionItem, ...], ...}
        self.myAttentionItemDict = {} # 玩家关注中的物品 ,不包含仙盟拍品,由前端界面自行整合数据,只保存在线的玩家,离线清除,上线不同步,由前端查询 {playerID:[tagDBAuctionItem, ...], ...}
        self.worldAuctionItemCountDict = {} # 全服拍品物品ID对应件数统计 {itemID:件数, ...}
        self.worldAuctionJobEquipCountDict = {} # 全服拍品职业装备对应件数统计 {(职业,阶,颜色,是否套装):件数, ...}
        self.worldAuctionReplenishTimeDict = {} # 全服拍品动态上架历史处理时间 {cfgID:time, ...}
        return
    
    # 保存数据 存数据库和realtimebackup