| | |
| | | AuctionType_World = 0
|
| | | AuctionType_Family = 1
|
| | |
|
| | | '''
|
| | | 竞价流程: |
| | | 1. MapServer 先验证价格是否够
|
| | | 2. GameServer 验证是否可以竞价
|
| | | 3. MapServer 扣除玩家货币
|
| | | 4. GameServer 进行竞价,变更下次竞价价格
|
| | |
|
| | | 基于以上流程,所以玩家竞价时需先锁定物品,防止竞价流程未完结时其他玩家请求竞价同一拍品判断竞价价格错误
|
| | | 锁定时长同样适用于拍品竞价时间结束时的保护时间
|
| | | '''
|
| | | BiddingQueryLockTick = 10000
|
| | |
|
| | | #拍卖行状态开关
|
| | | def GetAuctionHouseState(): return PlayerBourse.GetOpenState()
|
| | |
|
| | |
| | | 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
|
| | |
|
| | |
| | | ## 仙盟拍卖中的拍品列表
|
| | | 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:
|
| | |
| | | auctionItemMgr.allAuctionItemByEndTimeList.append(auctionItem)
|
| | | auctionItemMgr.worldAuctionItemList.append(auctionItem)
|
| | | notifyWorldAddItemList.append([itemGUID, itemID, playerID])
|
| | | |
| | | AddAuctionRecord(auctionItem, AuctionRecordResult_MoveToWorld)
|
| | |
|
| | | # 添加进我的关注
|
| | | for attentionPlayerID, attentionList in auctionItemMgr.myAttentionItemDict.items():
|
| | |
| | | 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))) # 有收益的人平分
|
| | |
| | |
|
| | | 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}
|
| | |
| | | @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:
|
| | |
| | | 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):
|
| | |
| | | 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()
|
| | |
| | | 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:
|
| | |
| | | % (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)):
|
| | | # 竞价价格错误
|
| | |
| | |
|
| | | 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"
|
| | |
| | |
|
| | | # 更新竞价信息
|
| | | auctionItem.BiddingQueryID = 0
|
| | | auctionItem.BiddingTick = 0
|
| | | auctionItem.BiddingQueryTick = 0
|
| | | auctionItem.BiddingTime = GameWorld.GetCurrentDataTimeStr()
|
| | | auctionItem.BidderID = playerID
|
| | | auctionItem.BidderName = curPlayer.GetName()
|
| | |
| | | refreshItem.AddTime = auctionItem.AddTime
|
| | | refreshItem.BidderID = auctionItem.BidderID
|
| | | refreshItem.BidderPrice = auctionItem.BidderPrice
|
| | | refreshItem.BiddingTime = auctionItem.BiddingTime
|
| | | refreshAuctionItemList.append(refreshItem)
|
| | |
|
| | | if not refreshAuctionItemList:
|
| | |
| | | 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
|
| | |
| | | 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, ...], ...}
|
| | |
| | | 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)
|
| | |
|
| | |
| | | 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)
|
| | |
| | | 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)
|
| | |
| | | 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
|
| | |
| | | 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)
|
| | |
| | | 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)
|