From 3d658259b25c4914c766c43aeea883bdd0847c5d Mon Sep 17 00:00:00 2001 From: hxp <ale99527@vip.qq.com> Date: 星期一, 04 三月 2019 16:39:42 +0800 Subject: [PATCH] 6250 【后端】【2.0】拍卖行开发单 --- ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/AuctionHouse.py | 1373 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 1,308 insertions(+), 65 deletions(-) diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/AuctionHouse.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/AuctionHouse.py index 16d3b83..bdc0374 100644 --- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/AuctionHouse.py +++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/AuctionHouse.py @@ -6,91 +6,1334 @@ # # @todo:拍卖行 # @author hxp -# @date 2019-02-19 +# @date 2019-03-04 # @version 1.0 # # 详细描述: 拍卖行 # #------------------------------------------------------------------------------- -#"""Version = 2019-02-19 12:00""" +#"""Version = 2019-03-04 17:00""" #------------------------------------------------------------------------------- -import CommFunc import GameWorld +import PyDataManager +import PlayerControl +import DataRecordPack +import PyGameDataStruct +import PlayerCompensation +import ChPyNetSendPack +import IpyGameDataPY +import NetPackCommon +import PlayerBourse +import PlayerFamily +import ChConfig +import operator +import time +import math +import json -#拍卖关注管理,注意该类只处理数据逻辑,功能相关逻辑不要写在该类,不然重读脚本不会生效 -class AuctionAttentionManager(object): - - def __init__(self): +# 拍卖记录类型定义 +AuctionRecordTypeList = ( +AuctionRecordType_MyAuction, # 我的拍品 +AuctionRecordType_FamilyAuction, # 仙盟拍品 +AuctionRecordType_MyBid, # 我的竞拍 +) = range(3) + +# 拍卖记录结果定义 +AuctionRecordResultList = ( +AuctionRecordResult_SellFail, # 流拍 +AuctionRecordResult_SellOK, # 拍卖成交 +AuctionRecordResult_Recycle, # 系统回收 +AuctionRecordResult_BidOK, # 竞价成功 +AuctionRecordResult_BidFail, # 竞价失败 +AuctionRecordResult_MoveToWorld, # 仙盟拍品转移到全服拍品 +) = range(6) + +# 当前拍品归类 0-全服拍品 1-仙盟私有拍品 +AuctionType_World = 0 +AuctionType_Family = 1 + +#拍卖行状态开关 +def GetAuctionHouseState(): return PlayerBourse.GetOpenState() + +def OnPlayerLogin(curPlayer): + Sync_PlayerAuctionItemInfo(curPlayer) + Sync_FamilyAuctionItemInfo(curPlayer, curPlayer.GetFamilyID()) + Sync_PlayerBiddingItemInfo(curPlayer) + Sync_PlayerAttentionAuctionItemID(curPlayer, False) + return + +def OnPlayerLeaveServer(curPlayer): + playerID = curPlayer.GetPlayerID() + auctionItemMgr = PyDataManager.GetAuctionItemManager() + auctionItemMgr.myAttentionItemDict.pop(playerID, None) + return + +##--------------------------------------- 拍卖记录 ------------------------------------------------- +def GetMyAuctionItemRecord(playerID): + ## 获取我的拍品记录 + return PyDataManager.GetAuctionRecordManager().myAuctionItemRecordDict.get(playerID, []) + +def GetMyBiddingItemRecord(playerID): + ## 获取我的竞拍记录 + return PyDataManager.GetAuctionRecordManager().myBidItemRecordDict.get(playerID, []) + +def GetFamilyAuctionItemRecord(familyID): + ## 获取仙盟拍品记录 + return PyDataManager.GetAuctionRecordManager().familyAuctionItemRecordDict.get(familyID, []) + +def AddAuctionRecord(auctionItem, recordResult): + ''' 添加拍卖行记录 + @param auctionItem: 相关的拍品实例 + @param recordResult: 记录结果 0-流拍 1-拍卖成交 2-回收 3-竞价成功 4-竞价失败 + ''' + if not auctionItem: return - ## =========================================================================================== + playerID, familyID, bidderID = auctionItem.PlayerID, auctionItem.FamilyID, auctionItem.BidderID + recordPlayerID, recordFamilyID = 0, 0 - # 保存数据 存数据库和realtimebackup - def GetSaveData(self): - savaData = "" - cntData = "" - cnt = 0 - - GameWorld.Log("Save AuctionAttention count :%s" % cnt) - return CommFunc.WriteDWORD(cntData, cnt) + savaData - - # 从数据库载入数据 - def LoadPyGameData(self, datas, pos, dataslen): - cnt, pos = CommFunc.ReadDWORD(datas, pos) - GameWorld.Log("Load AuctionAttention count :%s" % cnt) - - return pos - - -#拍卖记录管理,注意该类只处理数据逻辑,功能相关逻辑不要写在该类,不然重读脚本不会生效 -class AuctionRecordManager(object): - - def __init__(self): + if recordResult in [AuctionRecordResult_BidOK, AuctionRecordResult_BidFail]: + recordType = AuctionRecordType_MyBid + recordPlayerID = bidderID + else: + if familyID: + recordType = AuctionRecordType_FamilyAuction + recordFamilyID = familyID + else: + recordType = AuctionRecordType_MyAuction + recordPlayerID = playerID + + if not recordPlayerID and not recordFamilyID: return - ## =========================================================================================== + newRecordData = PyGameDataStruct.tagDBAuctionRecord() + newRecordData.ItemGUID = auctionItem.ItemGUID + newRecordData.PlayerID = recordPlayerID + newRecordData.FamilyID = recordFamilyID + newRecordData.RecordType = recordType + newRecordData.RecordResult = recordResult + newRecordData.RecordTime = GameWorld.GetCurrentDataTimeStr() + newRecordData.BidderPrice = auctionItem.BidderPrice + newRecordData.BidderName = auctionItem.BidderName + newRecordData.ItemID = auctionItem.ItemID + newRecordData.Count = auctionItem.Count + newRecordData.UserData = auctionItem.UserData + newRecordData.UserDataLen = auctionItem.UserDataLen + AddNewAuctionRecord(newRecordData) - # 保存数据 存数据库和realtimebackup - def GetSaveData(self): - savaData = "" - cntData = "" - cnt = 0 - - GameWorld.Log("Save AuctionRecord count :%s" % cnt) - return CommFunc.WriteDWORD(cntData, cnt) + savaData - - # 从数据库载入数据 - def LoadPyGameData(self, datas, pos, dataslen): - cnt, pos = CommFunc.ReadDWORD(datas, pos) - GameWorld.Log("Load AuctionRecord count :%s" % cnt) - - return pos + if recordFamilyID: + Sync_PlayerAuctionRecordInfo(None, recordType, newRecordData, recordFamilyID) + elif recordPlayerID: + recordPlayer = GameWorld.GetPlayerManager().FindPlayerByID(recordPlayerID) + if recordPlayer and not PlayerControl.GetIsTJG(recordPlayer): + Sync_PlayerAuctionRecordInfo(recordPlayer, recordType, newRecordData) + return +def AddNewAuctionRecord(newRecordData): + playerID = newRecordData.PlayerID + familyID = newRecordData.FamilyID + recordType = newRecordData.RecordType + if recordType == AuctionRecordType_MyAuction: + keyID = playerID + recordDict = PyDataManager.GetAuctionRecordManager().myAuctionItemRecordDict + elif recordType == AuctionRecordType_FamilyAuction: + keyID = familyID + recordDict = PyDataManager.GetAuctionRecordManager().familyAuctionItemRecordDict + elif recordType == AuctionRecordType_MyBid: + keyID = playerID + recordDict = PyDataManager.GetAuctionRecordManager().myBidItemRecordDict + else: + return + recordList = recordDict.get(keyID, []) + maxCount = min(50, IpyGameDataPY.GetFuncCfg("AuctionHouse", 3)) + if len(recordList) >= maxCount: + del recordList[0] + recordList.append(newRecordData) + recordDict[keyID] = recordList + return +##-------------------------------------- 拍卖关注 ------------------------------------------------ -#拍卖物品管理,注意该类只处理数据逻辑,功能相关逻辑不要写在该类,不然重读脚本不会生效 -class AuctionItemManager(object): +def GetPlayerAuctionAttention(attentionMgr, playerID): + ## 获取玩家关注的物品ID列表 + if playerID not in attentionMgr.playerAttentionDict: + return [] + attentionObj = attentionMgr.playerAttentionDict[playerID] + attentionItemIDList = attentionObj.AttentionItemIDList + return attentionItemIDList + +def AddPlayerAuctionAttention(attentionMgr, playerID, itemID): + ## 添加玩家关注的物品ID + if playerID not in attentionMgr.playerAttentionDict: + dbData = PyGameDataStruct.tagDBAuctionAttention() + dbData.PlayerID = playerID + __InitAuctionAttentionAttrEx(dbData) + attentionMgr.playerAttentionDict[playerID] = dbData + attentionObj = attentionMgr.playerAttentionDict[playerID] + attentionItemIDList = attentionObj.AttentionItemIDList + if len(attentionItemIDList) >= IpyGameDataPY.GetFuncCfg("AuctionHouse", 5): + GameWorld.DebugLog("关注拍品数达到上限!", playerID) + return + if itemID in attentionItemIDList: + return True + attentionItemIDList.append(itemID) + attentionObj.AttentionInfo = str(attentionItemIDList) + attentionObj.AttentionLen = len(attentionObj.AttentionInfo) + return True + +def DelPlayerAuctionAttention(attentionMgr, playerID, itemID): + ## 删除玩家关注的物品ID + if playerID not in attentionMgr.playerAttentionDict: + return + attentionObj = attentionMgr.playerAttentionDict[playerID] + attentionItemIDList = attentionObj.AttentionItemIDList + if itemID not in attentionItemIDList: + return + attentionItemIDList.remove(itemID) + attentionObj.AttentionInfo = str(attentionItemIDList) + attentionObj.AttentionLen = len(attentionObj.AttentionInfo) + return True + +def OnLoadAuctionAttentionDataEx(attentionData): + ## 加载拍卖关注表时附加处理 + __InitAuctionAttentionAttrEx(attentionData) + return + +def __InitAuctionAttentionAttrEx(attentionData): + ## 初始化拍卖关注实例附加属性 + setattr(attentionData, "AttentionItemIDList", [] if not attentionData.AttentionInfo else json.loads(attentionData.AttentionInfo)) + return + +##------------------------------------------------------------------------------------------------- + +def OnLoadAuctionItemDataEx(dbData): + ## 加载拍卖物品表时附加处理 + __InitAuctionItemAttrEx(dbData) + playerID = dbData.PlayerID + familyID = dbData.FamilyID + bidderID = dbData.BidderID - def __init__(self): + pyAuctionItemMgr = PyDataManager.GetAuctionItemManager() + pyAuctionItemMgr.allAuctionItemByEndTimeList.append(dbData) + + if dbData.AuctionType == AuctionType_World: + pyAuctionItemMgr.worldAuctionItemList.append(dbData) + + if familyID: + familyItemList = pyAuctionItemMgr.familyAuctionItemDict.get(familyID, []) + familyItemList.append(dbData) + pyAuctionItemMgr.familyAuctionItemDict[familyID] = familyItemList + + if playerID: + myItemList = pyAuctionItemMgr.myAuctionItemDict.get(playerID, []) + myItemList.append(dbData) + pyAuctionItemMgr.myAuctionItemDict[playerID] = myItemList + + if str(playerID) in dbData.BidderIDInfo: + if playerID == bidderID: + nowBidItemList = pyAuctionItemMgr.nowBiddingAuctionItemDict.get(playerID, []) + nowBidItemList.append(dbData) + pyAuctionItemMgr.nowBiddingAuctionItemDict[playerID] = nowBidItemList + else: + hisBidItemList = pyAuctionItemMgr.hisBiddingAuctionItemDict.get(playerID, []) + hisBidItemList.append(dbData) + pyAuctionItemMgr.hisBiddingAuctionItemDict[playerID] = hisBidItemList + + return + +def OnLoadAuctionItemDataOK(): + ## 加载拍卖物品表完成后的处理 + __SortAuctionitem() + return + +def __InitAuctionItemAttrEx(auctionItem, ipyData=None): + ## 初始化拍品实例附加属性 + if not ipyData: + ipyData = IpyGameDataPY.GetIpyGameData("AuctionItem", auctionItem.ItemID) + setattr(auctionItem, "Sortpriority", 99999 - (0 if not ipyData else ipyData.GetSortpriority())) # 排序优先级归组 + setattr(auctionItem, "BiddingQueryID", 0) # 当前正在竞价的玩家ID + setattr(auctionItem, "BiddingQueryTick", 0) # 当前正在竞价的tick + setattr(auctionItem, "EndTime", 0) # 结束竞价time值 + + __SetAuctionItemEndTime(auctionItem, ipyData) + return True + +def __SetAuctionItemEndTime(auctionItem, ipyData): + ## 更新拍品结束竞价time值 + if not ipyData: + return + addTimeStr = auctionItem.AddTime + auctionType = auctionItem.AuctionType + addTime = GameWorld.ChangeTimeStrToNum(addTimeStr) + noticeMinutes = ipyData.GetNoticeSaleMinutes() + saleMinutes = ipyData.GetFamilySaleMinutes() if auctionType == AuctionType_Family else ipyData.GetWorldSaleMinutes() + auctionItem.EndTime = addTime + (noticeMinutes + saleMinutes) * 60 + + __AddAuctionItemEndTimeByBid(auctionItem) + return + +def __AddAuctionItemEndTimeByBid(auctionItem): + # 根据最后一次竞价时间进行加时 + if not auctionItem.BidderPrice: + return + bidTime = GameWorld.ChangeTimeStrToNum(auctionItem.BiddingTime) + endTime = bidTime + IpyGameDataPY.GetFuncCfg("AuctionHouse", 4) + if endTime < auctionItem.EndTime: + return + auctionItem.EndTime = endTime + return True + +def __GetAuctionItemDRDict(auctionItem): + drDict = {"GUID":auctionItem.ItemGUID, "PlayerID":auctionItem.PlayerID, "FamilyID":auctionItem.FamilyID, + "ItemID":auctionItem.ItemID, "Count":auctionItem.Count, "AuctionType":auctionItem.AuctionType, + "AddTime":auctionItem.AddTime, "BiddingTime":auctionItem.BiddingTime, "BidderID":auctionItem.BidderID, + "BidderPrice":auctionItem.BidderPrice, "UserData":auctionItem.UserData, + "EndTime":"" if not auctionItem.EndTime else GameWorld.ChangeTimeNumToStr(auctionItem.EndTime), + "FamilyPlayerIDInfo":auctionItem.FamilyPlayerIDInfo, "BidderIDInfo":auctionItem.BidderIDInfo} + return drDict + +def GetAuctionItem(itemGUID): + ## 获取拍品实例 + return PyDataManager.GetAuctionItemManager().allAuctionItemDict.get(itemGUID) + +def GetPlayerAuctionItemList(playerID): + ## 玩家拍卖中的拍品列表 + return PyDataManager.GetAuctionItemManager().myAuctionItemDict.get(playerID, []) + +def GetFamilyAuctionItemList(familyID): + ## 仙盟拍卖中的拍品列表 + return PyDataManager.GetAuctionItemManager().familyAuctionItemDict.get(familyID, []) + +def OnAuctionItemTimeProcess(curTime): + ## 拍卖行拍品定时处理,每秒触发一次 + allAuctionItemByEndTimeList = PyDataManager.GetAuctionItemManager().allAuctionItemByEndTimeList + if not allAuctionItemByEndTimeList: return - ## =========================================================================================== - - # 保存数据 存数据库和realtimebackup - def GetSaveData(self): - savaData = "" - cntData = "" - cnt = 0 + endItemList = [] # 结束竞价的拍品列表 + moveToWorldItemList = [] # 转移到全服拍卖的仙盟拍品列表 + doCount = len(allAuctionItemByEndTimeList) + while doCount > 0 and allAuctionItemByEndTimeList: + doCount -= 1 + auctionItem = allAuctionItemByEndTimeList[0] + if curTime < auctionItem.EndTime: + break + allAuctionItemByEndTimeList.pop(0) - GameWorld.Log("Save AuctionItem count :%s" % cnt) - return CommFunc.WriteDWORD(cntData, cnt) + savaData - - # 从数据库载入数据 - def LoadPyGameData(self, datas, pos, dataslen): - cnt, pos = CommFunc.ReadDWORD(datas, pos) - GameWorld.Log("Load AuctionItem count :%s" % cnt) - - return pos - + # 没有人竞价的仙盟拍品 + if not auctionItem.BidderPrice and auctionItem.FamilyID and auctionItem.AuctionType == AuctionType_Family: + moveToWorldItemList.append(auctionItem) + else: + endItemList.append(auctionItem) + + __EndAuctionItem(endItemList, "ByTime") + __MoveFamilyAuctionItemToWorld(moveToWorldItemList) + return +def __MoveFamilyAuctionItemToWorld(auctionItemList): + ## 仙盟拍品转移到全服 + if not auctionItemList: + return + + curTimeStr = GameWorld.GetCurrentDataTimeStr() + attentionMgr = PyDataManager.GetAuctionAttentionManager() + auctionItemMgr = PyDataManager.GetAuctionItemManager() + notifyWorldAddItemList = [] # 新增全服拍品通知 [[itemGUID, itemID, playerID], ...] + + for auctionItem in auctionItemList: + itemGUID = auctionItem.ItemGUID + itemID = auctionItem.ItemID + itemCount = auctionItem.Count + playerID = auctionItem.PlayerID + familyID = auctionItem.FamilyID + + ipyData = IpyGameDataPY.GetIpyGameData("AuctionItem", itemID) + auctionItem.AuctionType = AuctionType_World + auctionItem.AddTime = curTimeStr + __SetAuctionItemEndTime(auctionItem, ipyData) + + auctionItemMgr.allAuctionItemByEndTimeList.append(auctionItem) + auctionItemMgr.worldAuctionItemList.append(auctionItem) + notifyWorldAddItemList.append([itemGUID, itemID, playerID]) + + # 添加进我的关注 + for attentionPlayerID, attentionList in auctionItemMgr.myAttentionItemDict.items(): + if itemID not in GetPlayerAuctionAttention(attentionMgr, attentionPlayerID): + continue + if auctionItem not in attentionList: + attentionList.append(auctionItem) + + if ipyData.GetNeedWorldNotify(): + PlayerControl.WorldNotify(0, "Paimai4", [itemID, ipyData.GetNoticeSaleMinutes()]) + + drDict = {"AuctionItemInfo":__GetAuctionItemDRDict(auctionItem)} + DR_AuctionHouse(None, "FamilyToWorld", drDict) + + GameWorld.DebugLog("仙盟拍品转移到全服: itemID=%s,itemCount=%s,familyID=%s,itemGUID=%s" + % (itemID, itemCount, familyID, itemGUID)) + + __SortAuctionitem() + __SyncRefreshAuctionItem(auctionItemList) + __NotifyAuctionPlayerAddItem(notifyWorldAddItemList) + return + +def __SortAuctionitem(isSortWorldItem=True): + ''' 刷新全部拍品排序 + 后端排序 + 1.全服拍品: 因为全服拍品数量比较大,采用只查询指定个数拍品,所以只能由后端排序后同步 + 2.全部拍品竞价结束时间:后端需要处理竞价结束 + + 前端排序: + 1.个人拍品:个数较少,全部同步,由前端自己排序 + 2.仙盟拍品:个数较少,全部同步,由前端自己排序 + 3.竞价拍品:个数较少,全部同步,由前端自己整合排序,区分最高竞价、历史竞价 + 4.关注拍品:个数较少,全部同步,由前端自己排序 + + 触发排序时机: + 1-上架新全服拍品 + 2-仙盟拍品转移全服拍品,相当于上架新全服拍品 + 3-竞价拍品触发加时时,需要对结束时间重排,竞价加时的只触发加时,对全服拍品的排序没有影响,故可不重拍全服拍品 + ''' + auctionItemMgr = PyDataManager.GetAuctionItemManager() + auctionItemMgr.allAuctionItemByEndTimeList.sort(key=operator.attrgetter("EndTime")) + if isSortWorldItem: + auctionItemMgr.worldAuctionItemList.sort(key=operator.attrgetter("Sortpriority", "AddTime")) + auctionItemMgr.worldAuctionItemQueryDict = {} # 重置全服拍品条件查询,下次有玩家查询时再重新刷新 + return + +def __EndAuctionItem(endItemList, endEvent): + ''' 结束拍品竞拍 + @param delItemStateDict: 删除的拍品竞拍状态 + ''' + if not endItemList: + return 0 + + auctionItemMgr = PyDataManager.GetAuctionItemManager() + clearAuctionItemList = [] + for auctionItem in endItemList: + if not auctionItem: + continue + + itemGUID = auctionItem.ItemGUID + itemID = auctionItem.ItemID + itemCount = auctionItem.Count + playerID = auctionItem.PlayerID + familyID = auctionItem.FamilyID + bidderID = auctionItem.BidderID # 当前竞价玩家ID + bidderPrice = auctionItem.BidderPrice # 当前竞价,有人竞价的话代表竞拍成功 + endType = "" + # 有人竞价,成交 + if bidderID and bidderPrice: + endType = "OK" + + # 竞拍成功邮件,发放物品 + paramList = [bidderPrice] + detail = {"ItemGUID":itemGUID} + addItemList = [{"ItemID":itemID, "Count":itemCount, "IsBind":True, "UserData":auctionItem.UserData}] + PlayerCompensation.SendMailByKey("PaimaiMail3", [bidderID], addItemList, paramList, detail=detail) + AddAuctionRecord(auctionItem, AuctionRecordResult_BidOK) + + # 拍卖成功收益,都以玩家收益向上取整 + if familyID and auctionItem.FamilyPlayerIDInfo: + familyPlayerIDList = json.loads(auctionItem.FamilyPlayerIDInfo) + taxRate = IpyGameDataPY.GetFuncCfg("AuctionTaxrate", 2) # 仙盟拍品税率百分比 + personMaxRate = IpyGameDataPY.GetFuncCfg("AuctionTaxrate", 3) # 仙盟拍品个人最大收益百分比 + giveTotalGold = int(math.ceil(bidderPrice * (100 - taxRate) / 100.0)) + giveMaxGold = int(math.ceil(giveTotalGold * personMaxRate / 100.0)) + memCount = len(familyPlayerIDList) + giveGoldAverage = min(giveMaxGold, int(math.ceil(giveTotalGold * 1.0 / memCount))) # 有收益的人平分 + + # 仙盟拍品收益邮件 + detail = {"ItemGUID":itemGUID, "ItemID":itemID, "Count":itemCount, "BidderPrice":bidderPrice, "FamilyPlayerIDList":familyPlayerIDList, + ChConfig.Def_MailMoneySource:ChConfig.Def_GiveMoney_AuctionGain} + paramList = [itemID, auctionItem.BidderName, bidderPrice, taxRate, giveGoldAverage, personMaxRate] + PlayerCompensation.SendMailByKey("PaimaiMail6", familyPlayerIDList, [], paramList, gold=giveGoldAverage, detail=detail) + + elif playerID: + taxRate = IpyGameDataPY.GetFuncCfg("AuctionTaxrate", 1) # 全服拍品税率百分比 + givePlayerGold = int(math.ceil(bidderPrice * (100 - taxRate) / 100.0)) + + # 个人拍卖收益邮件 + detail = {"ItemGUID":itemGUID, "ItemID":itemID, "Count":itemCount, "BidderPrice":bidderPrice, + ChConfig.Def_MailMoneySource:ChConfig.Def_GiveMoney_AuctionGain} + paramList = [itemID, auctionItem.BidderName, bidderPrice, taxRate, givePlayerGold] + PlayerCompensation.SendMailByKey("PaimaiMail5", [playerID], [], paramList, gold=givePlayerGold, detail=detail) + + AddAuctionRecord(auctionItem, AuctionRecordResult_SellOK) + else: + # 仙盟拍品回收 + if familyID: + endType = "Recycle" + AddAuctionRecord(auctionItem, AuctionRecordResult_Recycle) + # 个人拍品流拍,物品返还 + else: + endType = "Return" + + # 流拍返还物品邮件 + paramList = [] + detail = {"ItemGUID":itemGUID} + addItemList = [{"ItemID":itemID, "Count":itemCount, "IsBind":True, "UserData":auctionItem.UserData}] + PlayerCompensation.SendMailByKey("PaimaiMail4", [playerID], addItemList, paramList, detail=detail) + + AddAuctionRecord(auctionItem, AuctionRecordResult_SellFail) + + drDict = {"AuctionItemInfo":__GetAuctionItemDRDict(auctionItem), "EndType":endType, "EndEvent":endEvent} + DR_AuctionHouse(None, "EndAuctionItem", drDict) + + GameWorld.DebugLog("结束竞拍: itemID=%s,itemCount=%s,familyID=%s,endType=%s,endEvent=%s,itemGUID=%s" + % (itemID, itemCount, familyID, endType, endEvent, itemGUID), playerID) + + auctionItemMgr.allAuctionItemDict.pop(itemGUID, None) + + if auctionItem in auctionItemMgr.allAuctionItemByEndTimeList: + auctionItemMgr.allAuctionItemByEndTimeList.remove(auctionItem) + + if auctionItem in auctionItemMgr.worldAuctionItemList: + auctionItemMgr.worldAuctionItemList.remove(auctionItem) + + for queryItemList in auctionItemMgr.worldAuctionItemQueryDict.values(): + if auctionItem in queryItemList: + queryItemList.remove(auctionItem) + + if familyID and familyID in auctionItemMgr.familyAuctionItemDict: + familyItemList = auctionItemMgr.familyAuctionItemDict[familyID] + if auctionItem in familyItemList: + familyItemList.remove(auctionItem) + + for nowBiddingItemList in auctionItemMgr.nowBiddingAuctionItemDict.values(): + if auctionItem in nowBiddingItemList: + nowBiddingItemList.remove(auctionItem) + + for hisBiddingItemList in auctionItemMgr.hisBiddingAuctionItemDict.values(): + if auctionItem in hisBiddingItemList: + hisBiddingItemList.remove(auctionItem) + + if playerID and playerID in auctionItemMgr.myAuctionItemDict: + playerItemList = auctionItemMgr.myAuctionItemDict[playerID] + if auctionItem in playerItemList: + playerItemList.remove(auctionItem) + + for attentionItemList in auctionItemMgr.myAttentionItemDict.values(): + if auctionItem in attentionItemList: + attentionItemList.remove(auctionItem) + + clearItem = ChPyNetSendPack.tagGCClearAuctionItem() + clearItem.ItemGUID = itemGUID + clearAuctionItemList.append(clearItem) + + if not clearAuctionItemList: + return 0 + clearCount = len(clearAuctionItemList) + + clientPack = ChPyNetSendPack.tagGCClearAuctionItemInfo() + clientPack.ClearAuctionItemList = clearAuctionItemList + clientPack.ClearCount = len(clientPack.ClearAuctionItemList) + + playerManager = GameWorld.GetPlayerManager() + for i in xrange(playerManager.GetActivePlayerCount()): + player = playerManager.GetActivePlayerAt(i) + if player == None: + continue + if PlayerControl.GetIsTJG(player): + continue + NetPackCommon.SendFakePack(player, clientPack) + + return clearCount + +def MapServer_AuctionHouseLogic(curPlayer, msgList, tick): + ## 地图玩家拍卖处理 + + playerID = 0 if not curPlayer else curPlayer.GetPlayerID() + queryType, queryData = msgList + result = [] + + GameWorld.Log("收到地图拍卖行信息: queryType=%s,queryData=%s" % (queryType, queryData), playerID) + if not GetAuctionHouseState(): + if curPlayer: + PlayerControl.NotifyCode(curPlayer, "AuctionHouseClose") + return + + # 查询玩家可否上架 + if queryType == "AddAuctionItemQuery": + canSell = __CheckPlayerCanAddAuctionItem(curPlayer) + if not canSell: + return + result = [canSell] + + # 执行上架物品 + elif queryType == "AddAuctionItem": + addAuctionItemList = queryData + __AddAuctionItemByList(curPlayer, addAuctionItemList) + return + + # 查询玩家可否竞价物品 + elif queryType == "BidAuctionItemQuery": + itemGUID, biddingPrice = queryData + itemID, errInfo = __DoPlayerBidAuctionItem(curPlayer, itemGUID, biddingPrice, tick, True) + GameWorld.DebugLog(" itemID=%s,errInfo=%s" % (itemID, errInfo), playerID) + if errInfo: + return + if not itemID: + return + result = [itemID] + + # 执行玩家竞价物品 + elif queryType == "BidAuctionItem": + itemGUID, biddingPrice = queryData + itemID, errInfo = __DoPlayerBidAuctionItem(curPlayer, itemGUID, biddingPrice, tick, False) + if errInfo: + GameWorld.DebugLog(" errInfo=%s" % errInfo, playerID) + drDict = {"ItemGUID":itemGUID, "BiddingPrice":biddingPrice, "ErrInfo":errInfo} + DR_AuctionHouse(curPlayer, "BidAuctionItemError", drDict) + + return + + elif queryType == "ClearAuctionItem": + __DoGMClearAuctionItem(curPlayer) + return + + elif queryType == "PrintAuctionItem": + __DoGMPrintAuctionItem(curPlayer) + return + + resultMsg = str([queryType, queryData, result]) + if curPlayer: + curPlayer.MapServer_QueryPlayerResult(0, 0, "AuctionHouse", resultMsg, len(resultMsg)) + return + +def __CheckPlayerCanAddAuctionItem(curPlayer): + ## 检查玩家可否上架拍品 + playerID = curPlayer.GetPlayerID() + maxSellCount = IpyGameDataPY.GetFuncCfg("AuctionHouse", 2) + if maxSellCount: + playerAuctionItemList = GetPlayerAuctionItemList(playerID) + playerSellCount = len(playerAuctionItemList) + canSell = playerSellCount < maxSellCount + if not canSell: + PlayerControl.NotifyCode(curPlayer, "SellCountLimit") + return canSell + return True + +def __AddAuctionItemByList(curPlayer, addAuctionItemList): + ''' 批量添加拍品 + @param curPlayer: 可能为None + ''' + + notifyWorldAddItemList = [] # 新增全服拍品通知 [[itemGUID, itemID, playerID], ...] + notifyFamilyAddItemDict = {} # 新增仙盟拍品通知 {familyID:[auctionItem, ...], ...} + for playerID, familyID, familyPlayerIDList, itemData in addAuctionItemList: + if not playerID and not familyID: + continue + + auctionItem = __DoAddAuctionItem(curPlayer, playerID, familyID, familyPlayerIDList, itemData) + if not auctionItem: + continue + + if familyID: + familyAddItemList = notifyFamilyAddItemDict.get(familyID, []) + familyAddItemList.append(auctionItem) + notifyFamilyAddItemDict[familyID] = familyAddItemList + else: + itemGUID = auctionItem.ItemGUID + itemID = auctionItem.ItemID + notifyWorldAddItemList.append([itemGUID, itemID, playerID]) + + if notifyFamilyAddItemDict or notifyWorldAddItemList: + isSortWorldItem = notifyWorldAddItemList != [] + __SortAuctionitem(isSortWorldItem=isSortWorldItem) + + # 通知新增仙盟拍品 + for familyID, familyAddItemList in notifyFamilyAddItemDict.items(): + Sync_FamilyAuctionItemInfo(None, familyID, familyAddItemList) + + # 通知全服拍品关注玩家 + __NotifyAuctionPlayerAddItem(notifyWorldAddItemList) + return + +def __DoAddAuctionItem(curPlayer, playerID, familyID, familyPlayerIDList, itemData): + ## 添加拍品 + itemID = itemData.get("ItemID", 0) + ipyData = IpyGameDataPY.GetIpyGameData("AuctionItem", itemID) + if not ipyData: + return + + itemGUID = itemData.get("GUID", "") + auctionItem = PyGameDataStruct.tagDBAuctionItem() + auctionItem.ItemGUID = itemGUID + auctionItem.PlayerID = playerID + auctionItem.FamilyID = familyID + auctionItem.ItemID = itemID + auctionItem.Count = itemData.get("ItemCount", 0) + auctionItem.AddTime = GameWorld.GetCurrentDataTimeStr() + auctionItem.ItemType = itemData.get("ItemType", 0) + auctionItem.ItemJobLimit = itemData.get("ItemJobLimit", 0) + auctionItem.ItemClassLV = itemData.get("ItemClassLV", 0) + auctionItem.UserData = itemData.get("UserData", "") + auctionItem.UserDataLen = len(auctionItem.UserData) + auctionItem.FamilyPlayerIDInfo = str(familyPlayerIDList) + auctionItem.FamilyPlayerIDLen = len(auctionItem.FamilyPlayerIDInfo) + + if not __InitAuctionItemAttrEx(auctionItem): + return + + auctionItemMgr = PyDataManager.GetAuctionItemManager() + auctionItemMgr.allAuctionItemDict[auctionItem.ItemGUID] = auctionItem + auctionItemMgr.allAuctionItemByEndTimeList.append(auctionItem) + + if familyID: + auctionItem.AuctionType = AuctionType_Family + familyItemList = auctionItemMgr.familyAuctionItemDict.get(familyID, []) + familyItemList.append(auctionItem) + auctionItemMgr.familyAuctionItemDict[familyID] = familyItemList + else: + auctionItem.AuctionType = AuctionType_World + auctionItemMgr.worldAuctionItemList.append(auctionItem) + + # 添加进我的拍卖 + if playerID: + myAuctionItemList = auctionItemMgr.myAuctionItemDict.get(playerID, []) + myAuctionItemList.append(auctionItem) + auctionItemMgr.myAuctionItemDict[playerID] = myAuctionItemList + if curPlayer: + Sync_PlayerAuctionItemInfo(curPlayer, auctionItem) + + # 添加进我的关注 + attentionMgr = PyDataManager.GetAuctionAttentionManager() + for attentionPlayerID, attentionList in auctionItemMgr.myAttentionItemDict.items(): + if itemID not in GetPlayerAuctionAttention(attentionMgr, attentionPlayerID): + continue + if auctionItem not in attentionList: + attentionList.append(auctionItem) + + if ipyData.GetNeedWorldNotify(): + PlayerControl.WorldNotify(0, "Paimai4", [itemID, ipyData.GetNoticeSaleMinutes()]) + + drDict = {"AuctionItemInfo":__GetAuctionItemDRDict(auctionItem)} + DR_AuctionHouse(curPlayer, "AddAuctionItem", drDict) + GameWorld.DebugLog("上架拍品: playerID=%s,familyID=%s,%s" % (playerID, familyID, drDict), playerID) + GameWorld.DebugLog("更新拍品数: %s" % len(auctionItemMgr.allAuctionItemDict)) + return auctionItem + +def __NotifyAuctionPlayerAddItem(notifyWorldAddItemList): + ## 通知关注物品的玩家新上架物品了 + if not notifyWorldAddItemList: + return + attentionMgr = PyDataManager.GetAuctionAttentionManager() + playerManager = GameWorld.GetPlayerManager() + for i in xrange(playerManager.GetActivePlayerCount()): + player = playerManager.GetActivePlayerAt(i) + if player == None: + continue + if PlayerControl.GetIsTJG(player): + continue + playerAttentionIDList = GetPlayerAuctionAttention(attentionMgr, player.GetPlayerID()) + if not playerAttentionIDList: + continue + infoPack = None + for itemGUID, itemID, playerID in notifyWorldAddItemList: + if playerID == player.GetPlayerID(): + # 自己上架的物品不通知 + continue + if itemID not in playerAttentionIDList: + continue + if not infoPack: + infoPack = ChPyNetSendPack.tagGCAddAuctionItemInfo() + itemInfo = ChPyNetSendPack.tagGCAddAuctionItem() + itemInfo.ItemGUID = itemGUID + itemInfo.ItemID = itemID + infoPack.AddAuctionItemList.append(itemInfo) + + if infoPack: + infoPack.AddCount = len(infoPack.AddAuctionItemList) + NetPackCommon.SendFakePack(player, infoPack) + return + +def __DoPlayerBidAuctionItem(curPlayer, itemGUID, biddingPrice, tick, isOnlyCheck): + ''' 玩家竞价物品 + @param curPlayer: 竞价的玩家 + @param itemGUID: 拍品GUID + @param biddingPrice: 竞价 + @param isOnlyCheck: 是否仅检查可否竞价 + ''' + + errInfo = "" + itemID = 0 + + auctionItem = GetAuctionItem(itemGUID) + if not auctionItem: + # 拍品不存在 + PlayerControl.NotifyCode(curPlayer, "Paimai3") + errInfo = "not auctionItem" + return itemID, errInfo + itemID = auctionItem.ItemID + ipyData = IpyGameDataPY.GetIpyGameData("AuctionItem", itemID) + if not ipyData: + errInfo = "not ipyData" + return itemID, errInfo + playerID = curPlayer.GetPlayerID() + addTimeStr = auctionItem.AddTime + auctionType = auctionItem.AuctionType # 0-全服拍品,1-仙盟拍品 + addTime = GameWorld.ChangeTimeStrToNum(addTimeStr) + curTime = int(time.time()) + passMinutes = (curTime - addTime) / 60 + noticeMinutes = ipyData.GetNoticeSaleMinutes() + if passMinutes < noticeMinutes: + GameWorld.ErrLog("拍品尚未开放竞价! itemGUID=%s,itemID=%s,addTimeStr=%s" % (itemGUID, itemID, addTimeStr), playerID) + errInfo = "in notice time" + return itemID, errInfo + if auctionType == AuctionType_Family: + itemFamilyID = auctionItem.FamilyID + playerFamilyID = curPlayer.GetFamilyID() + if not playerFamilyID or playerFamilyID != itemFamilyID: + GameWorld.ErrLog("该拍品为仙盟私有拍品,非本仙盟人员不可竞拍! itemGUID=%s,itemID=%s,itemFamilyID=%s,playerFamilyID=%s" + % (itemGUID, itemID, itemFamilyID, playerFamilyID), playerID) + errInfo = "is family auction item" + return itemID, errInfo + 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 = nextPrice if not buyoutPrice else min(nextPrice, buyoutPrice) # 不超过一口价 + if not (biddingPrice == nextPrice or (buyoutPrice and biddingPrice == buyoutPrice)): + # 竞价价格错误 + PlayerControl.NotifyCode(curPlayer, "Paimai2") + errInfo = "bid price error! biddingPrice=%s,nextPrice=%s,buyoutPrice=%s,itemGUID=%s,itemID=%s" % (biddingPrice, nextPrice, buyoutPrice, itemGUID, itemID) + return itemID, errInfo + + if isOnlyCheck: + queryTick = auctionItem.BiddingQueryTick + if queryTick and tick - queryTick < 10000: + # 有玩家正在竞价,请稍等 + PlayerControl.NotifyCode(curPlayer, "Paimai1") + errInfo = "other player bidding" + return itemID, errInfo + auctionItem.BiddingQueryID = playerID + auctionItem.BiddingQueryTick = tick + return itemID, errInfo + + if auctionItem.BiddingQueryID != playerID: + PlayerControl.NotifyCode(curPlayer, "Paimai2") + errInfo = "bidding player error" + return itemID, errInfo + + lastBidderID = auctionItem.BidderID + lastBidderPrice = auctionItem.BidderPrice + itemCount = auctionItem.Count + + isBuyout = buyoutPrice and biddingPrice >= buyoutPrice # 大于等于一口价,直接成交 + + auctionItemMgr = PyDataManager.GetAuctionItemManager() + nowBiddingAuctionItemDict = auctionItemMgr.nowBiddingAuctionItemDict + hisBiddingAuctionItemDict = auctionItemMgr.hisBiddingAuctionItemDict + + # 邮件返还上个竞价者 + if lastBidderID and lastBidderPrice: + detail = {"ItemID":itemID, "ItemGUID":itemGUID, "Count":itemCount, ChConfig.Def_MailMoneySource:ChConfig.Def_GiveMoney_AuctionBidReturn} + if isBuyout: + # 竞拍失败,仅通知 + paramList = [itemID, lastBidderPrice] + PlayerCompensation.SendMailByKey("PaimaiMail2", [lastBidderID], [], paramList, gold=lastBidderPrice, detail=detail) + else: + # 竞拍失败,可继续竞价邮件 + paramList = [itemID, lastBidderPrice, itemGUID] + PlayerCompensation.SendMailByKey("PaimaiMail1", [lastBidderID], [], paramList, gold=lastBidderPrice, detail=detail) + AddAuctionRecord(auctionItem, AuctionRecordResult_BidFail) + + isSyncBiddingItem = False + nowBiddingAuctionItemList = nowBiddingAuctionItemDict.get(lastBidderID, []) + if auctionItem in nowBiddingAuctionItemList: + nowBiddingAuctionItemList.remove(auctionItem) + nowBiddingAuctionItemDict[lastBidderID] = nowBiddingAuctionItemList + isSyncBiddingItem = True + hisBiddingAuctionItemList = hisBiddingAuctionItemDict.get(lastBidderID, []) + if auctionItem not in hisBiddingAuctionItemList: + hisBiddingAuctionItemList.append(auctionItem) + hisBiddingAuctionItemDict[lastBidderID] = hisBiddingAuctionItemList + isSyncBiddingItem = True + if isSyncBiddingItem: + lastBidder = GameWorld.GetPlayerManager().FindPlayerByID(lastBidderID) + if lastBidder and not PlayerControl.GetIsTJG(lastBidder): + Sync_PlayerBiddingItemInfo(lastBidder, auctionItem) + + # 更新竞价信息 + auctionItem.BiddingQueryID = 0 + auctionItem.BiddingTick = 0 + auctionItem.BiddingTime = GameWorld.GetCurrentDataTimeStr() + auctionItem.BidderID = playerID + auctionItem.BidderName = curPlayer.GetName() + auctionItem.BidderPrice = biddingPrice + isSyncBiddingItem = False + nowBiddingAuctionItemList = nowBiddingAuctionItemDict.get(playerID, []) + if auctionItem not in nowBiddingAuctionItemList: + nowBiddingAuctionItemList.append(auctionItem) + nowBiddingAuctionItemDict[playerID] = nowBiddingAuctionItemList + isSyncBiddingItem = True + hisBiddingAuctionItemList = hisBiddingAuctionItemDict.get(playerID, []) + if auctionItem in hisBiddingAuctionItemList: + hisBiddingAuctionItemList.remove(auctionItem) + hisBiddingAuctionItemDict[playerID] = hisBiddingAuctionItemList + isSyncBiddingItem = True + if isSyncBiddingItem: + Sync_PlayerBiddingItemInfo(curPlayer, auctionItem) + + # 添加历史竞价者 + if str(playerID) not in auctionItem.BidderIDInfo: + auctionItem.BidderIDInfo += "%s|" % playerID + auctionItem.BidderIDLen = len(auctionItem.BidderIDInfo) + + GameWorld.DebugLog("玩家竞价拍品: itemGUID=%s,itemID=%s,isBuyout=%s,lastBidderID=%s,lastBidderPrice=%s,bidderIDInfo=%s" + % (itemGUID, itemID, isBuyout, lastBidderID, lastBidderPrice, auctionItem.BidderIDInfo), playerID) + + if isBuyout: + __EndAuctionItem([auctionItem], "Buyout") + else: + if __AddAuctionItemEndTimeByBid(auctionItem): + __SortAuctionitem(isSortWorldItem=False) + + drDict = {"AuctionItemInfo":__GetAuctionItemDRDict(auctionItem)} + DR_AuctionHouse(curPlayer, "BidAuctionItem", drDict) + + __SyncRefreshAuctionItem([auctionItem]) + + return itemID, errInfo + +def __SyncRefreshAuctionItem(auctionItemList): + ''' // B5 08 拍卖行刷新拍品 #tagGCRefreshAuctionItemInfo + 1-仙盟拍品转移到全服时通知; 2-拍品有人竞价时刷新 + ''' + + refreshAuctionItemList = [] + + for auctionItem in auctionItemList: + refreshItem = ChPyNetSendPack.tagGCRefreshAuctionItem() + refreshItem.ItemGUID = auctionItem.ItemGUID + refreshItem.AuctionType = auctionItem.AuctionType + refreshItem.AddTime = auctionItem.AddTime + refreshItem.BidderID = auctionItem.BidderID + refreshItem.BidderPrice = auctionItem.BidderPrice + refreshAuctionItemList.append(refreshItem) + + if not refreshAuctionItemList: + return + + clientPack = ChPyNetSendPack.tagGCRefreshAuctionItemInfo() + clientPack.RefreshAuctionItemList = refreshAuctionItemList + clientPack.RefreshCount = len(clientPack.RefreshAuctionItemList) + playerManager = GameWorld.GetPlayerManager() + for i in xrange(playerManager.GetActivePlayerCount()): + player = playerManager.GetActivePlayerAt(i) + if player == None: + continue + if PlayerControl.GetIsTJG(player): + continue + NetPackCommon.SendFakePack(player, clientPack) + + return + +def __DoGMClearAuctionItem(curPlayer): + if curPlayer.GetGMLevel() != 90: + return + + allAuctionItemByEndTimeList = PyDataManager.GetAuctionItemManager().allAuctionItemByEndTimeList + if not allAuctionItemByEndTimeList: + GameWorld.DebugAnswer(curPlayer, "当前没有拍品!") + return + + endItemList = [] + for auctionItem in allAuctionItemByEndTimeList: + endItemList.append(auctionItem) + + clearCount = __EndAuctionItem(endItemList, "GMClear") + + GameWorld.DebugAnswer(curPlayer, "清空拍品数=%s" % clearCount) + return + +def __DoGMPrintAuctionItem(curPlayer): + if curPlayer.GetGMLevel() != 90: + return + + auctionItemMgr = PyDataManager.GetAuctionItemManager() + allAuctionItemByEndTimeList = auctionItemMgr.allAuctionItemByEndTimeList + GameWorld.DebugLog("TimeList总拍品数: =%s" % len(allAuctionItemByEndTimeList)) + for i, auctionItem in enumerate(allAuctionItemByEndTimeList): + GameWorld.DebugLog(" i=%s, %s" % (i, __GetAuctionItemDRDict(auctionItem))) + + GameWorld.DebugLog("AllDict总拍品数: =%s" % len(auctionItemMgr.allAuctionItemDict)) + + GameWorld.DebugLog("全服拍品个数: =%s" % len(auctionItemMgr.worldAuctionItemList)) + for familyID, familyItemList in auctionItemMgr.familyAuctionItemDict.items(): + GameWorld.DebugLog("仙盟拍品个数: familyID=%s, %s" % (familyID, len(familyItemList))) + + for playerID, myItemList in auctionItemMgr.myAuctionItemDict.items(): + GameWorld.DebugLog("玩家拍品个数: playerID=%s, %s" % (playerID, len(myItemList))) + + for playerID, nowBiddingItemList in auctionItemMgr.nowBiddingAuctionItemDict.items(): + GameWorld.DebugLog("玩家最高竞价拍品个数: playerID=%s, %s" % (playerID, len(nowBiddingItemList))) + + for playerID, hisBiddingItemList in auctionItemMgr.hisBiddingAuctionItemDict.items(): + GameWorld.DebugLog("玩家历史竞价拍品个数: playerID=%s, %s" % (playerID, len(hisBiddingItemList))) + + for playerID, attentionItemList in auctionItemMgr.myAttentionItemDict.items(): + GameWorld.DebugLog("玩家关注拍品个数: playerID=%s, %s" % (playerID, len(attentionItemList))) + + return + +#// B5 10 拍卖行查询拍卖中的物品 #tagCGQueryAuctionItem +# +#struct tagCGQueryAuctionItem +#{ +# tagHead Head; +# BYTE Job; //过滤职业,0为不限制 +# BYTE ItemTypeCount; +# DWORD ItemTypeList[ItemTypeCount]; //指定的物品类型 +# BYTE ClassLV; //过滤阶数,0为不限制 +# BYTE SpecItemIDCount; //指定物品ID个数 +# DWORD SpecItemIDList[SpecItemIDCount]; //指定物品ID +# char FromItemGUID[40]; //从哪个物品开始查询 +# BYTE QueryDir; //查询方向,1-往后查,2-往前查 +# BYTE QueryCount; //查询个数,0为全部 +#}; +def OnQueryAuctionItem(index, clientData, tick): + curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + job = clientData.Job + itemTypeList = clientData.ItemTypeList + classLV = clientData.ClassLV + specItemIDList = clientData.SpecItemIDList + fromItemGUID = clientData.FromItemGUID + queryDir = clientData.QueryDir + queryCount = clientData.QueryCount + __Sync_WorldAuctionItemQueryResult(curPlayer, job, itemTypeList, classLV, specItemIDList, fromItemGUID, queryDir, queryCount) + return + +#// B5 17 拍卖行查询定位目标拍品 #tagCGQueryTagAuctionItem +# +#struct tagCGQueryTagAuctionItem +#{ +# tagHead Head; +# char ItemGUID[40]; +# DWORD ItemID; +#}; +def OnQueryTagAuctionItem(index, clientData, tick): + curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + tagItemGUID = clientData.ItemGUID + queryDir = 3 + __Sync_WorldAuctionItemQueryResult(curPlayer, fromItemGUID=tagItemGUID, queryDir=queryDir) + return + +def __Sync_WorldAuctionItemQueryResult(curPlayer, job=0, itemTypeList=[], classLV=0, specItemIDList=[], fromItemGUID="", queryDir=1, queryCount=10): + ## 根据过滤条件同步全服拍品列表,目前仅全服拍品需要通过查询服务器获得,个人拍品及仙盟拍品由于个数较少直接由上线或变更时主动同步 + + fromAuctionItem = None + if fromItemGUID: + fromAuctionItem = GetAuctionItem(fromItemGUID) + if not fromAuctionItem: + GameWorld.DebugLog("查询的目标拍品不存在! fromItemGUID=%s" % fromItemGUID) + PlayerControl.NotifyCode(curPlayer, "Paimai5") + return + + # {(job, (itemType, ...), itemClassLV, (itemID, ...)):[tagDBAuctionItem, ...], ...} + queryKey = (job, tuple(itemTypeList), classLV, tuple(specItemIDList)) + auctionItemMgr = PyDataManager.GetAuctionItemManager() + worldAuctionItemQueryDict = auctionItemMgr.worldAuctionItemQueryDict + if queryKey not in worldAuctionItemQueryDict: + # 载入对应查询条件拍品缓存 + auctionItemQueryList = [] + for worldAuctionItem in auctionItemMgr.worldAuctionItemList: + if job and worldAuctionItem.ItemJobLimit != job: + continue + if itemTypeList and worldAuctionItem.ItemType not in itemTypeList: + continue + if classLV and worldAuctionItem.ItemClassLV != classLV: + continue + if specItemIDList and worldAuctionItem.ItemID not in specItemIDList: + continue + auctionItemQueryList.append(worldAuctionItem) + worldAuctionItemQueryDict[queryKey] = auctionItemQueryList + else: + auctionItemQueryList = worldAuctionItemQueryDict[queryKey] + queryTotalCount = len(auctionItemQueryList) + + fromIndex = 0 + if fromAuctionItem: + if fromAuctionItem not in auctionItemQueryList: + GameWorld.ErrLog("查询的目标拍品不在所在的过滤的条件里! fromItemGUID=%s" % fromItemGUID) + PlayerControl.NotifyCode(curPlayer, "Paimai5") + return + fromIndex = auctionItemQueryList.index(fromAuctionItem) + + # 向前查,其他的默认向后查 + if queryDir == 2: + startIndex = max(0, fromIndex - queryCount + 1) + syncItemList = auctionItemQueryList[startIndex:fromIndex + 1] + queryRemainlCount = startIndex + # 向后查 + else: + syncItemList = auctionItemQueryList[fromIndex:fromIndex + queryCount] + queryRemainlCount = max(0, queryTotalCount - fromIndex - queryCount) + + clientPack = ChPyNetSendPack.tagGCAuctionItemInfo() + clientPack.Job = job + clientPack.ItemTypeList = itemTypeList + clientPack.ItemTypeCount = len(clientPack.ItemTypeList) + clientPack.ClassLV = classLV + clientPack.SpecItemIDList = specItemIDList + clientPack.SpecItemIDCount = len(clientPack.SpecItemIDList) + clientPack.FromItemGUID = fromItemGUID + clientPack.QueryDir = queryDir + clientPack.QueryCount = queryCount + clientPack.QueryRemainlCount = queryRemainlCount + clientPack.AuctionItemList = [] + for auctionItem in syncItemList: + itemInfo = ChPyNetSendPack.tagGCAuctionItem() + itemInfo.ItemGUID = auctionItem.ItemGUID + itemInfo.FamilyID = auctionItem.FamilyID + itemInfo.ItemID = auctionItem.ItemID + itemInfo.ItemCount = auctionItem.Count + itemInfo.AddTime = auctionItem.AddTime + itemInfo.BidderPrice = auctionItem.BidderPrice + itemInfo.UserData = auctionItem.UserData + itemInfo.UserDataLen = auctionItem.UserDataLen + clientPack.AuctionItemList.append(itemInfo) + clientPack.AuctionItemCount = len(clientPack.AuctionItemList) + NetPackCommon.SendFakePack(curPlayer, clientPack) + return + +#// B5 12 拍卖行查询拍卖记录 #tagCGQueryAuctionRecord +# +#struct tagCGQueryAuctionRecord +#{ +# tagHead Head; +# BYTE RecordType; //记录类型 0-我的拍品记录 1-仙盟拍品记录 2-我的竞拍记录 +#}; +def OnQueryAuctionRecord(index, clientData, tick): + curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + recordType = clientData.RecordType + Sync_PlayerAuctionRecordInfo(curPlayer, recordType, None, curPlayer.GetFamilyID()) + return + +#// B5 16 拍卖行查询关注中的拍品 #tagCGQueryAttentionAuctionItem +# +#struct tagCGQueryAttentionAuctionItem +#{ +# tagHead Head; +#}; +def OnQueryAttentionAuctionItem(index, clientData, tick): + curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + playerID = curPlayer.GetPlayerID() + + auctionItemMgr = PyDataManager.GetAuctionItemManager() + myAttentionItemDict = auctionItemMgr.myAttentionItemDict + if playerID in myAttentionItemDict: + attentionItemList = myAttentionItemDict[playerID] + else: + attentionItemList = [] + attentionMgr = PyDataManager.GetAuctionAttentionManager() + attentionItemIDList = GetPlayerAuctionAttention(attentionMgr, playerID) + if attentionItemIDList: + for auctionItem in auctionItemMgr.worldAuctionItemList: + if auctionItem.ItemID not in attentionItemIDList: + continue + attentionItemList.append(auctionItem) + myAttentionItemDict[playerID] = attentionItemList + + clientPack = ChPyNetSendPack.tagGCAttentionAuctionItemInfo() + clientPack.AuctionItemList = [] + for attentionItem in attentionItemList: + itemObj = ChPyNetSendPack.tagGCAttentionAuctionItem() + itemObj.ItemGUID = attentionItem.ItemGUID + itemObj.FamilyID = attentionItem.FamilyID + itemObj.ItemID = attentionItem.ItemID + itemObj.ItemCount = attentionItem.Count + itemObj.AddTime = attentionItem.AddTime + itemObj.BidderPrice = attentionItem.BidderPrice + itemObj.UserData = attentionItem.UserData + itemObj.UserDataLen = attentionItem.UserDataLen + clientPack.AuctionItemList.append(itemObj) + clientPack.AuctionItemCount = len(clientPack.AuctionItemList) + NetPackCommon.SendFakePack(curPlayer, clientPack) + return + +#// B5 18 拍卖行修改关注物品 #tagCGAttentionAuctionItemChange +# +#struct tagCGAttentionAuctionItemChange +#{ +# tagHead Head; +# DWORD ItemID; +# BYTE IsAttention; //是否关注,取消关注发0 +#}; +def OnAttentionAuctionItemChange(index, clientData, tick): + curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index) + playerID = curPlayer.GetPlayerID() + itemID = clientData.ItemID + isAttention = clientData.IsAttention + + attentionMgr = PyDataManager.GetAuctionAttentionManager() + if isAttention: + if not AddPlayerAuctionAttention(attentionMgr, playerID, itemID): + return + else: + if not DelPlayerAuctionAttention(attentionMgr, playerID, itemID): + return + Sync_PlayerAttentionAuctionItemID(curPlayer, True) + + # 关注信息变更,清空关注拍品实例缓存 + auctionItemMgr = PyDataManager.GetAuctionItemManager() + auctionItemMgr.myAttentionItemDict.pop(playerID, None) + return + +def Sync_FamilyAuctionItemInfo(curPlayer, familyID, itemInfoList=[]): + # // B5 05 拍卖行仙盟拍卖中的物品信息 #tagGCFamilyAuctionItemInfo + + if not familyID: + return + + if not itemInfoList: + itemInfoList = GetFamilyAuctionItemList(familyID) + + if not itemInfoList: + return + + itemInfoPack = ChPyNetSendPack.tagGCFamilyAuctionItemInfo() + itemInfoPack.AuctionItemList = [] + for auctionItem in itemInfoList: + packItem = ChPyNetSendPack.tagGCFamilyAuctionItem() + packItem.ItemGUID = auctionItem.ItemGUID + packItem.FamilyID = auctionItem.FamilyID + packItem.ItemID = auctionItem.ItemID + packItem.ItemCount = auctionItem.Count + packItem.AddTime = auctionItem.AddTime + packItem.BidderPrice = auctionItem.BidderPrice + packItem.UserData = auctionItem.UserData + packItem.UserDataLen = auctionItem.UserDataLen + packItem.FamilyPlayerIDInfo = auctionItem.FamilyPlayerIDInfo + packItem.FamilyPlayerIDLen = auctionItem.FamilyPlayerIDLen + packItem.AuctionType = auctionItem.AuctionType + itemInfoPack.AuctionItemList.append(packItem) + itemInfoPack.AuctionItemCount = len(itemInfoPack.AuctionItemList) + + if curPlayer: + NetPackCommon.SendFakePack(curPlayer, itemInfoPack) + else: + PlayerFamily.SendFamilyFakePack(familyID, itemInfoPack) + return + +def Sync_PlayerAuctionItemInfo(curPlayer, auctionItem=None): + # // B5 02 拍卖行玩家拍卖中的物品信息 #tagGCPlayerAuctionItemInfo + + if auctionItem: + syncItemList = [auctionItem] + else: + syncItemList = GetPlayerAuctionItemList(curPlayer.GetPlayerID()) + + if not syncItemList: + return + + itemInfoPack = ChPyNetSendPack.tagGCPlayerAuctionItemInfo() + itemInfoPack.AuctionItemList = [] + for auctionItem in syncItemList: + packItem = ChPyNetSendPack.tagGCPlayerAuctionItem() + packItem.ItemGUID = auctionItem.ItemGUID + packItem.FamilyID = auctionItem.FamilyID + packItem.ItemID = auctionItem.ItemID + packItem.ItemCount = auctionItem.Count + packItem.AddTime = auctionItem.AddTime + packItem.BidderPrice = auctionItem.BidderPrice + packItem.UserData = auctionItem.UserData + packItem.UserDataLen = auctionItem.UserDataLen + itemInfoPack.AuctionItemList.append(packItem) + itemInfoPack.AuctionItemCount = len(itemInfoPack.AuctionItemList) + NetPackCommon.SendFakePack(curPlayer, itemInfoPack) + return + +def Sync_PlayerAuctionRecordInfo(curPlayer, recordType, newRecordData=None, familyID=0): + ## B5 03 拍卖行玩家拍卖记录 #tagGCPlayerAuctionRecordInfo + if recordType == AuctionRecordType_MyAuction and curPlayer: + syncRecordList = [newRecordData] if newRecordData else GetMyAuctionItemRecord(curPlayer.GetPlayerID()) + elif recordType == AuctionRecordType_FamilyAuction and familyID: + syncRecordList = [newRecordData] if newRecordData else GetFamilyAuctionItemRecord(familyID) + elif recordType == AuctionRecordType_MyBid and curPlayer: + syncRecordList = [newRecordData] if newRecordData else GetMyBiddingItemRecord(curPlayer.GetPlayerID()) + else: + return + + clientPack = ChPyNetSendPack.tagGCPlayerAuctionRecordInfo() + clientPack.AuctionRecordList = [] + for recordData in syncRecordList: + record = ChPyNetSendPack.tagGCPlayerAuctionRecord() + record.ItemGUID = recordData.ItemGUID + record.FamilyID = recordData.FamilyID + record.RecordType = recordData.RecordType + record.RecordResult = recordData.RecordResult + record.RecordTime = recordData.RecordTime + record.BidderPrice = recordData.BidderPrice + record.BidderName = recordData.BidderName + record.ItemID = recordData.ItemID + record.ItemCount = recordData.Count + record.UserData = recordData.UserData + record.UserDataLen = recordData.UserDataLen + clientPack.AuctionRecordList.append(record) + clientPack.Count = len(clientPack.AuctionRecordList) + + if curPlayer: + NetPackCommon.SendFakePack(curPlayer, clientPack) + elif familyID and recordType == AuctionRecordType_FamilyAuction: + PlayerFamily.SendFamilyFakePack(familyID, clientPack) + return + +def Sync_PlayerBiddingItemInfo(curPlayer, auctionItem=None): + #// B5 10 拍卖行玩家竞价中的物品信息 #tagGCBiddingItemInfo + # 上线同步、玩家相关的竞价拍品竞价变更时同步 + + if auctionItem: + syncItemList = [auctionItem] + else: + playerID = curPlayer.GetPlayerID() + auctionItemMgr = PyDataManager.GetAuctionItemManager() + nowBiddingAuctionItemList = auctionItemMgr.nowBiddingAuctionItemDict.get(playerID, []) + hisBiddingAuctionItemList = auctionItemMgr.hisBiddingAuctionItemDict.get(playerID, []) + syncItemList = nowBiddingAuctionItemList + hisBiddingAuctionItemList + + if not syncItemList: + return + + itemInfoPack = ChPyNetSendPack.tagGCBiddingItemInfo() + itemInfoPack.AuctionItemList = [] + for auctionItem in syncItemList: + packItem = ChPyNetSendPack.tagGCBiddingItem() + packItem.ItemGUID = auctionItem.ItemGUID + packItem.FamilyID = auctionItem.FamilyID + packItem.ItemID = auctionItem.ItemID + packItem.ItemCount = auctionItem.Count + packItem.AddTime = auctionItem.AddTime + packItem.BidderID = auctionItem.BidderID + packItem.BidderPrice = auctionItem.BidderPrice + packItem.UserData = auctionItem.UserData + packItem.UserDataLen = auctionItem.UserDataLen + itemInfoPack.AuctionItemList.append(packItem) + itemInfoPack.AuctionItemCount = len(itemInfoPack.AuctionItemList) + NetPackCommon.SendFakePack(curPlayer, itemInfoPack) + return + +def Sync_PlayerAttentionAuctionItemID(curPlayer, isForce=False): + # // B5 07 拍卖行关注的物品ID #tagGCAttentionAuctionItemID + attentionMgr = PyDataManager.GetAuctionAttentionManager() + attentionItemIDList = GetPlayerAuctionAttention(attentionMgr, curPlayer.GetPlayerID()) + if not attentionItemIDList and not isForce: + return + clientPack = ChPyNetSendPack.tagGCAttentionAuctionItemID() + clientPack.AttentionItemIDList = attentionItemIDList + clientPack.AttentionCount = len(clientPack.AttentionItemIDList) + NetPackCommon.SendFakePack(curPlayer, clientPack) + return + +def DR_AuctionHouse(curPlayer, eventName, drDict): + accID = "" if not curPlayer else curPlayer.GetAccID() + playerID = 0 if not curPlayer else curPlayer.GetPlayerID() + dataDict = {"EventName":eventName, "PlayerID":playerID, "AccID":accID} + dataDict.update(drDict) + DataRecordPack.SendEventPack("AuctionHouse", dataDict, curPlayer) + return -- Gitblit v1.8.0