xdh
2019-05-21 865ef7e9b7040f592a8bb423db4b0887122b5485
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/AuctionHouse.py
@@ -53,6 +53,18 @@
AuctionType_World = 0
AuctionType_Family = 1
'''
竞价流程:
1. MapServer 先验证价格是否够
2. GameServer 验证是否可以竞价
3. MapServer 扣除玩家货币
4. GameServer  进行竞价,变更下次竞价价格
基于以上流程,所以玩家竞价时需先锁定物品,防止竞价流程未完结时其他玩家请求竞价同一拍品判断竞价价格错误
锁定时长同样适用于拍品竞价时间结束时的保护时间
'''
BiddingQueryLockTick = 10000
#拍卖行状态开关
def GetAuctionHouseState(): return PlayerBourse.GetOpenState()
@@ -278,8 +290,9 @@
        return
    bidTime = GameWorld.ChangeTimeStrToNum(auctionItem.BiddingTime)
    endTime = bidTime + IpyGameDataPY.GetFuncCfg("AuctionHouse", 4)
    if endTime < auctionItem.EndTime:
    if endTime <= auctionItem.EndTime:
        return
    GameWorld.DebugLog("拍品加时: EndTime=%s,updEndTime=%s" % (auctionItem.EndTime, endTime))
    auctionItem.EndTime = endTime
    return True
@@ -304,21 +317,33 @@
    ## 仙盟拍卖中的拍品列表
    return PyDataManager.GetAuctionItemManager().familyAuctionItemDict.get(familyID, [])
def OnAuctionItemTimeProcess(curTime):
def IsFamilyMemberBiddingAuctionItem(familyID, memberID):
    ## 仙盟成员是否最高竞价拍品中
    familyAuctionItemList = GetFamilyAuctionItemList(familyID)
    for auctionItem in familyAuctionItemList:
        if auctionItem.BidderID == memberID:
            return True
    return False
def OnAuctionItemTimeProcess(curTime, tick):
    ## 拍卖行拍品定时处理,每秒触发一次
    allAuctionItemByEndTimeList = PyDataManager.GetAuctionItemManager().allAuctionItemByEndTimeList
    if not allAuctionItemByEndTimeList:
        return
    
    index = 0
    endItemList = [] # 结束竞价的拍品列表
    moveToWorldItemList = [] # 转移到全服拍卖的仙盟拍品列表
    doCount = len(allAuctionItemByEndTimeList)
    while doCount > 0 and allAuctionItemByEndTimeList:
        doCount -= 1
        auctionItem = allAuctionItemByEndTimeList[0]
        if curTime < auctionItem.EndTime:
        auctionItem = allAuctionItemByEndTimeList[index]
        if curTime <= auctionItem.EndTime:
            break
        allAuctionItemByEndTimeList.pop(0)
        if auctionItem.BiddingQueryTick and tick - auctionItem.BiddingQueryTick < BiddingQueryLockTick:
            index += 1
            continue
        allAuctionItemByEndTimeList.pop(index)
        
        # 没有人竞价的仙盟拍品
        if not auctionItem.BidderPrice and auctionItem.FamilyID and auctionItem.AuctionType == AuctionType_Family:
@@ -355,6 +380,8 @@
        auctionItemMgr.allAuctionItemByEndTimeList.append(auctionItem)
        auctionItemMgr.worldAuctionItemList.append(auctionItem)
        notifyWorldAddItemList.append([itemGUID, itemID, playerID])
        AddAuctionRecord(auctionItem, AuctionRecordResult_MoveToWorld)
        
        # 添加进我的关注
        for attentionPlayerID, attentionList in auctionItemMgr.myAttentionItemDict.items():
@@ -438,7 +465,8 @@
                familyPlayerIDList = json.loads(auctionItem.FamilyPlayerIDInfo)
                taxRate = IpyGameDataPY.GetFuncCfg("AuctionTaxrate", 2) # 仙盟拍品税率百分比
                personMaxRate = IpyGameDataPY.GetFuncCfg("AuctionTaxrate", 3) # 仙盟拍品个人最大收益百分比
                giveTotalGold = int(math.ceil(bidderPrice * (100 - taxRate) / 100.0))
                taxGold = max(1, int(bidderPrice * taxRate / 100.0)) # 最少收税1
                giveTotalGold = max(0, bidderPrice - taxGold)
                giveMaxGold = int(math.ceil(giveTotalGold * personMaxRate / 100.0))
                memCount = len(familyPlayerIDList)
                giveGoldAverage = min(giveMaxGold, int(math.ceil(giveTotalGold * 1.0 / memCount))) # 有收益的人平分
@@ -451,7 +479,8 @@
                
            elif playerID:
                taxRate = IpyGameDataPY.GetFuncCfg("AuctionTaxrate", 1) # 全服拍品税率百分比
                givePlayerGold = int(math.ceil(bidderPrice * (100 - taxRate) / 100.0))
                taxGold = max(1, int(bidderPrice * taxRate / 100.0)) # 最少收税1
                givePlayerGold = max(0, bidderPrice - taxGold)
                
                # 个人拍卖收益邮件
                detail = {"ItemGUID":itemGUID, "ItemID":itemID, "Count":itemCount, "BidderPrice":bidderPrice}
