diff options
-rw-r--r-- | src/server/game/AuctionHouse/AuctionHouseMgr.cpp | 43 | ||||
-rw-r--r-- | src/server/game/AuctionHouse/AuctionHouseMgr.h | 11 | ||||
-rw-r--r-- | src/server/game/Handlers/AuctionHouseHandler.cpp | 8 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 7 | ||||
-rw-r--r-- | src/server/game/World/World.h | 2 | ||||
-rw-r--r-- | src/server/worldserver/worldserver.conf.dist | 18 |
6 files changed, 79 insertions, 10 deletions
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index f3c20750069..035d9af4369 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -573,6 +573,14 @@ void AuctionHouseObject::Update() if (AuctionsMap.empty()) return; + // Clear expired throttled players + for (PlayerGetAllThrottleMap::const_iterator itr = GetAllThrottleMap.begin(); itr != GetAllThrottleMap.end();) + { + if (itr->second <= curTime) + itr = GetAllThrottleMap.erase(itr); + else + ++itr; + } SQLTransaction trans = CharacterDatabase.BeginTransaction(); @@ -648,13 +656,40 @@ void AuctionHouseObject::BuildListOwnerItems(WorldPacket& data, Player* player, void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player, std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable, uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, - uint32& count, uint32& totalcount) + uint32& count, uint32& totalcount, bool getall) { int loc_idx = player->GetSession()->GetSessionDbLocaleIndex(); int locdbc_idx = player->GetSession()->GetSessionDbcLocale(); time_t curTime = sWorld->GetGameTime(); + PlayerGetAllThrottleMap::const_iterator itr = GetAllThrottleMap.find(player->GetGUID()); + time_t throttleTime = itr != GetAllThrottleMap.end() ? itr->second : curTime; + + if (getall && throttleTime <= curTime) + { + for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr) + { + AuctionEntry* Aentry = itr->second; + // Skip expired auctions + if (Aentry->expire_time < curTime) + continue; + + Item* item = sAuctionMgr->GetAItem(Aentry->itemGUIDLow); + if (!item) + continue; + + ++count; + ++totalcount; + Aentry->BuildAuctionInfo(data, item); + + if (count >= MAX_GETALL_RETURN) + break; + } + GetAllThrottleMap[player->GetGUID()] = curTime + sWorld->getIntConfig(CONFIG_AUCTION_GETALL_DELAY); + return; + } + for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr) { AuctionEntry* Aentry = itr->second; @@ -744,16 +779,16 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player if (count < 50 && totalcount >= listfrom) { ++count; - Aentry->BuildAuctionInfo(data); + Aentry->BuildAuctionInfo(data, item); } ++totalcount; } } //this function inserts to WorldPacket auction's data -bool AuctionEntry::BuildAuctionInfo(WorldPacket& data) const +bool AuctionEntry::BuildAuctionInfo(WorldPacket& data, Item* sourceItem) const { - Item* item = sAuctionMgr->GetAItem(itemGUIDLow); + Item* item = (sourceItem) ? sourceItem : sAuctionMgr->GetAItem(itemGUIDLow); if (!item) { TC_LOG_ERROR("misc", "AuctionEntry::BuildAuctionInfo: Auction %u has a non-existent item: %u", Id, itemGUIDLow); diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h index 4a2b79ab170..fe4b9ed07de 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.h +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h @@ -30,6 +30,7 @@ class WorldPacket; #define MIN_AUCTION_TIME (12*HOUR) #define MAX_AUCTION_ITEMS 160 +#define MAX_GETALL_RETURN 55000 enum AuctionError { @@ -90,7 +91,7 @@ struct AuctionEntry uint8 GetHouseId() const { return houseId; } uint32 GetAuctionCut() const; uint32 GetAuctionOutBid() const; - bool BuildAuctionInfo(WorldPacket & data) const; + bool BuildAuctionInfo(WorldPacket & data, Item* sourceItem = nullptr) const; void DeleteFromDB(SQLTransaction& trans) const; void SaveToDB(SQLTransaction& trans) const; bool LoadFromDB(Field* fields); @@ -110,6 +111,7 @@ class AuctionHouseObject } typedef std::map<uint32, AuctionEntry*> AuctionEntryMap; + typedef std::unordered_map<ObjectGuid, time_t> PlayerGetAllThrottleMap; uint32 Getcount() const { return AuctionsMap.size(); } @@ -133,10 +135,15 @@ class AuctionHouseObject void BuildListAuctionItems(WorldPacket& data, Player* player, std::wstring const& searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable, uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, - uint32& count, uint32& totalcount); + uint32& count, uint32& totalcount, bool getall = false); private: AuctionEntryMap AuctionsMap; + + // Map of throttled players for GetAll, and throttle expiry time + // Stored here, rather than player object to maintain persistence after logout + PlayerGetAllThrottleMap GetAllThrottleMap; + }; class AuctionHouseMgr diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index f23888cab03..efe0526baae 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -706,7 +706,7 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData) TC_LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_LIST_ITEMS"); std::string searchedname; - uint8 levelmin, levelmax, usable; + uint8 levelmin, levelmax, usable, getAll; uint32 listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality; ObjectGuid guid; @@ -718,7 +718,7 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData) recvData >> auctionSlotID >> auctionMainCategory >> auctionSubCategory; recvData >> quality >> usable; - recvData.read_skip<uint8>(); // unk + recvData >> getAll; // this block looks like it uses some lame byte packing or similar... uint8 unkCnt; @@ -760,11 +760,11 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData) auctionHouse->BuildListAuctionItems(data, _player, wsearchedname, listfrom, levelmin, levelmax, usable, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, - count, totalcount); + count, totalcount, (getAll != 0 && sWorld->getIntConfig(CONFIG_AUCTION_GETALL_DELAY) != 0)); data.put<uint32>(0, count); data << (uint32) totalcount; - data << (uint32) 300; // unk 2.3.0 const? + data << (uint32) sWorld->getIntConfig(CONFIG_AUCTION_SEARCH_DELAY); SendPacket(&data); } diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 09cc9180a57..289a4d47666 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -575,6 +575,13 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_ADDON_CHANNEL] = sConfigMgr->GetBoolDefault("AddonChannel", true); m_bool_configs[CONFIG_CLEAN_CHARACTER_DB] = sConfigMgr->GetBoolDefault("CleanCharacterDB", false); m_int_configs[CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS] = sConfigMgr->GetIntDefault("PersistentCharacterCleanFlags", 0); + m_int_configs[CONFIG_AUCTION_GETALL_DELAY] = sConfigMgr->GetIntDefault("Auction.GetAllScanDelay", 900); + m_int_configs[CONFIG_AUCTION_SEARCH_DELAY] = sConfigMgr->GetIntDefault("Auction.SearchDelay", 300); + if (m_int_configs[CONFIG_AUCTION_SEARCH_DELAY] < 100 || m_int_configs[CONFIG_AUCTION_SEARCH_DELAY] > 10000) + { + TC_LOG_ERROR("server.loading", "Auction.SearchDelay (%i) must be between 100 and 10000. Using default of 300ms", m_int_configs[CONFIG_AUCTION_SEARCH_DELAY]); + m_int_configs[CONFIG_AUCTION_SEARCH_DELAY] = 300; + } m_int_configs[CONFIG_CHAT_CHANNEL_LEVEL_REQ] = sConfigMgr->GetIntDefault("ChatLevelReq.Channel", 1); m_int_configs[CONFIG_CHAT_WHISPER_LEVEL_REQ] = sConfigMgr->GetIntDefault("ChatLevelReq.Whisper", 1); m_int_configs[CONFIG_CHAT_SAY_LEVEL_REQ] = sConfigMgr->GetIntDefault("ChatLevelReq.Say", 1); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index a624fd6e6a7..00b244c9efb 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -356,6 +356,8 @@ enum WorldIntConfigs CONFIG_CHARTER_COST_ARENA_5v5, CONFIG_NO_GRAY_AGGRO_ABOVE, CONFIG_NO_GRAY_AGGRO_BELOW, + CONFIG_AUCTION_GETALL_DELAY, + CONFIG_AUCTION_SEARCH_DELAY, INT_CONFIG_VALUE_COUNT }; diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 5b07dde22bb..217995cb88a 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -406,6 +406,24 @@ CleanCharacterDB = 0 PersistentCharacterCleanFlags = 0 # +# Auction.GetAllScanDelay +# Description: Sets the minimum time in seconds, a single player character can perform a getall scan. +# The value is only held in memory so a server restart will clear it. +# Setting this to zero, will disable GetAll functions completely. +# Default: 900 - (GetAll scan limited to once every 15mins per player character) + +Auction.GetAllScanDelay = 900 + +# +# Auction.SearchDelay +# Description: Sets the minimum time in milliseconds (seconds x 1000), that the client must wait between +# auction search operations. This can be increased if somehow Auction House activity is causing +# too much load. +# Default: 300 - (Time delay between auction searches set to 0.3secs) + +Auction.SearchDelay = 300 + +# ################################################################################################### ################################################################################################### |