@@ -623,7 +652,8 @@
    @param curPlayer: 可能为None
    '''
    
    notifyWorldAddItemList = [] # 新增全服拍品通知 [[itemGUID, itemID, playerID], ...]
    isSortWorldItem = False
    notifyAddItemList = [] # 新增拍品通知 [[itemGUID, itemID, playerID], ...]
    notifyFamilyAddItemDict = {} # 新增仙盟拍品通知 {familyID:[auctionItem, ...], ...}
    for playerID, familyID, familyPlayerIDList, itemData in addAuctionItemList:
        if not playerID and not familyID:
@@ -633,25 +663,25 @@
        if not auctionItem:
            continue
        
        itemGUID = auctionItem.ItemGUID
        itemID = auctionItem.ItemID
        notifyAddItemList.append([itemGUID, itemID, playerID])
        if familyID:
            familyAddItemList = notifyFamilyAddItemDict.get(familyID, [])
            familyAddItemList.append(auctionItem)
            notifyFamilyAddItemDict[familyID] = familyAddItemList
        else:
            itemGUID = auctionItem.ItemGUID
            itemID = auctionItem.ItemID
            notifyWorldAddItemList.append([itemGUID, itemID, playerID])
            isSortWorldItem = True
            
    if notifyFamilyAddItemDict or notifyWorldAddItemList:
        isSortWorldItem = notifyWorldAddItemList != []
    if notifyAddItemList:
        __SortAuctionitem(isSortWorldItem=isSortWorldItem)
        
    # 通知新增仙盟拍品
    for familyID, familyAddItemList in notifyFamilyAddItemDict.items():
        Sync_FamilyAuctionItemInfo(None, familyID, familyAddItemList)
        
    # 通知全服拍品关注玩家
    __NotifyAuctionPlayerAddItem(notifyWorldAddItemList)
    # 通知拍品关注玩家
    __NotifyAuctionPlayerAddItem(notifyAddItemList)
    return
def __DoAddAuctionItem(curPlayer, playerID, familyID, familyPlayerIDList, itemData):
@@ -718,9 +748,9 @@
    GameWorld.DebugLog("更新拍品数: %s" % len(auctionItemMgr.allAuctionItemDict))
    return auctionItem
def __NotifyAuctionPlayerAddItem(notifyWorldAddItemList):
def __NotifyAuctionPlayerAddItem(notifyAddItemList):
    ## 通知关注物品的玩家新上架物品了
    if not notifyWorldAddItemList:
    if not notifyAddItemList:
        return
    attentionMgr = PyDataManager.GetAuctionAttentionManager()
    playerManager = GameWorld.GetPlayerManager()
@@ -734,8 +764,8 @@
        if not playerAttentionIDList:
            continue
        infoPack = None
        for itemGUID, itemID, playerID in notifyWorldAddItemList:
            if playerID == player.GetPlayerID():
        for itemGUID, itemID, playerID in notifyAddItemList:
            if playerID and playerID == player.GetPlayerID():
                # 自己上架的物品不通知
                continue
            if itemID not in playerAttentionIDList:
@@ -793,13 +823,13 @@
                             % (itemGUID, itemID, itemFamilyID, playerFamilyID), playerID)
            errInfo = "is family auction item"
            return itemID, errInfo
    if curTime >= auctionItem.EndTime:
    if curTime > auctionItem.EndTime:
        GameWorld.ErrLog("拍品已结束竞价! itemGUID=%s,itemID=%s,addTimeStr=%s" % (itemGUID, itemID, addTimeStr), playerID)
        errInfo = "end bid"
        return itemID, errInfo
    
    nextPrice = ipyData.GetBasePrice() if not auctionItem.BidderPrice else (auctionItem.BidderPrice + ipyData.GetBiddingAdd())
    buyoutPrice = ipyData.GetBuyoutPrice() # 允许没有一口价的,代表可以一直竞价
    nextPrice = ipyData.GetBasePrice() * auctionItem.Count if not auctionItem.BidderPrice else (auctionItem.BidderPrice + ipyData.GetBiddingAdd() * auctionItem.Count)
    buyoutPrice = ipyData.GetBuyoutPrice() * auctionItem.Count # 允许没有一口价的,代表可以一直竞价
    nextPrice = nextPrice if not buyoutPrice else min(nextPrice, buyoutPrice) # 不超过一口价
    if not (biddingPrice == nextPrice or (buyoutPrice and biddingPrice == buyoutPrice)):
        # 竞价价格错误
@@ -809,7 +839,7 @@
    
    if isOnlyCheck:
        queryTick = auctionItem.BiddingQueryTick
        if queryTick and tick - queryTick < 10000:
        if queryTick and tick - queryTick < BiddingQueryLockTick:
            # 有玩家正在竞价,请稍等
            PlayerControl.NotifyCode(curPlayer, "Paimai1")
            errInfo = "other player bidding"
@@ -866,7 +896,7 @@
                
    # 更新竞价信息
    auctionItem.BiddingQueryID = 0
    auctionItem.BiddingTick = 0
    auctionItem.BiddingQueryTick = 0
    auctionItem.BiddingTime = GameWorld.GetCurrentDataTimeStr()
    auctionItem.BidderID = playerID
    auctionItem.BidderName = curPlayer.GetName()
@@ -920,6 +950,7 @@
        refreshItem.AddTime = auctionItem.AddTime
        refreshItem.BidderID = auctionItem.BidderID
        refreshItem.BidderPrice = auctionItem.BidderPrice
        refreshItem.BiddingTime = auctionItem.BiddingTime
        refreshAuctionItemList.append(refreshItem)
        
    if not refreshAuctionItemList:
@@ -1026,10 +1057,10 @@
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    tagItemGUID = clientData.ItemGUID
    queryDir = 3
    __Sync_WorldAuctionItemQueryResult(curPlayer, fromItemGUID=tagItemGUID, queryDir=queryDir)
    __Sync_WorldAuctionItemQueryResult(curPlayer, fromItemGUID=tagItemGUID, queryDir=queryDir, isNotify=True)
    return
def __Sync_WorldAuctionItemQueryResult(curPlayer, job=0, itemTypeList=[], classLV=0, specItemIDList=[], fromItemGUID="", queryDir=1, queryCount=10):
def __Sync_WorldAuctionItemQueryResult(curPlayer, job=0, itemTypeList=[], classLV=0, specItemIDList=[], fromItemGUID="", queryDir=1, queryCount=10, isNotify=False):
    ## 根据过滤条件同步全服拍品列表,目前仅全服拍品需要通过查询服务器获得,个人拍品及仙盟拍品由于个数较少直接由上线或变更时主动同步
    
    fromAuctionItem = None
@@ -1037,7 +1068,8 @@
        fromAuctionItem = GetAuctionItem(fromItemGUID)
        if not fromAuctionItem:
            GameWorld.DebugLog("查询的目标拍品不存在! fromItemGUID=%s" % fromItemGUID)
            PlayerControl.NotifyCode(curPlayer, "Paimai5")
            if isNotify:
                PlayerControl.NotifyCode(curPlayer, "Paimai5")
            return
        
    # {(job, (itemType, ...), itemClassLV, (itemID, ...)):[tagDBAuctionItem, ...], ...}
@@ -1066,7 +1098,8 @@
    if fromAuctionItem:
        if fromAuctionItem not in auctionItemQueryList:
            GameWorld.ErrLog("查询的目标拍品不在所在的过滤的条件里! fromItemGUID=%s" % fromItemGUID)
            PlayerControl.NotifyCode(curPlayer, "Paimai5")
            if isNotify:
                PlayerControl.NotifyCode(curPlayer, "Paimai5")
            return
        fromIndex = auctionItemQueryList.index(fromAuctionItem)
        
@@ -1100,6 +1133,7 @@
        itemInfo.ItemCount = auctionItem.Count
        itemInfo.AddTime = auctionItem.AddTime
        itemInfo.BidderPrice = auctionItem.BidderPrice
        itemInfo.BiddingTime = auctionItem.BiddingTime
        itemInfo.UserData = auctionItem.UserData
        itemInfo.UserDataLen = auctionItem.UserDataLen
        clientPack.AuctionItemList.append(itemInfo)
@@ -1155,6 +1189,7 @@
        itemObj.ItemCount = attentionItem.Count
        itemObj.AddTime = attentionItem.AddTime
        itemObj.BidderPrice = attentionItem.BidderPrice
        itemObj.BiddingTime = attentionItem.BiddingTime
        itemObj.UserData = attentionItem.UserData
        itemObj.UserDataLen = attentionItem.UserDataLen
        clientPack.AuctionItemList.append(itemObj)
@@ -1212,6 +1247,7 @@
        packItem.ItemCount = auctionItem.Count
        packItem.AddTime = auctionItem.AddTime
        packItem.BidderPrice = auctionItem.BidderPrice
        packItem.BiddingTime = auctionItem.BiddingTime
        packItem.UserData = auctionItem.UserData
        packItem.UserDataLen = auctionItem.UserDataLen
        packItem.FamilyPlayerIDInfo = auctionItem.FamilyPlayerIDInfo
@@ -1247,6 +1283,7 @@
        packItem.ItemCount = auctionItem.Count
        packItem.AddTime = auctionItem.AddTime
        packItem.BidderPrice = auctionItem.BidderPrice
        packItem.BiddingTime = auctionItem.BiddingTime
        packItem.UserData = auctionItem.UserData
        packItem.UserDataLen = auctionItem.UserDataLen
        itemInfoPack.AuctionItemList.append(packItem)
@@ -1316,6 +1353,7 @@
        packItem.AddTime = auctionItem.AddTime
        packItem.BidderID = auctionItem.BidderID
        packItem.BidderPrice = auctionItem.BidderPrice
        packItem.BiddingTime = auctionItem.BiddingTime
        packItem.UserData = auctionItem.UserData
        packItem.UserDataLen = auctionItem.UserDataLen
        itemInfoPack.AuctionItemList.append(packItem)