From 8661d8afc9a0da7ec31db71cec0202c7d20d17f8 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 21 Jan 2014 07:09:42 -0700 Subject: [PATCH] Added the CommoditiesServer project --- engine/server/application/CMakeLists.txt | 1 + .../CommoditiesServer/CMakeLists.txt | 6 + .../CommoditiesServer/src/CMakeLists.txt | 93 + .../CommoditiesServer/src/linux/main.cpp | 80 + .../CommoditiesServer/src/shared/Auction.cpp | 1459 +++++ .../CommoditiesServer/src/shared/Auction.h | 157 + .../src/shared/AuctionBid.cpp | 73 + .../CommoditiesServer/src/shared/AuctionBid.h | 53 + .../src/shared/AuctionItem.cpp | 56 + .../src/shared/AuctionItem.h | 70 + .../src/shared/AuctionLocation.cpp | 524 ++ .../src/shared/AuctionLocation.h | 120 + .../src/shared/AuctionMarket.cpp | 5179 +++++++++++++++++ .../src/shared/AuctionMarket.h | 235 + .../src/shared/CentralServerConnection.cpp | 55 + .../src/shared/CentralServerConnection.h | 33 + .../src/shared/CommodityServer.cpp | 296 + .../src/shared/CommodityServer.h | 58 + .../src/shared/CommodityServerMetricsData.cpp | 99 + .../src/shared/CommodityServerMetricsData.h | 38 + .../src/shared/ConfigCommodityServer.cpp | 72 + .../src/shared/ConfigCommodityServer.h | 299 + .../src/shared/DatabaseServerConnection.cpp | 218 + .../src/shared/DatabaseServerConnection.h | 34 + .../src/shared/FirstCommodityServer.h | 19 + .../src/shared/GameServerConnection.cpp | 289 + .../src/shared/GameServerConnection.h | 41 + .../src/shared/dBAuctionRecord.h | 42 + .../src/shared/dBBidRecord.h | 37 + .../shared/database/auction_characters.tab | 7 + .../src/shared/database/auction_locations.tab | 9 + .../src/shared/database/auctions.tab | 18 + .../shared/database/market_auction_bids.tab | 11 + .../src/shared/database/market_auctions.tab | 18 + .../src/shared/database/sp_swg_auctions.sql | 460 ++ .../library/sharedNetwork/src/CMakeLists.txt | 4 + 36 files changed, 10263 insertions(+) create mode 100644 engine/server/application/CommoditiesServer/CMakeLists.txt create mode 100644 engine/server/application/CommoditiesServer/src/CMakeLists.txt create mode 100644 engine/server/application/CommoditiesServer/src/linux/main.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/Auction.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/Auction.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/AuctionBid.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/AuctionBid.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/AuctionItem.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/AuctionItem.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/AuctionLocation.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/AuctionLocation.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/AuctionMarket.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/AuctionMarket.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/CentralServerConnection.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/CentralServerConnection.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/CommodityServer.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/CommodityServer.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/CommodityServerMetricsData.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/CommodityServerMetricsData.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/ConfigCommodityServer.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/ConfigCommodityServer.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/DatabaseServerConnection.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/DatabaseServerConnection.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/FirstCommodityServer.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/GameServerConnection.cpp create mode 100644 engine/server/application/CommoditiesServer/src/shared/GameServerConnection.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/dBAuctionRecord.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/dBBidRecord.h create mode 100644 engine/server/application/CommoditiesServer/src/shared/database/auction_characters.tab create mode 100644 engine/server/application/CommoditiesServer/src/shared/database/auction_locations.tab create mode 100644 engine/server/application/CommoditiesServer/src/shared/database/auctions.tab create mode 100644 engine/server/application/CommoditiesServer/src/shared/database/market_auction_bids.tab create mode 100644 engine/server/application/CommoditiesServer/src/shared/database/market_auctions.tab create mode 100644 engine/server/application/CommoditiesServer/src/shared/database/sp_swg_auctions.sql diff --git a/engine/server/application/CMakeLists.txt b/engine/server/application/CMakeLists.txt index 0cc28aff..b96af8e1 100644 --- a/engine/server/application/CMakeLists.txt +++ b/engine/server/application/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(CentralServer) add_subdirectory(ChatServer) +add_subdirectory(CommoditiesServer) add_subdirectory(ConnectionServer) add_subdirectory(LogServer) add_subdirectory(LoginPing) diff --git a/engine/server/application/CommoditiesServer/CMakeLists.txt b/engine/server/application/CommoditiesServer/CMakeLists.txt new file mode 100644 index 00000000..bd78e2db --- /dev/null +++ b/engine/server/application/CommoditiesServer/CMakeLists.txt @@ -0,0 +1,6 @@ + +cmake_minimum_required(VERSION 2.8) + +project(CommoditiesServer) + +add_subdirectory(src) diff --git a/engine/server/application/CommoditiesServer/src/CMakeLists.txt b/engine/server/application/CommoditiesServer/src/CMakeLists.txt new file mode 100644 index 00000000..01ef9652 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/CMakeLists.txt @@ -0,0 +1,93 @@ + +set(SHARED_SOURCES + shared/AuctionBid.cpp + shared/AuctionBid.h + shared/Auction.cpp + shared/Auction.h + shared/AuctionItem.cpp + shared/AuctionItem.h + shared/AuctionLocation.cpp + shared/AuctionLocation.h + shared/AuctionMarket.cpp + shared/AuctionMarket.h + shared/CentralServerConnection.cpp + shared/CentralServerConnection.h + shared/CommodityServer.cpp + shared/CommodityServer.h + shared/CommodityServerMetricsData.cpp + shared/CommodityServerMetricsData.h + shared/ConfigCommodityServer.cpp + shared/ConfigCommodityServer.h + shared/DatabaseServerConnection.cpp + shared/DatabaseServerConnection.h + shared/FirstCommodityServer.h + shared/GameServerConnection.cpp + shared/GameServerConnection.h +) + +if(WIN32) + set(PLATFORM_SOURCES "") +else() + set(PLATFORM_SOURCES + linux/main.cpp + ) +endif() + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/shared + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCompression/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedGame/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedLog/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetwork/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetworkMessages/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedObject/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRandom/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedThread/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverMetrics/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverNetworkMessages/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverUtility/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localizationArchive/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/singleton/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public +) + +link_directories(${STLPORT_LIBDIR}) + +add_executable(CommoditiesServer + ${SHARED_SOURCES} + ${PLATFORM_SOURCES} +) + +target_link_libraries(CommoditiesServer + sharedCompression + sharedDebug + sharedFile + sharedFoundation + sharedGame + sharedMemoryManager + sharedLog + sharedMessageDispatch + sharedNetwork + sharedNetworkMessages + sharedObject + sharedRandom + sharedThread + sharedUtility + serverMetrics + serverNetworkMessages + serverUtility + ${STLPORT_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${CMAKE_DL_LIBS} +) diff --git a/engine/server/application/CommoditiesServer/src/linux/main.cpp b/engine/server/application/CommoditiesServer/src/linux/main.cpp new file mode 100644 index 00000000..b93208f5 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/linux/main.cpp @@ -0,0 +1,80 @@ +// main.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstCommodityServer.h" + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedCompression/SetupSharedCompression.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/TreeFile.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/ExitChain.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedGame/CommoditiesAdvancedSearchAttribute.h" +#include "sharedGame/ConfigSharedGame.h" +#include "sharedNetwork/SetupSharedNetwork.h" +#include "sharedNetwork/NetworkHandler.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "sharedThread/SetupSharedThread.h" +#include "sharedUtility/DataTableManager.h" +#include "CommodityServer.h" +#include "ConfigCommodityServer.h" +#include "LocalizationManager.h" +#include "UnicodeUtils.h" + +//----------------------------------------------------------------------- + +int main(int argc, char ** argv) +{ + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + //-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + + setupFoundationData.argc = argc; + setupFoundationData.argv = argv; + setupFoundationData.runInBackground = true; + SetupSharedFoundation::install (setupFoundationData); + + ConfigSharedGame::install(); + SetupSharedCompression::install(); + SetupSharedFile::install(false); + SetupSharedNetworkMessages::install(); + + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + SetupSharedNetwork::install(networkSetupData); + NetworkHandler::install(); + + Os::setProgramName("CommodityServer"); + ConfigCommodityServer::install(); + + const bool displayBadStringIds = ConfigSharedGame::getDisplayBadStringIds (); + const bool debugStringIds = ConfigSharedGame::getDebugStringIds (); + Unicode::NarrowString defaultLocale(ConfigSharedGame::getDefaultLocale ()); + Unicode::UnicodeNarrowStringVector localeVector; + localeVector.push_back(defaultLocale); + + LocalizationManager::install (new TreeFile::TreeFileFactory, localeVector, debugStringIds, NULL, displayBadStringIds); + ExitChain::add(LocalizationManager::remove, "LocalizationManager::remove"); + + DataTableManager::install(); + CommoditiesAdvancedSearchAttribute::install(); + + //-- run server + SetupSharedFoundation::callbackWithExceptionHandling(CommodityServer::run); + + NetworkHandler::remove(); + SetupSharedFoundation::remove(); + SetupSharedThread::remove(); + + return 0; +} + +//----------------------------------------------------------------------- diff --git a/engine/server/application/CommoditiesServer/src/shared/Auction.cpp b/engine/server/application/CommoditiesServer/src/shared/Auction.cpp new file mode 100644 index 00000000..c2079375 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/Auction.cpp @@ -0,0 +1,1459 @@ +// ====================================================================== +// +// Auction.cpp +// copyright (c) 2004 Sony Online Entertainment +// +// (refactor of original code only to the degree to make it work with new) +// (server & database framework ... i.e. none of the logic has changed) +// +// Original Author: Matt Severenson +// Refactored by : Doug Mellencamp +// +// ====================================================================== + +#include "FirstCommodityServer.h" +#include "Auction.h" +#include "AuctionMarket.h" +#include "CommodityServer.h" +#include "ConfigCommodityServer.h" +#include "StringId.h" +#include "UnicodeUtils.h" +#include "sharedFoundation/Crc.h" +#include "sharedFoundation/CrcLowerString.h" +#include "sharedGame/CommoditiesAdvancedSearchAttribute.h" +#include "sharedGame/GameObjectTypes.h" +#include "sharedGame/SharedObjectTemplate.h" +#include "sharedLog/Log.h" +#include "sharedUtility/DataTable.h" +#include "sharedUtility/DataTableManager.h" + +#ifndef max +using std::max; +#endif + +// src/engine/client/library/clientGame/src/shared/core/AuctionManagerClient.cpp (s_maxBid) +// src/engine/server/application/CommoditiesServer/src/shared/Auction.cpp (MAX_BID) +// src/engine/server/library/serverGame/src/shared/commoditiesMarket/CommoditiesMarket.cpp (MAX_BID) +#define MAX_BID 10000000 +#define MAX_VENDOR_PRICE 833333333 + +namespace AuctionNamespace +{ + typedef bool (*SearchConditionComparisonFn) (AuctionQueryHeadersMessage::SearchCondition const & /*searchCondition*/, + std::map const * /*searchableAttributeInt*/, + std::map const * /*searchableAttributeFloat*/, + std::map const * /*searchableAttributeString*/, + bool & /*applicableSearchCondition*/); + + SearchConditionComparisonFn s_searchConditionComparisonFn[static_cast(AuctionQueryHeadersMessage::SCC_LAST)]; + + // ---------------------------------------------------------------------- + + bool searchConditionComparisonFnInt(AuctionQueryHeadersMessage::SearchCondition const & searchCondition, + std::map const * searchableAttributeInt, + std::map const * searchableAttributeFloat, + std::map const * searchableAttributeString, + bool & applicableSearchCondition) + { +#ifdef _DEBUG + DEBUG_FATAL((searchCondition.comparison != AuctionQueryHeadersMessage::SCC_int), ("searchConditionComparisonFnInt() called for attributeNameCrc=(%lu), comparison=(%d) that is not AuctionQueryHeadersMessage::SCC_int", searchCondition.attributeNameCrc, static_cast(searchCondition.comparison))); + DEBUG_REPORT_LOG(ConfigCommodityServer::getShowAllDebugInfo(), ("[Commodities Server QueryAuctionHeadersMessage] searchConditionComparisonFnInt\n")); +#endif + UNREF(searchableAttributeFloat); + UNREF(searchableAttributeString); + + // if the filter condition requires the attribute, + // it will always be an applicable filter condition; + // otherwise, it will only be applicable if the item + // has the attribute + applicableSearchCondition = searchCondition.requiredAttribute; + + if (searchableAttributeInt) + { + std::map::const_iterator iterAttr = searchableAttributeInt->find(searchCondition.attributeNameCrc); + if (iterAttr != searchableAttributeInt->end()) + { + applicableSearchCondition = true; + return ((iterAttr->second >= searchCondition.intMin) && (iterAttr->second <= searchCondition.intMax)); + } + } + + return false; + } + + // ---------------------------------------------------------------------- + + bool searchConditionComparisonFnFloat(AuctionQueryHeadersMessage::SearchCondition const & searchCondition, + std::map const * searchableAttributeInt, + std::map const * searchableAttributeFloat, + std::map const * searchableAttributeString, + bool & applicableSearchCondition) + { +#ifdef _DEBUG + DEBUG_FATAL((searchCondition.comparison != AuctionQueryHeadersMessage::SCC_float), ("searchConditionComparisonFnFloat() called for attributeNameCrc=(%lu), comparison=(%d) that is not AuctionQueryHeadersMessage::SCC_float", searchCondition.attributeNameCrc, static_cast(searchCondition.comparison))); + DEBUG_REPORT_LOG(ConfigCommodityServer::getShowAllDebugInfo(), ("[Commodities Server QueryAuctionHeadersMessage] searchConditionComparisonFnFloat\n")); +#endif + UNREF(searchableAttributeInt); + UNREF(searchableAttributeString); + + // if the filter condition requires the attribute, + // it will always be an applicable filter condition; + // otherwise, it will only be applicable if the item + // has the attribute + applicableSearchCondition = searchCondition.requiredAttribute; + + if (searchableAttributeFloat) + { + std::map::const_iterator iterAttr = searchableAttributeFloat->find(searchCondition.attributeNameCrc); + if (iterAttr != searchableAttributeFloat->end()) + { + applicableSearchCondition = true; + return ((iterAttr->second >= searchCondition.floatMin) && (iterAttr->second <= searchCondition.floatMax)); + } + } + + return false; + } + + // ---------------------------------------------------------------------- + + bool searchConditionComparisonFnStringEqual(AuctionQueryHeadersMessage::SearchCondition const & searchCondition, + std::map const * searchableAttributeInt, + std::map const * searchableAttributeFloat, + std::map const * searchableAttributeString, + bool & applicableSearchCondition) + { +#ifdef _DEBUG + DEBUG_FATAL((searchCondition.comparison != AuctionQueryHeadersMessage::SCC_string_equal), ("searchConditionComparisonFnStringEqual() called for attributeNameCrc=(%lu), comparison=(%d) that is not AuctionQueryHeadersMessage::SCC_string_equal", searchCondition.attributeNameCrc, static_cast(searchCondition.comparison))); + DEBUG_REPORT_LOG(ConfigCommodityServer::getShowAllDebugInfo(), ("[Commodities Server QueryAuctionHeadersMessage] searchConditionComparisonFnStringEqual\n")); +#endif + UNREF(searchableAttributeInt); + UNREF(searchableAttributeFloat); + + // if the filter condition requires the attribute, + // it will always be an applicable filter condition; + // otherwise, it will only be applicable if the item + // has the attribute + applicableSearchCondition = searchCondition.requiredAttribute; + + if (searchableAttributeString) + { + std::map::const_iterator iterAttr = searchableAttributeString->find(searchCondition.attributeNameCrc); + if (iterAttr != searchableAttributeString->end()) + { + applicableSearchCondition = true; + return (0 == strcmp(iterAttr->second.c_str(), searchCondition.stringValue.c_str())); // lowercase is assumed (and required) + } + } + + return false; + } + + // ---------------------------------------------------------------------- + + bool searchConditionComparisonFnStringNotEqual(AuctionQueryHeadersMessage::SearchCondition const & searchCondition, + std::map const * searchableAttributeInt, + std::map const * searchableAttributeFloat, + std::map const * searchableAttributeString, + bool & applicableSearchCondition) + { +#ifdef _DEBUG + DEBUG_FATAL((searchCondition.comparison != AuctionQueryHeadersMessage::SCC_string_not_equal), ("searchConditionComparisonFnStringNotEqual() called for attributeNameCrc=(%lu), comparison=(%d) that is not AuctionQueryHeadersMessage::SCC_string_not_equal", searchCondition.attributeNameCrc, static_cast(searchCondition.comparison))); + DEBUG_REPORT_LOG(ConfigCommodityServer::getShowAllDebugInfo(), ("[Commodities Server QueryAuctionHeadersMessage] searchConditionComparisonFnStringNotEqual\n")); +#endif + UNREF(searchableAttributeInt); + UNREF(searchableAttributeFloat); + + // if the filter condition requires the attribute, + // it will always be an applicable filter condition; + // otherwise, it will only be applicable if the item + // has the attribute + applicableSearchCondition = searchCondition.requiredAttribute; + + if (searchableAttributeString) + { + std::map::const_iterator iterAttr = searchableAttributeString->find(searchCondition.attributeNameCrc); + if (iterAttr != searchableAttributeString->end()) + { + applicableSearchCondition = true; + return (0 != strcmp(iterAttr->second.c_str(), searchCondition.stringValue.c_str())); // lowercase is assumed (and required) + } + } + + return false; + } + + // ---------------------------------------------------------------------- + + bool searchConditionComparisonFnStringContain(AuctionQueryHeadersMessage::SearchCondition const & searchCondition, + std::map const * searchableAttributeInt, + std::map const * searchableAttributeFloat, + std::map const * searchableAttributeString, + bool & applicableSearchCondition) + { +#ifdef _DEBUG + DEBUG_FATAL((searchCondition.comparison != AuctionQueryHeadersMessage::SCC_string_contain), ("searchConditionComparisonFnStringContain() called for attributeNameCrc=(%lu), comparison=(%d) that is not AuctionQueryHeadersMessage::SCC_string_contain", searchCondition.attributeNameCrc, static_cast(searchCondition.comparison))); + DEBUG_REPORT_LOG(ConfigCommodityServer::getShowAllDebugInfo(), ("[Commodities Server QueryAuctionHeadersMessage] searchConditionComparisonFnStringContain\n")); +#endif + UNREF(searchableAttributeInt); + UNREF(searchableAttributeFloat); + + // if the filter condition requires the attribute, + // it will always be an applicable filter condition; + // otherwise, it will only be applicable if the item + // has the attribute + applicableSearchCondition = searchCondition.requiredAttribute; + + if (searchableAttributeString) + { + std::map::const_iterator iterAttr = searchableAttributeString->find(searchCondition.attributeNameCrc); + if (iterAttr != searchableAttributeString->end()) + { + applicableSearchCondition = true; + return (NULL != strstr(iterAttr->second.c_str(), searchCondition.stringValue.c_str())); // lowercase is assumed (and required) + } + } + + return false; + } + + // ---------------------------------------------------------------------- + + bool searchConditionComparisonFnStringNotContain(AuctionQueryHeadersMessage::SearchCondition const & searchCondition, + std::map const * searchableAttributeInt, + std::map const * searchableAttributeFloat, + std::map const * searchableAttributeString, + bool & applicableSearchCondition) + { +#ifdef _DEBUG + DEBUG_FATAL((searchCondition.comparison != AuctionQueryHeadersMessage::SCC_string_not_contain), ("searchConditionComparisonFnStringNotContain() called for attributeNameCrc=(%lu), comparison=(%d) that is not AuctionQueryHeadersMessage::SCC_string_not_contain", searchCondition.attributeNameCrc, static_cast(searchCondition.comparison))); + DEBUG_REPORT_LOG(ConfigCommodityServer::getShowAllDebugInfo(), ("[Commodities Server QueryAuctionHeadersMessage] searchConditionComparisonFnStringNotContain\n")); +#endif + UNREF(searchableAttributeInt); + UNREF(searchableAttributeFloat); + + // if the filter condition requires the attribute, + // it will always be an applicable filter condition; + // otherwise, it will only be applicable if the item + // has the attribute + applicableSearchCondition = searchCondition.requiredAttribute; + + if (searchableAttributeString) + { + std::map::const_iterator iterAttr = searchableAttributeString->find(searchCondition.attributeNameCrc); + if (iterAttr != searchableAttributeString->end()) + { + applicableSearchCondition = true; + return (NULL == strstr(iterAttr->second.c_str(), searchCondition.stringValue.c_str())); // lowercase is assumed (and required) + } + } + + return false; + } + + // ---------------------------------------------------------------------- + + // + std::pair s_searchConditionMatchAllAnyActionAnyMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_LAST)]; + std::pair s_searchConditionMatchAllAnyActionAnyNotMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_LAST)]; + + // search return value + bool s_searchConditionMatchAllAnyActionAllMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_LAST)]; + bool s_searchConditionMatchAllAnyActionAllNotMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_LAST)]; +}; + +using namespace AuctionNamespace; + +// ====================================================================== + +Auction::Auction( + const NetworkId & creatorId, + int minBid, + int auctionTimer, + const NetworkId & itemId, + int itemNameLength, + const Unicode::String & itemName, + int itemType, + int itemTemplateId, + int itemTimer, + int itemSize, + const AuctionLocation & location, + int flags, + int buyNowPrice, + int userDescriptionLength, + const Unicode::String & userDescription, + int oobLength, + const Unicode::String & oobData, + std::vector > const & attributes +) : +m_creatorId(creatorId), +m_minBid(minBid), +m_auctionTimer(auctionTimer), +m_buyNowPrice(buyNowPrice), +m_userDescriptionLength(userDescriptionLength), +m_userDescription(userDescription), +m_oobLength(oobLength), +m_oobData(oobData), +m_attributes(), +m_searchableAttributeInt(NULL), +m_searchableAttributeFloat(NULL), +m_searchableAttributeString(NULL), +m_highBid(NULL), +m_item(new AuctionItem(itemId, itemType, itemTemplateId, itemTimer, itemNameLength, itemName, creatorId, itemSize)), +m_sold(false), +m_active(true), +m_bids(), +m_location(const_cast(location)), +m_flags(flags), +m_trackId(-1) +{ + assert(m_auctionTimer != 0); + + // it it's a instant sale resource container, add "credits per unit" attribute + if (AuctionItem::IsCategoryResourceContainer(m_item->GetCategory()) && (m_buyNowPrice > 0)) + { + for (std::vector >::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) + { + if (iter->first == "credits_per_unit") + { + // ignore any existing credits per unit attribute; we'll recalculate it and add the updated attribute + continue; + } + + m_attributes.push_back(*iter); + + if (iter->first == "resource_contents") + { + int count = ::atoi(Unicode::wideToNarrow(iter->second).c_str()); + if (count > 0) + { + char buffer[128]; + int const len = snprintf(buffer, sizeof(buffer)-1, "%.6f", (static_cast(m_buyNowPrice) / static_cast(count))); + buffer[sizeof(buffer)-1] = '\0'; + + // trim trailing 0s after the decimal point + char * pChar = buffer + len - 1; + while (pChar >= buffer) + { + if (*pChar == '.') + { + *pChar = '\0'; + break; + } + else if (*pChar != '0') + { + ++pChar; + *pChar = '\0'; + break; + } + + --pChar; + } + + m_attributes.push_back(std::make_pair("credits_per_unit", Unicode::narrowToWide(buffer))); + } + } + } + } + else + { + m_attributes = attributes; + } + + SetItemResourceContainerClassCrc(); + BuildSearchableAttributeList(); +} + +// ---------------------------------------------------------------------- + +Auction::Auction( + const NetworkId & creatorId, + int minBid, + int auctionTimer, + const NetworkId & itemId, + int itemNameLength, + const Unicode::String & itemName, + int itemType, + int itemTemplateId, + int itemTimer, + int itemSize, + const AuctionLocation & location, + int flags, + int buyNowPrice, + int userDescriptionLength, + const Unicode::String & userDescription, + int oobLength, + const Unicode::String & oobData, + std::vector > const & attributes, + bool isActive, + bool isSold +) : +m_creatorId(creatorId), +m_minBid(minBid), +m_auctionTimer(auctionTimer), +m_buyNowPrice(buyNowPrice), +m_userDescriptionLength(userDescriptionLength), +m_userDescription(userDescription), +m_oobLength(oobLength), +m_oobData(oobData), +m_attributes(), +m_searchableAttributeInt(NULL), +m_searchableAttributeFloat(NULL), +m_searchableAttributeString(NULL), +m_highBid(NULL), +m_item(new AuctionItem(itemId, itemType, itemTemplateId, itemTimer, itemNameLength, itemName, creatorId, itemSize)), +m_sold(isSold), +m_active(isActive), +m_bids(), +m_location(const_cast(location)), +m_flags(flags), +m_trackId(-1) +{ + assert(m_auctionTimer != 0); + + // it it's a instant sale resource container, add "credits per unit" attribute + if (AuctionItem::IsCategoryResourceContainer(m_item->GetCategory()) && (m_buyNowPrice > 0)) + { + for (std::vector >::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) + { + if (iter->first == "credits_per_unit") + { + // ignore any existing credits per unit attribute; we'll recalculate it and add the updated attribute + continue; + } + + m_attributes.push_back(*iter); + + if (iter->first == "resource_contents") + { + int count = ::atoi(Unicode::wideToNarrow(iter->second).c_str()); + if (count > 0) + { + char buffer[128]; + int const len = snprintf(buffer, sizeof(buffer)-1, "%.6f", (static_cast(m_buyNowPrice) / static_cast(count))); + buffer[sizeof(buffer)-1] = '\0'; + + // trim trailing 0s after the decimal point + char * pChar = buffer + len - 1; + while (pChar >= buffer) + { + if (*pChar == '.') + { + *pChar = '\0'; + break; + } + else if (*pChar != '0') + { + ++pChar; + *pChar = '\0'; + break; + } + + --pChar; + } + + m_attributes.push_back(std::make_pair("credits_per_unit", Unicode::narrowToWide(buffer))); + } + } + } + } + else + { + m_attributes = attributes; + } + + SetItemResourceContainerClassCrc(); + BuildSearchableAttributeList(); +} + +// ---------------------------------------------------------------------- + +Auction::~Auction() +{ + std::vector::iterator i = m_bids.begin(); + for (; i != m_bids.end(); ++i) + { + AuctionBid *bid = (*i); + delete bid; + } + delete m_item; + + delete m_searchableAttributeInt; + delete m_searchableAttributeFloat; + delete m_searchableAttributeString; +} + +// ---------------------------------------------------------------------- + +void Auction::Initialization() +{ +#ifdef _DEBUG + for (int i = 0; i < static_cast(AuctionQueryHeadersMessage::SCC_LAST); ++i) + { + s_searchConditionComparisonFn[i] = NULL; + } +#endif + + s_searchConditionComparisonFn[static_cast(AuctionQueryHeadersMessage::SCC_int)] = searchConditionComparisonFnInt; + s_searchConditionComparisonFn[static_cast(AuctionQueryHeadersMessage::SCC_float)] = searchConditionComparisonFnFloat; + s_searchConditionComparisonFn[static_cast(AuctionQueryHeadersMessage::SCC_string_equal)] = searchConditionComparisonFnStringEqual; + s_searchConditionComparisonFn[static_cast(AuctionQueryHeadersMessage::SCC_string_not_equal)] = searchConditionComparisonFnStringNotEqual; + s_searchConditionComparisonFn[static_cast(AuctionQueryHeadersMessage::SCC_string_contain)] = searchConditionComparisonFnStringContain; + s_searchConditionComparisonFn[static_cast(AuctionQueryHeadersMessage::SCC_string_not_contain)] = searchConditionComparisonFnStringNotContain; + +#ifdef _DEBUG + for (int j = 0; j < static_cast(AuctionQueryHeadersMessage::SCC_LAST); ++j) + { + DEBUG_FATAL((s_searchConditionComparisonFn[j] == NULL), ("s_searchConditionComparisonFn array is NULL at index (%d)", j)); + } +#endif + + // + static std::pair const continueToCheckNextMatch(std::make_pair(false, false)); + static std::pair const stopAndReturnTrue(std::make_pair(true, true)); + static std::pair const stopAndReturnFalse(std::make_pair(true, false)); + + // "will only match if all applicable attribute filter conditions match" + // ASMAA_match_all -> true after all match + // -> false after first mismatch + s_searchConditionMatchAllAnyActionAnyMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_match_all)] = continueToCheckNextMatch; // after any match, continue to check next match + s_searchConditionMatchAllAnyActionAnyNotMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_match_all)] = stopAndReturnFalse; // after any not match, stop and return false + s_searchConditionMatchAllAnyActionAllMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_match_all)] = true; // after all match, return true + s_searchConditionMatchAllAnyActionAllNotMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_match_all)] = false; // after all not match, return false + + // "will only match if any applicable attribute filter condition matches" + // ASMAA_match_any -> false after all mismatch + // -> true after first match + s_searchConditionMatchAllAnyActionAnyMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_match_any)] = stopAndReturnTrue; // after any match, stop and return true + s_searchConditionMatchAllAnyActionAnyNotMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_match_any)] = continueToCheckNextMatch; // after any not match, continue to check next match + s_searchConditionMatchAllAnyActionAllMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_match_any)] = true; // after all match, return true + s_searchConditionMatchAllAnyActionAllNotMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_match_any)] = false; // after all not match, return false + + // "will only match if no applicable attribute filter condition matches" + // (i.e. match none) + // ASMAA_not_match_all is basically "not ASMAA_match_any" + // ASMAA_not_match_all -> true after all mismatch + // -> false after first match + s_searchConditionMatchAllAnyActionAnyMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_not_match_all)] = stopAndReturnFalse; // after any match, stop and return false + s_searchConditionMatchAllAnyActionAnyNotMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_not_match_all)] = continueToCheckNextMatch; // after any not match, continue to check next match + s_searchConditionMatchAllAnyActionAllMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_not_match_all)] = false; // after all match, return false + s_searchConditionMatchAllAnyActionAllNotMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_not_match_all)] = true; // after all not match, return true + + // "will only match if any applicable attribute filter condition does not match" + // ASMAA_not_match_any is basically "not ASMAA_match_all" + // ASMAA_not_match_any -> false after all match + // -> true after first mismatch + s_searchConditionMatchAllAnyActionAnyMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_not_match_any)] = continueToCheckNextMatch; // after any match, continue to check next match + s_searchConditionMatchAllAnyActionAnyNotMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_not_match_any)] = stopAndReturnTrue; // after any not match, stop and return true + s_searchConditionMatchAllAnyActionAllMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_not_match_any)] = false; // after all match, return false + s_searchConditionMatchAllAnyActionAllNotMatch[static_cast(AuctionQueryHeadersMessage::ASMAA_not_match_any)] = true; // after all not match, return true +} + +// ---------------------------------------------------------------------- + +void Auction::GetAttributes(std::string & output) const +{ + output.clear(); + + output = Unicode::wideToNarrow(m_item->GetName()); + output += " ("; + output += m_item->GetItemId().getValueString(); + output += ") (GOT_"; + output += GameObjectTypes::getCanonicalName(m_item->GetCategory()); + output += ")\r\n\r\n"; + + char buffer[2048]; + for (std::vector >::const_iterator iter = m_attributes.begin(); iter != m_attributes.end(); ++iter) + { + snprintf(buffer, sizeof(buffer)-1, "(%s) (%s)", iter->first.c_str(), Unicode::wideToNarrow(iter->second).c_str()); + buffer[sizeof(buffer)-1] = '\0'; + + output += buffer; + output += "\r\n"; + } + + if (m_searchableAttributeInt) + { + output += "\r\nInteger indexed search attribute:\r\n"; + + for (std::map::const_iterator iter = m_searchableAttributeInt->begin(); iter != m_searchableAttributeInt->end(); ++iter) + { + std::string attributeName; + for (std::vector >::const_iterator iterAttribute = m_attributes.begin(); iterAttribute != m_attributes.end(); ++iterAttribute) + { + if (Crc::calculate(iterAttribute->first.c_str()) == iter->first) + { + attributeName = iterAttribute->first; + break; + } + } + + snprintf(buffer, sizeof(buffer)-1, "(%s, %lu) (%d)", attributeName.c_str(), iter->first, iter->second); + buffer[sizeof(buffer)-1] = '\0'; + + output += buffer; + output += "\r\n"; + } + } + + if (m_searchableAttributeFloat) + { + output += "\r\nFloat indexed search attribute:\r\n"; + + for (std::map::const_iterator iter = m_searchableAttributeFloat->begin(); iter != m_searchableAttributeFloat->end(); ++iter) + { + std::string attributeName; + for (std::vector >::const_iterator iterAttribute = m_attributes.begin(); iterAttribute != m_attributes.end(); ++iterAttribute) + { + if (Crc::calculate(iterAttribute->first.c_str()) == iter->first) + { + attributeName = iterAttribute->first; + break; + } + } + + snprintf(buffer, sizeof(buffer)-1, "(%s, %lu) (%.10g)", attributeName.c_str(), iter->first, iter->second); + buffer[sizeof(buffer)-1] = '\0'; + + output += buffer; + output += "\r\n"; + } + } + + if (m_searchableAttributeString) + { + output += "\r\nString indexed search attribute:\r\n"; + + for (std::map::const_iterator iter = m_searchableAttributeString->begin(); iter != m_searchableAttributeString->end(); ++iter) + { + std::string attributeName; + for (std::vector >::const_iterator iterAttribute = m_attributes.begin(); iterAttribute != m_attributes.end(); ++iterAttribute) + { + if (Crc::calculate(iterAttribute->first.c_str()) == iter->first) + { + attributeName = iterAttribute->first; + break; + } + } + + snprintf(buffer, sizeof(buffer)-1, "(%s, %lu) (%s)", attributeName.c_str(), iter->first, iter->second.c_str()); + buffer[sizeof(buffer)-1] = '\0'; + + output += buffer; + output += "\r\n"; + } + } +} + +// ---------------------------------------------------------------------- + +int Auction::GetHighBidAmount() const +{ + if (m_highBid) + return m_highBid->GetBid(); + else + return 0; +} + +// ---------------------------------------------------------------------- + +const AuctionBid *Auction::GetPreviousBid() const +{ + if (m_bids.size() <= 1) + { + return NULL; + } + else + { + return m_bids[m_bids.size() - 2]; + } +} + +// ---------------------------------------------------------------------- + +/** + * This isn't at all obvious, so here is a description. This function returns + * bid that will actually take place when a given bid is attempted. This bid + * can be less than the existing bid, so the bid will fail, but we still need + * to adjust the existing high bid to outbid the current one. + */ +int Auction::GetActualBid(AuctionBid *bid) +{ + assert(bid != NULL); + int bidNeeded = max(m_minBid, bid->GetBid()); + if (m_highBid != NULL) + { + bidNeeded = m_highBid->GetBid(); + if (*bid > *m_highBid) + { + bidNeeded = max(bid->GetBid(), m_highBid->GetMaxProxyBid() + 1); + } + else if (*bid == *m_highBid) + { + bidNeeded = m_highBid->GetMaxProxyBid(); + } + else if (*bid < *m_highBid) + { + bidNeeded = max(m_highBid->GetBid(), bid->GetMaxProxyBid() + 1); + } + } + return bidNeeded; +} + +// ---------------------------------------------------------------------- + +void Auction::AddLoadedBid( + const NetworkId & bidderId, + int bid, + int maxProxyBid +) +{ + AuctionBid *auctionBid = new AuctionBid(bidderId, bid, maxProxyBid); + std::vector::iterator i = m_bids.begin(); + bool inserted = false; + for (; i != m_bids.end(); ++i) + { + if ((*i)->GetMaxProxyBid() > auctionBid->GetMaxProxyBid()) + { + m_bids.insert(i, auctionBid); + inserted = true; + break; + } + } + + if (!inserted) + { + m_bids.push_back(auctionBid); + } + m_highBid = m_bids.back(); +} + +// ---------------------------------------------------------------------- + +AuctionResultCode Auction::AddBid( + const NetworkId & bidderId, + int bid, + int maxProxyBid +) +{ + AuctionResultCode success = ARC_Success; + int maxBid = max(bid, maxProxyBid); + + if (!m_active || m_sold) + { + return ARC_AuctionExpired; + DEBUG_REPORT_LOG(true, ("[Commodities Server AddBid] : Auction Expired - Auction is sold and inactive.\n")); + } + + if (maxBid > MAX_BID && !m_location.IsVendorMarket()) + { + return ARC_BidTooHigh; + DEBUG_REPORT_LOG(true, ("[Commodities Server AddBid] : Bid too high.\n")); + } + + /*!!!TODO, put me back in after testingif (bidderId == m_creatorId) + { + return ARC_OwnerBidOnOwnItem; + }*/ + if (maxProxyBid < m_minBid) + { + return ARC_BidTooLow; + DEBUG_REPORT_LOG(true, ("[Commodities Server AddBid] : Bid too low.\n")); + } + if (IsImmediate() && (GetFlags() & AUCTION_ALWAYS_PRESENT)) + { + return ARC_SuccessPermanentAuction; + } + + AuctionBid *auctionBid = new AuctionBid(bidderId, bid, maxProxyBid); + int newBidForHighBidder = GetActualBid(auctionBid); + if (m_highBid != NULL) + { + if (*auctionBid <= *m_highBid) + { + delete auctionBid; + success = ARC_BidOutbid; + DEBUG_REPORT_LOG(true, ("[Commodities Server AddBid] : Bid outbid.\n")); + } + } + + if (success == ARC_Success) + { + m_highBid = auctionBid; + m_bids.push_back(auctionBid); + } + m_highBid->SetBid(newBidForHighBidder); + + if (IsImmediate()) + { + m_sold = true; + DEBUG_REPORT_LOG(true, ("[Commodities Server AddBid] : Immediate Auction - marked as sold.\n")); + + // put auction into the completed auctions list so + // that the auction can be processed to completion + // during the next frame + AuctionMarket::getInstance().AddAuctionToCompletedAuctionsList(*this); + } + return success; +} + +// ---------------------------------------------------------------------- + +const AuctionBid *Auction::GetPlayerBid(const NetworkId & playerId) const +{ + // new bids are pushed on the back of the vector + // so, we search using a reverse iterator + std::vector::const_reverse_iterator iter = m_bids.rbegin(); + while (iter != m_bids.rend()) + { + if ((*iter) && ((*iter)->GetBidderId() == playerId)) + { + return (*iter); + } + ++iter; + } + return NULL; +} + +// ---------------------------------------------------------------------- + +bool Auction::Update(int gameTime) +{ + if (GetFlags() & AUCTION_ALWAYS_PRESENT) + { + return true; + } + if (m_active && m_sold) + { + //immediate sale + DEBUG_REPORT_LOG(true, ("[Commodities Server Auction::Update] : Expiring immediate sale - Auction is active and sold.\n")); + + if ((m_trackId != -1) && (CommodityServer::getInstance().getGameServer(m_trackId) != NULL)) + { + Expire(true, false, m_trackId); + m_trackId = -1; + } + else + { + Expire(true, false); + } + } + else if (m_active && (gameTime >= m_auctionTimer)) + { + DEBUG_REPORT_LOG(true, ("[Commodities Server Auction::Update] : Auction expiring based on timer.\n")); + + if ((m_trackId != -1) && (CommodityServer::getInstance().getGameServer(m_trackId) != NULL)) + { + Expire(m_highBid != NULL, true, m_trackId); + m_trackId = -1; + } + else + { + Expire(m_highBid != NULL, true); + } + } + + return !m_item->IsExpired(gameTime); +} + +// ---------------------------------------------------------------------- + +void Auction::Expire(bool sold, bool expiredBasedOnTimer, int track_id) +{ + AuctionMarket::getInstance().RemoveFromAuctionTimerPriorityQueue(m_auctionTimer, m_item->GetItemId()); + + m_auctionTimer = 0; + m_active = false; + if (sold && m_highBid != NULL) + { + m_sold = true; + } + else + { + m_sold = false; + } + + bool immediate = IsImmediate(); + + DEBUG_REPORT_LOG(true, ("[Commodities Server Auction::Expire] : Sold flag is %d.\n", m_sold)); + DEBUG_REPORT_LOG(true, ("[Commodities Server Auction::Expire] : Active flag is %d.\n", m_active)); + DEBUG_REPORT_LOG(true, ("[Commodities Server Auction::Expire] : Immediate flag is %d.\n", immediate)); + + if (m_sold) + { + DEBUG_REPORT_LOG(true, ("[Commodities Server Auction::Expire] : Old Owner is %s.\n", m_item->GetOwnerId().getValueString().c_str())); + m_item->SetOwnerId(m_highBid->GetBidderId()); + DEBUG_REPORT_LOG(true, ("[Commodities Server Auction::Expire] : New Owner is %s.\n", m_item->GetOwnerId().getValueString().c_str())); + + DEBUG_REPORT_LOG(true, ("[Commodities Server Auction::Expire] : Sending OnAuctionExpired for sold auction .\n")); + + AuctionMarket::getInstance().OnAuctionExpired( + GetCreatorId(), m_sold, m_flags, + m_highBid->GetBidderId(), m_highBid->GetBid(), m_item->GetItemId(), + m_highBid->GetMaxProxyBid(), + m_location.GetLocationString(), immediate, + m_item->GetNameLength(), m_item->GetName(), + m_item->GetOwnerId(), track_id, true); + } + else + { + if (m_highBid) + { + DEBUG_REPORT_LOG(true, ("[Commodities Server Auction::Expire] : Sending OnAuctionExpired for non-sold auction and high bid obj .\n")); + AuctionMarket::getInstance().OnAuctionExpired( + GetCreatorId(), m_sold, m_flags, + m_highBid->GetBidderId(), m_highBid->GetBid(), m_item->GetItemId(), + m_highBid->GetMaxProxyBid(), + m_location.GetLocationString(), immediate, + m_item->GetNameLength(), m_item->GetName(), + m_item->GetOwnerId(), track_id, true); + } + else + { + // for items on a vendor placed by the vendor owner, we + // use the following rule to determine if a mail message + // should be sent to the vendor owner when the item + // auction expire and goes back into the vendor stockroom; + // the goal here is to avoid sending too many mail message + // to a vendor owner when a bunch of auctions expire around + // the same time + // + // 1) if the auction did not expire because of the auction + // timer, don't send mail. This means if the vendor owner + // withdraws the sale of an item, no mail is sent. + // 2) if the auction expired because of the auction timer, + // send mail only for the first item, and don't send + // another mail until the next auction expires after + // the vendor is next accessed or the cluster is restarted. + bool sendSellerMail = true; + if (m_location.IsVendorMarket() && m_location.IsOwner(GetCreatorId())) + { + if (!expiredBasedOnTimer) + sendSellerMail = false; + else if (m_location.GetVendorFirstTimerExpiredAuctionDate() > 0) + sendSellerMail = false; + else + m_location.SetVendorFirstTimerExpiredAuctionDate(time(0)); + } + + DEBUG_REPORT_LOG(true, ("[Commodities Server Auction::Expire] : Sending OnAuctionExpired for non-sold auction and null high bid obj .\n")); + AuctionMarket::getInstance().OnAuctionExpired( + GetCreatorId(), m_sold, m_flags, + NetworkId::cms_invalid, 0, m_item->GetItemId(), 0, + m_location.GetLocationString(), immediate, + m_item->GetNameLength(), m_item->GetName(), + m_item->GetOwnerId(), track_id, sendSellerMail); + } + if (m_location.IsVendorMarket() && + m_location.IsOwner(GetCreatorId())) + { + //vendor owner canceled his own auction. Sorry this is such a hack + m_location.CancelVendorSale(this); + } + } + + if (m_location.IsVendorMarket()) + { + //If its a vendor, remove and then re-add the item to ensure it is in the right list + m_location.RemoveAuction(this); + m_location.AddAuction(this); + } +} + +// ---------------------------------------------------------------------- + +int Auction::GetBuyNowPriceWithSalesTax() const +{ + if( GetBuyNowPrice() > 0 ) + { + int salesTax = GetLocation().GetSalesTax(); + return (int)(GetBuyNowPrice() + (GetBuyNowPrice() * (salesTax/10000.0f))); + } + else + { + return 0; + } +} + +// ---------------------------------------------------------------------- + +void Auction::AddAttributes(const std::string & attributeName, const Unicode::String & attributeValue) +{ + // it it's a instant sale resource container, add "credits per unit" attribute + // once we receive the item count attribute for the resource container, and also + // ignore any existing "credits per unit" attribute to avoid duplicate attribute + if (AuctionItem::IsCategoryResourceContainer(m_item->GetCategory())) + { + if (m_buyNowPrice > 0) + { + if (attributeName == "credits_per_unit") + { + // ignore any existing credits per unit attribute; we'll recalculate it and add the updated attribute + return; + } + + m_attributes.push_back(std::make_pair(attributeName, attributeValue)); + + if (attributeName == "resource_contents") + { + int count = ::atoi(Unicode::wideToNarrow(attributeValue).c_str()); + if (count > 0) + { + char buffer[128]; + int const len = snprintf(buffer, sizeof(buffer)-1, "%.6f", (static_cast(m_buyNowPrice) / static_cast(count))); + buffer[sizeof(buffer)-1] = '\0'; + + // trim trailing 0s after the decimal point + char * pChar = buffer + len - 1; + while (pChar >= buffer) + { + if (*pChar == '.') + { + *pChar = '\0'; + break; + } + else if (*pChar != '0') + { + ++pChar; + *pChar = '\0'; + break; + } + + --pChar; + } + + m_attributes.push_back(std::make_pair("credits_per_unit", Unicode::narrowToWide(buffer))); + } + + return; + } + } + else + { + m_attributes.push_back(std::make_pair(attributeName, attributeValue)); + } + + SetItemResourceContainerClassCrc(attributeName, attributeValue); + } + else + { + m_attributes.push_back(std::make_pair(attributeName, attributeValue)); + } +} + +// ---------------------------------------------------------------------- + +void Auction::SetItemResourceContainerClassCrc() +{ + if (AuctionItem::IsCategoryResourceContainer(m_item->GetCategory()) && ((m_item->GetResourceContainerClassCrc() == 0) || (m_item->GetResourceNameCrc() == 0))) + { + for (std::vector >::const_iterator iter = m_attributes.begin(); iter != m_attributes.end(); ++iter) + { + if ((iter->first == "resource_class") || (iter->first == "resource_name")) + { + SetItemResourceContainerClassCrc(iter->first, iter->second); + + if ((m_item->GetResourceContainerClassCrc() != 0) && (m_item->GetResourceNameCrc() != 0)) + break; + } + } + } +} + +// ---------------------------------------------------------------------- + +void Auction::SetItemResourceContainerClassCrc(const std::string & attributeName, const Unicode::String & attributeValue) +{ + if (AuctionItem::IsCategoryResourceContainer(m_item->GetCategory()) && ((m_item->GetResourceContainerClassCrc() == 0) || (m_item->GetResourceNameCrc() == 0))) + { + if ((attributeName == "resource_class") || (attributeName == "resource_name")) + { + if ((attributeName == "resource_class") && (m_item->GetResourceContainerClassCrc() == 0)) + { + std::string className = Unicode::wideToNarrow(attributeValue); + if (0 == className.find("@resource/resource_names:")) + { + className = className.substr(sizeof("@resource/resource_names:") - 1); + if (!className.empty()) + { + m_item->SetResourceContainerClassCrc(static_cast(Crc::calculate(className.c_str()))); + } + } + } + else if ((attributeName == "resource_name") && (m_item->GetResourceNameCrc() == 0)) + { + std::string name = Unicode::wideToNarrow(attributeValue); + if (!name.empty()) + { + m_item->SetResourceName(name); + m_item->SetResourceNameCrc(static_cast(Crc::calculate(name.c_str()))); + } + } + + if ((m_item->GetResourceContainerClassCrc() != 0) && (m_item->GetResourceNameCrc() != 0)) + { + AuctionMarket::getInstance().AddResourceType(m_item->GetResourceContainerClassCrc(), m_item->GetResourceName()); + } + } + } +} + +// ---------------------------------------------------------------------- + +void Auction::BuildSearchableAttributeList() +{ + std::map const & sa = CommoditiesAdvancedSearchAttribute::getSearchAttributeForGameObjectType(m_item->GetCategory()); + if (sa.empty()) + return; + + std::map const & saAlias = CommoditiesAdvancedSearchAttribute::getSearchAttributeNameAliasesForGameObjectType(m_item->GetCategory()); + + // for factory crates, also include the attributes of the item inside the crate + std::map const * saItemInsideFactoryCrate = NULL; + std::map const * saAliasItemInsideFactoryCrate = NULL; + int gotItemInsideFactoryCrate = 0; + + if (m_item->GetCategory() == SharedObjectTemplate::GOT_misc_factory_crate) + { + // determine the type of item inside the crate by looking at the value of the object_type attribute + for (std::vector >::const_iterator iter = m_attributes.begin(); iter != m_attributes.end(); ++iter) + { + if (iter->first == "object_type") + { + std::string const objectType(Unicode::wideToNarrow(iter->second)); + if (0 == objectType.find("@got_n:")) + { + gotItemInsideFactoryCrate = GameObjectTypes::getGameObjectType(objectType.substr(7)); + if (gotItemInsideFactoryCrate == SharedObjectTemplate::GOT_misc_factory_crate) + { + // factory crate inside factory crate??? + gotItemInsideFactoryCrate = 0; + } + + if (gotItemInsideFactoryCrate > 0) + { + saItemInsideFactoryCrate = &(CommoditiesAdvancedSearchAttribute::getSearchAttributeForGameObjectType(gotItemInsideFactoryCrate)); + saAliasItemInsideFactoryCrate = &(CommoditiesAdvancedSearchAttribute::getSearchAttributeNameAliasesForGameObjectType(gotItemInsideFactoryCrate)); + + if (saItemInsideFactoryCrate->empty()) + saItemInsideFactoryCrate = NULL; + + if (saAliasItemInsideFactoryCrate->empty()) + saAliasItemInsideFactoryCrate = NULL; + } + } + + break; + } + } + } + + std::string attributeName; + for (std::vector >::const_iterator iter = m_attributes.begin(); iter != m_attributes.end(); ++iter) + { + // strip out the embedded trailing '\0' on those funky attribute + // name that have the trailing '\0' embedded in the string + // + // also, remove any leading/trailing white space + attributeName = Unicode::getTrim(iter->first.c_str()); + + // handle attribute name alias + if (!saAlias.empty()) + { + std::map::const_iterator const iterFindAlias = saAlias.find(attributeName); + if (iterFindAlias != saAlias.end()) + { + attributeName = iterFindAlias->second; + } + } + + std::map::const_iterator iterFind = sa.find(attributeName); + if ((iterFind == sa.end()) && (m_item->GetCategory() == SharedObjectTemplate::GOT_misc_factory_crate) && saItemInsideFactoryCrate) + { + // strip out the embedded trailing '\0' on those funky attribute + // name that have the trailing '\0' embedded in the string + // + // also, remove any leading/trailing white space + attributeName = Unicode::getTrim(iter->first.c_str()); + + // handle attribute name alias + if (saAliasItemInsideFactoryCrate && !saAliasItemInsideFactoryCrate->empty()) + { + std::map::const_iterator const iterFindAlias = saAliasItemInsideFactoryCrate->find(attributeName); + if (iterFindAlias != saAliasItemInsideFactoryCrate->end()) + { + attributeName = iterFindAlias->second; + } + } + + iterFind = saItemInsideFactoryCrate->find(attributeName); + if (iterFind == saItemInsideFactoryCrate->end()) + { + iterFind = sa.end(); + } + } + + if (iterFind != sa.end()) + { + if (iterFind->second->attributeDataType == CommoditiesAdvancedSearchAttribute::SADT_int) + { + if (!m_searchableAttributeInt) + m_searchableAttributeInt = new std::map; + + if (attributeName == "cat_wpn_other.wpn_range") + { + // special parsing for cat_wpn_other.wpn_range attribute which is + // of the "range" form 22-49m and we want to use the second value + std::string const narrowStr(Unicode::wideToNarrow(iter->second)); + + char const * const pChar = strchr(narrowStr.c_str(), '-'); + if (pChar) + { + (*m_searchableAttributeInt)[iterFind->second->attributeNameCrc] = ::atoi(pChar + 1); + } + else + { + (*m_searchableAttributeInt)[iterFind->second->attributeNameCrc] = ::atoi(narrowStr.c_str()); + } + } + else if (attributeName == "storage_module_rating") + { + // Storage Module Rating - 10 + std::string const narrowStr(Unicode::wideToNarrow(iter->second)); + + char const * const pChar = strchr(narrowStr.c_str(), '-'); + if (pChar) + { + (*m_searchableAttributeInt)[iterFind->second->attributeNameCrc] = ::atoi(pChar + 1); + } + else + { + (*m_searchableAttributeInt)[iterFind->second->attributeNameCrc] = ::atoi(narrowStr.c_str()); + } + } + else + { + (*m_searchableAttributeInt)[iterFind->second->attributeNameCrc] = ::atoi(Unicode::wideToNarrow(iter->second).c_str()); + } + } + else if (iterFind->second->attributeDataType == CommoditiesAdvancedSearchAttribute::SADT_float) + { + if (!m_searchableAttributeFloat) + m_searchableAttributeFloat = new std::map; + + (*m_searchableAttributeFloat)[iterFind->second->attributeNameCrc] = ::atof(Unicode::wideToNarrow(iter->second).c_str()); + } + else if (iterFind->second->attributeDataType == CommoditiesAdvancedSearchAttribute::SADT_string) + { + if (!m_searchableAttributeString) + m_searchableAttributeString = new std::map; + + // strip out the embedded trailing '\0' on those funky attribute + // values that have the trailing '\0' embedded in the string + // + // also, remove any leading/trailing white space + std::string const attributeValue(Unicode::getTrim(Unicode::wideToNarrow(iter->second).c_str())); + + // for resource container's "Resource Class" attribute, convert + // the string id to a display string so it can be searched on + if (AuctionItem::IsCategoryResourceContainer(m_item->GetCategory()) && (attributeName == "resource_class")) + { + (*m_searchableAttributeString)[iterFind->second->attributeNameCrc] = Unicode::getTrim(Unicode::toLower(Unicode::wideToNarrow(StringId::decodeString(Unicode::narrowToWide(attributeValue))))); + } + // for fish type, convert the string id to a display string so it can be searched on + else if ((m_item->GetCategory() == SharedObjectTemplate::GOT_misc) && (attributeName == "type")) + { + (*m_searchableAttributeString)[iterFind->second->attributeNameCrc] = Unicode::getTrim(Unicode::toLower(Unicode::wideToNarrow(StringId::decodeString(Unicode::narrowToWide(attributeValue))))); + } + else + { + (*m_searchableAttributeString)[iterFind->second->attributeNameCrc] = Unicode::toLower(attributeValue); + } + } + else if (iterFind->second->attributeDataType == CommoditiesAdvancedSearchAttribute::SADT_enum) + { + if (!m_searchableAttributeString) + m_searchableAttributeString = new std::map; + + // strip out the embedded trailing '\0' on those funky attribute + // values that have the trailing '\0' embedded in the string + std::string attributeValue(Unicode::wideToNarrow(iter->second).c_str()); + + // handle enum value alias + std::map::const_iterator const iterFindAlias = iterFind->second->enumValueAliasList.find(attributeValue); + if (iterFindAlias != iterFind->second->enumValueAliasList.end()) + { + attributeValue = iterFindAlias->second; + } + + // remove any leading/trailing white space + attributeValue = Unicode::getTrim(attributeValue); + + (*m_searchableAttributeString)[iterFind->second->attributeNameCrc] = Unicode::toLower(attributeValue); + + if (iterFind->second->defaultSearchValueList.count(attributeValue) <= 0) + { + std::string bufferStr; + char buffer[16]; + for (size_t i = 0, size = attributeValue.size(); i < size; ++i) + { + snprintf(buffer, sizeof(buffer)-1, "%d ", attributeValue[i]); + buffer[sizeof(buffer)-1] = '\0'; + + bufferStr += buffer; + } + + LOG("CustomerService", ("CommoditiesAttributeSearch:Item %s (%s) in category %d (%s) has value (%s) (%s) (%d) for attribute (%s) that is not in the attribute enum list", + m_item->GetItemId().getValueString().c_str(), + Unicode::wideToNarrow(m_item->GetName()).c_str(), + m_item->GetCategory(), + GameObjectTypes::getCanonicalName(m_item->GetCategory()).c_str(), + attributeValue.c_str(), + bufferStr.c_str(), + attributeValue.size(), + iterFind->second->attributeName.c_str())); + } + } + } + } + + // for ship component and ship flight computer (or factory crate containing them), need to add "certifications required" search attribute + bool const itemIsShipComponentOrShipFlightComputer = ((GameObjectTypes::getMaskedType(m_item->GetCategory()) == SharedObjectTemplate::GOT_ship_component) || (m_item->GetCategory() == SharedObjectTemplate::GOT_deed_droid)); + bool const factoryCrateItemIsShipComponentOrShipFlightComputer = ((m_item->GetCategory() == SharedObjectTemplate::GOT_misc_factory_crate) && (gotItemInsideFactoryCrate > 0) && ((GameObjectTypes::getMaskedType(gotItemInsideFactoryCrate) == SharedObjectTemplate::GOT_ship_component) || (gotItemInsideFactoryCrate == SharedObjectTemplate::GOT_deed_droid))); + if (itemIsShipComponentOrShipFlightComputer || factoryCrateItemIsShipComponentOrShipFlightComputer) + { + static std::map requiredCerts; + + // load the required certs table + static bool requiredCertsLoaded = false; + if (!requiredCertsLoaded) + { + requiredCertsLoaded = true; + + DataTable * table = DataTableManager::getTable("datatables/commodity/ship_certification_attribute.iff", true); + if (table) + { + int const columnItem = table->findColumnNumber("Item"); + int const columnCert = table->findColumnNumber("Certifications Required"); + + if ((columnItem >= 0) && (columnCert >= 0) && (columnItem != columnCert)) + { + std::string item, cert; + int const numRows = table->getNumRows(); + for (int i = 0; i < numRows; ++i) + { + item = Unicode::getTrim(table->getStringValue(columnItem, i)); + cert = Unicode::getTrim(table->getStringValue(columnCert, i)); + + if (!item.empty() && !cert.empty()) + { + requiredCerts[static_cast(CrcLowerString::calculateCrc(item.c_str()))] = cert; + } + } + } + + DataTableManager::close("datatables/commodity/ship_certification_attribute.iff"); + } + } + + std::map::const_iterator const iterFind = requiredCerts.find(m_item->GetItemTemplateId()); + if (iterFind != requiredCerts.end()) + { + if (!m_searchableAttributeString) + m_searchableAttributeString = new std::map; + + static uint32 const shipCertAttributeCrc = Crc::calculate("ship_equipment_certification_search_attribute"); + static uint32 const astromechCertAttributeCrc = Crc::calculate("astromech_certification_search_attribute"); + + if (itemIsShipComponentOrShipFlightComputer) + { + (*m_searchableAttributeString)[((m_item->GetCategory() == SharedObjectTemplate::GOT_deed_droid) ? astromechCertAttributeCrc : shipCertAttributeCrc)] = iterFind->second; + } + else + { + (*m_searchableAttributeString)[((gotItemInsideFactoryCrate == SharedObjectTemplate::GOT_deed_droid) ? astromechCertAttributeCrc : shipCertAttributeCrc)] = iterFind->second; + } + } + } +} + +// ---------------------------------------------------------------------- + +bool Auction::IsAdvancedFilterMatch(std::list const & advancedSearch, int matchAllAny) const +{ + if (advancedSearch.empty()) + return true; + + // the following is the logic what will be used to determine match/no match + + // "will only match if all applicable attribute filter conditions match" + // ASMAA_match_all -> true after all match + // -> false after first mismatch + + // "will only match if any applicable attribute filter condition does not match" + // ASMAA_not_match_any is basically "not ASMAA_match_all" + // ASMAA_not_match_any -> false after all match + // -> true after first mismatch + + // "will only match if any applicable attribute filter condition matches" + // ASMAA_match_any -> false after all mismatch + // -> true after first match + + // "will only match if no applicable attribute filter condition matches" + // (i.e. match none) + // ASMAA_not_match_all is basically "not ASMAA_match_any" + // ASMAA_not_match_all -> true after all mismatch + // -> false after first match + + int filterCountMatch = 0; + int filterCountNotMatch = 0; + bool applicableFilter; + bool matchFilter; + for (std::list::const_iterator iter = advancedSearch.begin(); iter != advancedSearch.end(); ++iter) + { + matchFilter = (*(s_searchConditionComparisonFn[static_cast(iter->comparison)]))(*iter, m_searchableAttributeInt, m_searchableAttributeFloat, m_searchableAttributeString, applicableFilter); + + if (!applicableFilter) + { + continue; + } + else if (matchFilter) // match filter + { + if (s_searchConditionMatchAllAnyActionAnyMatch[matchAllAny].first) + return s_searchConditionMatchAllAnyActionAnyMatch[matchAllAny].second; + + ++filterCountMatch; + } + else // does not match filter + { + if (s_searchConditionMatchAllAnyActionAnyNotMatch[matchAllAny].first) + return s_searchConditionMatchAllAnyActionAnyNotMatch[matchAllAny].second; + + ++filterCountNotMatch; + } + } + + // if we get this far, then either all applicable filters + // match or all applicable filters do not match, or there + // were no applicable filters + // + // it's impossible to have gotten this far and have some + // applicable filters match and some not match, because + // that situation should have caused an immediate return + // as soon as it was encountered + if (filterCountMatch > 0) + { + // all applicable filters match + return s_searchConditionMatchAllAnyActionAllMatch[matchAllAny]; + } + else if (filterCountNotMatch > 0) + { + // all applicable filters do not match + return s_searchConditionMatchAllAnyActionAllNotMatch[matchAllAny]; + } + + // no filter was applicable, so treat as if no filter was specified + return true; +} + +// ====================================================================== diff --git a/engine/server/application/CommoditiesServer/src/shared/Auction.h b/engine/server/application/CommoditiesServer/src/shared/Auction.h new file mode 100644 index 00000000..c72c0e45 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/Auction.h @@ -0,0 +1,157 @@ +// ====================================================================== +// +// Auction.h +// copyright (c) 2004 Sony Online Entertainment +// +// (refactorof original code only to the degree to make it work with new) +// (server & database framework ... i.e. none of the logic has changed) +// +// Original Author: Matt Severenson +// Refactored by : Doug Mellencamp +// +// ====================================================================== +#ifndef Auction_h +#define Auction_h + +#include "serverNetworkMessages/AuctionBase.h" +#include "AuctionItem.h" +#include "AuctionBid.h" + +#include +#include +#include +#include "Unicode.h" + +#include "sharedFoundation/NetworkId.h" +#include "sharedNetworkMessages/AuctionQueryHeadersMessage.h" + +class AuctionLocation; + +// ====================================================================== + +class Auction +{ +private: + Auction(); + Auction(const Auction&); + Auction& operator= (const Auction&); + +protected: + const NetworkId m_creatorId; + const int m_minBid; + int m_auctionTimer; + const int m_buyNowPrice; + const int m_userDescriptionLength; + const Unicode::String m_userDescription; + const int m_oobLength; + const Unicode::String m_oobData; + std::vector > m_attributes; + std::map * m_searchableAttributeInt; + std::map * m_searchableAttributeFloat; + std::map * m_searchableAttributeString; + AuctionBid * m_highBid; + AuctionItem * const m_item; + + bool m_sold; + bool m_active; + std::vector m_bids; + AuctionLocation & m_location; + const int m_flags; + + int m_trackId; + + int GetActualBid(AuctionBid *bid); + +public: + Auction( + const NetworkId & creatorId, + int minBid, + int auctionTimer, + const NetworkId & itemId, + int itemNameLength, + const Unicode::String & itemName, + int itemType, + int itemTemplateId, + int itemTimer, + int itemSize, + const AuctionLocation & location, + int flags, + int buyNowPrice, + int userDescriptionLength, + const Unicode::String & userDescription, + int oobLength, + const Unicode::String & oobData, + std::vector > const & attributes + ); + + Auction( + const NetworkId & creatorId, + int minBid, + int auctionTimer, + const NetworkId & itemId, + int itemNameLength, + const Unicode::String & itemName, + int itemType, + int itemTemplateId, + int itemTimer, + int itemSize, + const AuctionLocation & location, + int flags, + int buyNowPrice, + int userDescriptionLength, + const Unicode::String & userDescription, + int oobLength, + const Unicode::String & oobData, + std::vector > const & attributes, + bool isActive, + bool isSold + ); + + ~Auction(); + + static void Initialization(); + + const NetworkId & GetCreatorId() const {return m_creatorId;} + int GetMinBid() const {return m_minBid;} + int GetAuctionTimer() const {return m_auctionTimer;} + int GetBuyNowPrice() const {return m_buyNowPrice;} + int GetBuyNowPriceWithSalesTax() const; + int GetUserDescriptionLength() const {return m_userDescriptionLength;} + const Unicode::String & GetUserDescription() const {return m_userDescription;} + int GetOobLength() const {return m_oobLength;} + const Unicode::String & GetOobData() const {return m_oobData;} + std::vector > const & GetAttributes() const {return m_attributes;} + void GetAttributes(std::string & output) const; + void AddAttributes(const std::string & attributeName, const Unicode::String & attributeValue); + const AuctionBid * GetHighBid() const {return m_highBid;} + int GetHighBidAmount() const; + const AuctionBid * GetPreviousBid() const; + const AuctionBid * GetPlayerBid(const NetworkId & playerId) const; + AuctionItem & GetItem() const {return *m_item;} + bool IsSold() const {return m_sold;} + bool IsActive() const {return m_active;} + bool IsImmediate() const {return m_buyNowPrice > 0;} + int GetFlags() const {return m_flags;} + + AuctionResultCode AddBid(const NetworkId & bidderId, int bid, int maxProxyBid); + void AddLoadedBid(const NetworkId & bidderId, int bid, int maxProxyBid); + + bool Update(int gameTime); + void Expire(bool sold, bool expiredBasedOnTimer, int track_id = -1); + + AuctionLocation & GetLocation() const {return m_location;} + + void SetTrackId(int trackId) {m_trackId = trackId;} + + void BuildSearchableAttributeList(); + + bool IsAdvancedFilterMatch(std::list const & advancedSearch, int matchAllAny) const; + +private: + void SetItemResourceContainerClassCrc(); + void SetItemResourceContainerClassCrc(const std::string & attributeName, const Unicode::String & attributeValue); +}; + +#endif + +// ====================================================================== diff --git a/engine/server/application/CommoditiesServer/src/shared/AuctionBid.cpp b/engine/server/application/CommoditiesServer/src/shared/AuctionBid.cpp new file mode 100644 index 00000000..a91526b4 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/AuctionBid.cpp @@ -0,0 +1,73 @@ +// ====================================================================== +// +// AuctionBid.cpp +// copyright (c) 2004 Sony Online Entertainment +// +// (refactorof original code only to the degree to make it work with new) +// (server & database framework ... i.e. none of the logic has changed) +// +// Original Author: Matt Severenson +// Refactored by : Doug Mellencamp +// +// ====================================================================== + +#include "FirstCommodityServer.h" + +#include "AuctionBid.h" +#include + +// ====================================================================== + +AuctionBid::AuctionBid( + const NetworkId & bidderId, + int bid, + int maxProxyBid +) : +m_bidderId(bidderId), +m_bid(bid), +m_maxProxyBid(maxProxyBid) +{ +} + +// ---------------------------------------------------------------------- + +AuctionBid::~AuctionBid() +{ +} + +// ---------------------------------------------------------------------- + +const bool AuctionBid::operator > (const AuctionBid & rhs) const +{ + return (max(m_bid, m_maxProxyBid) > max(rhs.m_bid, rhs.m_maxProxyBid)); +} + +// ---------------------------------------------------------------------- + +const bool AuctionBid::operator >= (const AuctionBid & rhs) const +{ + return (max(m_bid, m_maxProxyBid) >= max(rhs.m_bid, rhs.m_maxProxyBid)); +} + +// ---------------------------------------------------------------------- + +const bool AuctionBid::operator == (const AuctionBid & rhs) const +{ + return (max(m_bid, m_maxProxyBid) == max(rhs.m_bid, rhs.m_maxProxyBid)); +} + +// ---------------------------------------------------------------------- + +const bool AuctionBid::operator < (const AuctionBid & rhs) const +{ + return (max(m_bid, m_maxProxyBid) < max(rhs.m_bid, rhs.m_maxProxyBid)); +} + +// ---------------------------------------------------------------------- + +const bool AuctionBid::operator <= (const AuctionBid & rhs) const +{ + return (max(m_bid, m_maxProxyBid) <= max(rhs.m_bid, rhs.m_maxProxyBid)); +} + +// ====================================================================== diff --git a/engine/server/application/CommoditiesServer/src/shared/AuctionBid.h b/engine/server/application/CommoditiesServer/src/shared/AuctionBid.h new file mode 100644 index 00000000..fde6fc3e --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/AuctionBid.h @@ -0,0 +1,53 @@ +// ====================================================================== +// +// AuctionBid.h +// copyright (c) 2004 Sony Online Entertainment +// +// (refactorof original code only to the degree to make it work with new) +// (server & database framework ... i.e. none of the logic has changed) +// +// Original Author: Matt Severenson +// Refactored by : Doug Mellencamp +// +// ====================================================================== + +#ifndef AuctionBid_h +#define AuctionBid_h + +#include +#include "sharedFoundation/NetworkId.h" +#include "serverNetworkMessages/AuctionBase.h" + +// ====================================================================== + +class AuctionBid +{ +private: + AuctionBid(); + AuctionBid(const AuctionBid&); + AuctionBid& operator= (const AuctionBid&); + +protected: + const NetworkId m_bidderId; + int m_bid; + const int m_maxProxyBid; + +public: + AuctionBid(const NetworkId & bidderId, int bid, int maxProxyBid); + ~AuctionBid(); + + const NetworkId & GetBidderId() const {return m_bidderId;} + int GetBid() const {return m_bid;} + int GetMaxProxyBid() const {return m_maxProxyBid;} + + void SetBid(int bid) {m_bid = bid;} + const bool operator>(const AuctionBid &rhs) const; + const bool operator>=(const AuctionBid &rhs) const; + const bool operator==(const AuctionBid &rhs) const; + const bool operator<(const AuctionBid &rhs) const; + const bool operator<=(const AuctionBid &rhs) const; +}; + +#endif + +// ====================================================================== diff --git a/engine/server/application/CommoditiesServer/src/shared/AuctionItem.cpp b/engine/server/application/CommoditiesServer/src/shared/AuctionItem.cpp new file mode 100644 index 00000000..3e62aeb6 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/AuctionItem.cpp @@ -0,0 +1,56 @@ +// ====================================================================== +// +// AuctionItem.cpp +// copyright (c) 2004 Sony Online Entertainment +// +// (refactorof original code only to the degree to make it work with new) +// (server & database framework ... i.e. none of the logic has changed) +// +// Original Author: Matt Severenson +// Refactored by : Doug Mellencamp +// +// ====================================================================== + +#include "FirstCommodityServer.h" +#include "AuctionItem.h" + +// ====================================================================== + +AuctionItem::AuctionItem( + const NetworkId & itemId, + const int category, + const int itemTemplateId, + const int itemTimer, + const int nameLength, + const Unicode::String & name, + const NetworkId & ownerId, + const int size +) : +m_itemId(itemId), +m_category(category), +m_itemTemplateId(itemTemplateId), +m_resourceContainerClassCrc(0), +m_resourceName(), +m_resourceNameCrc(0), +m_itemTimer(itemTimer), +m_nameLength(nameLength), +m_name(name), +m_ownerId(ownerId), +m_size(size) +{ +} + +// ---------------------------------------------------------------------- + +AuctionItem::~AuctionItem() +{ +} + +// ---------------------------------------------------------------------- + +bool AuctionItem::IsExpired(int gameTime) const +{ + return (gameTime > m_itemTimer); +} + +// ====================================================================== diff --git a/engine/server/application/CommoditiesServer/src/shared/AuctionItem.h b/engine/server/application/CommoditiesServer/src/shared/AuctionItem.h new file mode 100644 index 00000000..3e0650dd --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/AuctionItem.h @@ -0,0 +1,70 @@ +// ====================================================================== +// +// AuctionItem.h +// copyright (c) 2004 Sony Online Entertainment +// +// (refactorof original code only to the degree to make it work with new) +// (server & database framework ... i.e. none of the logic has changed) +// +// Original Author: Matt Severenson +// Refactored by : Doug Mellencamp +// +// ====================================================================== + +#ifndef AuctionItem_h +#define AuctionItem_h + +#include "Unicode.h" +#include "sharedFoundation/NetworkId.h" + +// ====================================================================== + +class AuctionItem +{ +private: + AuctionItem(); + AuctionItem(const AuctionItem&); + AuctionItem& operator= (const AuctionItem&); + +protected: + const NetworkId m_itemId; + const int m_category; + const int m_itemTemplateId; + int m_resourceContainerClassCrc; // for resource container, this contains the crc of the resource class + std::string m_resourceName; // for resource container, this is the name of the resource (like Iblovris) + int m_resourceNameCrc; // crc for m_resourceName + const int m_itemTimer; + const int m_nameLength; + const Unicode::String m_name; + NetworkId m_ownerId; + const int m_size; + +public: + AuctionItem(const NetworkId & itemId, int category, int itemTemplateId, int itemTimer, int nameLength, const Unicode::String & name, const NetworkId & ownerId, int size); + ~AuctionItem(); + + const NetworkId & GetItemId() const {return m_itemId;} + int GetCategory() const {return m_category;} + int GetItemTemplateId() const {return m_itemTemplateId;} + int GetResourceContainerClassCrc() const {return m_resourceContainerClassCrc;} + const std::string & GetResourceName() const {return m_resourceName;} + int GetResourceNameCrc() const {return m_resourceNameCrc;} + void SetResourceContainerClassCrc(int resourceContainerClassCrc) {m_resourceContainerClassCrc = resourceContainerClassCrc;} + void SetResourceName(const std::string & resourceName) {m_resourceName = resourceName;} + void SetResourceNameCrc(int resourceNameCrc) {m_resourceNameCrc = resourceNameCrc;} + int GetItemTimer() const {return m_itemTimer;} + int GetNameLength() const {return m_nameLength;} + const Unicode::String & GetName() const {return m_name;} + const NetworkId & GetOwnerId() const {return m_ownerId;} + int GetSize() const {return m_size;} + + void SetOwnerId(const NetworkId & ownerId) {m_ownerId = ownerId;} + + bool IsExpired(int gameTime) const; + + static bool IsCategoryResourceContainer(int category) {return ((category & 0xffffff00) == 0x00400000);} // SharedObjectTemplate::GOT_resource_container is 0x00400000 +}; + +#endif + +// ====================================================================== diff --git a/engine/server/application/CommoditiesServer/src/shared/AuctionLocation.cpp b/engine/server/application/CommoditiesServer/src/shared/AuctionLocation.cpp new file mode 100644 index 00000000..9cc38dff --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/AuctionLocation.cpp @@ -0,0 +1,524 @@ +// ====================================================================== +// +// AuctionLocation.cpp +// copyright (c) 2004 Sony Online Entertainment +// +// (refactorof original code only to the degree to make it work with new) +// (server & database framework ... i.e. none of the logic has changed) +// +// Original Author: Matt Severenson +// Refactored by : Doug Mellencamp +// +// ====================================================================== + +#include "FirstCommodityServer.h" +#include "AuctionLocation.h" +#include "AuctionMarket.h" +#include "DatabaseServerConnection.h" +#include "CommodityServer.h" +#include "serverNetworkMessages/CMUpdateLocationMessage.h" +#include "serverNetworkMessages/AuctionBase.h" +#include "sharedGame/GameObjectTypes.h" + +// ====================================================================== + +namespace AuctionMarketNameSpace +{ + int const cs_statusMask = 0x00FFFFFF; + int const cs_packedFlag = 0x01000000; + + std::map emptyAuctionList; +} + +using namespace AuctionMarketNameSpace; + +// ====================================================================== + +static AuctionMarket::VendorStatusCode nextStatus[AuctionMarket::REMOVED + 1][AuctionMarket::REMOVED + 1]; + +// ---------------------------------------------------------------------- + +void AuctionLocation::Initialization() +{ + nextStatus[AuctionMarket::ACTIVE][AuctionMarket::ACTIVE] = AuctionMarket::ACTIVE; + nextStatus[AuctionMarket::ACTIVE][AuctionMarket::EMPTY] = AuctionMarket::EMPTY; + nextStatus[AuctionMarket::ACTIVE][AuctionMarket::UNACCESSED] = AuctionMarket::UNACCESSED; + nextStatus[AuctionMarket::ACTIVE][AuctionMarket::EMPTY_AND_UNACCESSED] = AuctionMarket::EMPTY_AND_UNACCESSED; + nextStatus[AuctionMarket::ACTIVE][AuctionMarket::ENDANGERED] = AuctionMarket::ACTIVE; + nextStatus[AuctionMarket::ACTIVE][AuctionMarket::REMOVED] = AuctionMarket::ACTIVE; + nextStatus[AuctionMarket::EMPTY][AuctionMarket::ACTIVE] = AuctionMarket::ACTIVE; + nextStatus[AuctionMarket::EMPTY][AuctionMarket::EMPTY] = AuctionMarket::EMPTY; + nextStatus[AuctionMarket::EMPTY][AuctionMarket::UNACCESSED] = AuctionMarket::EMPTY_AND_UNACCESSED; + nextStatus[AuctionMarket::EMPTY][AuctionMarket::EMPTY_AND_UNACCESSED] = AuctionMarket::EMPTY_AND_UNACCESSED; + nextStatus[AuctionMarket::EMPTY][AuctionMarket::ENDANGERED] = AuctionMarket::ENDANGERED; + nextStatus[AuctionMarket::EMPTY][AuctionMarket::REMOVED] = AuctionMarket::EMPTY; + nextStatus[AuctionMarket::UNACCESSED][AuctionMarket::ACTIVE] = AuctionMarket::ACTIVE; + nextStatus[AuctionMarket::UNACCESSED][AuctionMarket::EMPTY] = AuctionMarket::EMPTY_AND_UNACCESSED; + nextStatus[AuctionMarket::UNACCESSED][AuctionMarket::UNACCESSED] = AuctionMarket::UNACCESSED; + nextStatus[AuctionMarket::UNACCESSED][AuctionMarket::EMPTY_AND_UNACCESSED] = AuctionMarket::EMPTY_AND_UNACCESSED; + nextStatus[AuctionMarket::UNACCESSED][AuctionMarket::ENDANGERED] = AuctionMarket::ENDANGERED; + nextStatus[AuctionMarket::UNACCESSED][AuctionMarket::REMOVED] = AuctionMarket::UNACCESSED; + nextStatus[AuctionMarket::EMPTY_AND_UNACCESSED][AuctionMarket::ACTIVE] = AuctionMarket::ACTIVE; + nextStatus[AuctionMarket::EMPTY_AND_UNACCESSED][AuctionMarket::EMPTY] = AuctionMarket::EMPTY_AND_UNACCESSED; + nextStatus[AuctionMarket::EMPTY_AND_UNACCESSED][AuctionMarket::UNACCESSED] = AuctionMarket::EMPTY_AND_UNACCESSED; + nextStatus[AuctionMarket::EMPTY_AND_UNACCESSED][AuctionMarket::EMPTY_AND_UNACCESSED] = AuctionMarket::EMPTY_AND_UNACCESSED; + nextStatus[AuctionMarket::EMPTY_AND_UNACCESSED][AuctionMarket::ENDANGERED] = AuctionMarket::ENDANGERED; + nextStatus[AuctionMarket::EMPTY_AND_UNACCESSED][AuctionMarket::REMOVED] = AuctionMarket::EMPTY_AND_UNACCESSED; + nextStatus[AuctionMarket::ENDANGERED][AuctionMarket::ACTIVE] = AuctionMarket::ACTIVE; + nextStatus[AuctionMarket::ENDANGERED][AuctionMarket::EMPTY] = AuctionMarket::ENDANGERED; + nextStatus[AuctionMarket::ENDANGERED][AuctionMarket::UNACCESSED] = AuctionMarket::ENDANGERED; + nextStatus[AuctionMarket::ENDANGERED][AuctionMarket::EMPTY_AND_UNACCESSED] = AuctionMarket::ENDANGERED; + nextStatus[AuctionMarket::ENDANGERED][AuctionMarket::ENDANGERED] = AuctionMarket::ENDANGERED; + nextStatus[AuctionMarket::ENDANGERED][AuctionMarket::REMOVED] = AuctionMarket::REMOVED; + nextStatus[AuctionMarket::REMOVED][AuctionMarket::ACTIVE] = AuctionMarket::REMOVED; + nextStatus[AuctionMarket::REMOVED][AuctionMarket::EMPTY] = AuctionMarket::REMOVED; + nextStatus[AuctionMarket::REMOVED][AuctionMarket::UNACCESSED] = AuctionMarket::REMOVED; + nextStatus[AuctionMarket::REMOVED][AuctionMarket::EMPTY_AND_UNACCESSED] = AuctionMarket::REMOVED; + nextStatus[AuctionMarket::REMOVED][AuctionMarket::ENDANGERED] = AuctionMarket::REMOVED; + nextStatus[AuctionMarket::REMOVED][AuctionMarket::REMOVED] = AuctionMarket::REMOVED; +} + +// ---------------------------------------------------------------------- + +AuctionLocation::AuctionLocation( + const NetworkId & locationId, + const std::string & location, + const NetworkId & ownerId, + int salesTax, + const NetworkId & salesTaxBankId, + int emptyDate, + int lastAccessDate, + int inactiveDate, + int status, + bool searchEnabled, + int entranceCharge +) : +m_locationId(locationId), +m_ownerId(ownerId), +m_location(location), +m_locationPlanet(), +m_locationRegion(), +m_salesTax(salesTax), +m_salesTaxBankId(salesTaxBankId), +m_emptyDate(emptyDate), +m_lastAccessDate(lastAccessDate), +m_vendorFirstTimerExpiredAuctionDate(0), +m_inactiveDate(inactiveDate), +m_nextUpdateTime(0), // force an immediate update on the auction location +m_status(status), +m_searchEnabled(searchEnabled), +m_entranceCharge(entranceCharge), +m_auctionItemCount(0), +m_auctions(), +m_auctionsIndexedByType(), +m_auctionsIndexedByParentTypeExactMatch(), +m_auctionsIndexedByTemplate(), +m_auctionsResourceContainer(), +m_vendorOffers() +{ + assert(location != ""); + assert(GetStatus() >= AuctionMarket::ACTIVE && GetStatus() <= AuctionMarket::REMOVED); + + AuctionMarket::getPlanetAndRegionFromLocationString(m_location, m_locationPlanet, m_locationRegion); + AuctionMarket::getInstance().addAuctionLocationToLocationIndex(this); + + AuctionMarket::getInstance().AddAuctionLocationToPriorityQueue(*this); +} + +// ---------------------------------------------------------------------- + +AuctionLocation::~AuctionLocation() +{ + AuctionMarket::getInstance().sanityCheckAuctionLocationBeingDestroyed(this); + AuctionMarket::getInstance().RemoveAuctionLocationFromPriorityQueue(*this); +} + +// ---------------------------------------------------------------------- + +bool AuctionLocation::AddAuction(Auction *auction) +{ + assert(auction != NULL); + if (IsVendorMarket() && + (!auction->IsActive() || !IsOwner(auction->GetCreatorId()))) + { +// printf("!!!Offering item to vendor\n"); + m_vendorOffers.insert(std::make_pair(auction->GetItem().GetItemId(), auction)); + } + else + { + m_auctionItemCount += auction->GetItem().GetSize(); + m_auctions.insert(std::make_pair(auction->GetItem().GetItemId(), auction)); + + if (AuctionItem::IsCategoryResourceContainer(auction->GetItem().GetCategory())) + { + m_auctionsResourceContainer.insert(std::make_pair(auction->GetItem().GetItemId(), auction)); + } + else if (auction->GetItem().GetCategory() != 0) + { + m_auctionsIndexedByType[auction->GetItem().GetCategory()].insert(std::make_pair(auction->GetItem().GetItemId(), auction)); + + if (GameObjectTypes::isSubType(auction->GetItem().GetCategory())) + { + m_auctionsIndexedByType[GameObjectTypes::getMaskedType(auction->GetItem().GetCategory())].insert(std::make_pair(auction->GetItem().GetItemId(), auction)); + } + else + { + m_auctionsIndexedByParentTypeExactMatch[auction->GetItem().GetCategory()].insert(std::make_pair(auction->GetItem().GetItemId(), auction)); + } + + if (auction->GetItem().GetItemTemplateId() != 0) + { + m_auctionsIndexedByTemplate[std::make_pair(auction->GetItem().GetCategory(), auction->GetItem().GetItemTemplateId())].insert(std::make_pair(auction->GetItem().GetItemId(), auction)); + } + } + } + return true; +} + +// ---------------------------------------------------------------------- + +//All vendor available items must be in the vendor offers list to be retrieved +void AuctionLocation::CancelVendorSale(Auction *auction) +{ + RemoveAuction(auction); + m_vendorOffers.insert(std::make_pair(auction->GetItem().GetItemId(), + auction)); +} + +// ---------------------------------------------------------------------- + +bool AuctionLocation::RemoveAuction(Auction *auction) +{ + assert(auction != NULL); + return RemoveAuction(auction->GetItem().GetItemId()); +} + +// ---------------------------------------------------------------------- + +bool AuctionLocation::RemoveAuction(const NetworkId & itemId) +{ + std::map::iterator i = m_auctions.find(itemId); + if (i != m_auctions.end()) + { + m_auctionItemCount -= (*i).second->GetItem().GetSize(); + if (m_auctionItemCount < 0) + { + m_auctionItemCount = 0; + } + + if (m_auctionItemCount == 0) + { + // vendor has reached 0 item, so force an immediate update on the auction location + SetNextUpdateTime(0); + } + + if (AuctionItem::IsCategoryResourceContainer((*i).second->GetItem().GetCategory())) + { + m_auctionsResourceContainer.erase((*i).second->GetItem().GetItemId()); + } + else if ((*i).second->GetItem().GetCategory() != 0) + { + m_auctionsIndexedByType[(*i).second->GetItem().GetCategory()].erase((*i).second->GetItem().GetItemId()); + + if (GameObjectTypes::isSubType((*i).second->GetItem().GetCategory())) + { + m_auctionsIndexedByType[GameObjectTypes::getMaskedType((*i).second->GetItem().GetCategory())].erase((*i).second->GetItem().GetItemId()); + } + else + { + m_auctionsIndexedByParentTypeExactMatch[(*i).second->GetItem().GetCategory()].erase((*i).second->GetItem().GetItemId()); + } + + if ((*i).second->GetItem().GetItemTemplateId() != 0) + { + m_auctionsIndexedByTemplate[std::make_pair((*i).second->GetItem().GetCategory(), (*i).second->GetItem().GetItemTemplateId())].erase((*i).second->GetItem().GetItemId()); + } + } + + m_auctions.erase(i); + } + else + { + i = m_vendorOffers.find(itemId); + if (i != m_vendorOffers.end()) + { + m_vendorOffers.erase(i); + } + } + return true; +} + +// ---------------------------------------------------------------------- + +Auction *AuctionLocation::GetAuction(const NetworkId & itemId) +{ + std::map::iterator i = m_auctions.find(itemId); + if (i != m_auctions.end()) + { + return((*i).second); + } + else + { + i = m_vendorOffers.find(itemId); + if (i != m_vendorOffers.end()) + { + return((*i).second); + } + } + return NULL; +} + +// ---------------------------------------------------------------------- + +int AuctionLocation::GetValue() const +{ + int value = 0; + std::map::const_iterator i = m_auctions.begin(); + while (i != m_auctions.end()) + { + Auction *auction = (*i).second; + if (auction->IsActive()) + { + int auctionValue = auction->GetBuyNowPrice(); + if (auctionValue > 0) + { + value += auctionValue; + } + } + ++i; + } + return value; +} + +// ---------------------------------------------------------------------- + +bool AuctionLocation::MatchLocation(const std::string & planet, const std::string & region, const NetworkId & locationId, bool checkLocationInfo, bool searchMyVendorsOnly, bool overrideVendorSearchFlag, const NetworkId & playerId, bool allowSearchVendors, const NetworkId & vendorId, const int searchType) const +{ + if (IsPacked()) + { + return false; + } + + if (!allowSearchVendors && IsVendorMarket()) + { + return false; + } + + if (searchMyVendorsOnly && playerId != m_ownerId) + { + return false; + } + + if (!m_searchEnabled && !overrideVendorSearchFlag && !searchMyVendorsOnly && IsVendorMarket()) + { + // Search is disabled on this vendor. However search of this vendor should still be allowed + // if player comes to the vendor to search. + return (vendorId == m_locationId); + } + + // do not show bazaar items while searching vendor items + if (searchType == AST_ByVendorSelling && (! IsVendorMarket())) + return false; + + if (checkLocationInfo) + { + if (locationId.isValid()) + return (locationId == m_locationId); + + if (!planet.empty() && (planet != m_locationPlanet)) + return false; + + if (!region.empty() && (region != m_locationRegion)) + return false; + } + + return true; +} + +// ---------------------------------------------------------------------- + +void AuctionLocation::SetOwnerId(const NetworkId & ownerId) +{ + AuctionMarket::getInstance().removeAuctionLocationFromLocationIndex(this); + + m_ownerId = ownerId; + + AuctionMarket::getInstance().addAuctionLocationToLocationIndex(this); + SetNextUpdateTime(0); // force an immediate update on the auction location +} + +// ---------------------------------------------------------------------- + +void AuctionLocation::SetLocationString( const std::string & newstr ) +{ + AuctionMarket::getInstance().removeAuctionLocationFromLocationIndex(this); + + m_location = newstr; + + AuctionMarket::getPlanetAndRegionFromLocationString(m_location, m_locationPlanet, m_locationRegion); + AuctionMarket::getInstance().addAuctionLocationToLocationIndex(this); +} + +// ---------------------------------------------------------------------- + +void AuctionLocation::SetSearchedEnabled(bool enabled) +{ + AuctionMarket::getInstance().removeAuctionLocationFromLocationIndex(this); + + m_searchEnabled = enabled; + + AuctionMarket::getInstance().addAuctionLocationToLocationIndex(this); +} + +// ---------------------------------------------------------------------- + +void AuctionLocation::SetSalesTax( int salesTax, const NetworkId & bankId ) +{ + m_salesTax = salesTax; + m_salesTaxBankId = bankId; + + //printf( "AuctionLocation::SetSalesTax() setting sales tax to %ld for bankId %Ld.\n", m_salesTax, m_salesTaxBankId.getValue()); +} + +// ---------------------------------------------------------------------- + +void AuctionLocation::SetNextUpdateTime(int nextUpdateTime) +{ + if (nextUpdateTime != m_nextUpdateTime) + { + AuctionMarket::getInstance().RemoveAuctionLocationFromPriorityQueue(*this); + } + + m_nextUpdateTime = nextUpdateTime; + AuctionMarket::getInstance().AddAuctionLocationToPriorityQueue(*this); +} + +// ---------------------------------------------------------------------- + +void AuctionLocation::Update(int emptyDate, int lastAccessDate, int inactiveDate, int status) +{ + int oldStatus = GetStatus(); + if (emptyDate >= 0) + { + m_emptyDate = emptyDate; + SetNextUpdateTime(0); // force an immediate update on the auction location + } + if (lastAccessDate >= 0) + { + m_lastAccessDate = lastAccessDate; + m_vendorFirstTimerExpiredAuctionDate = 0; + SetNextUpdateTime(0); // force an immediate update on the auction location + } + if (inactiveDate >= 0) + { + m_inactiveDate = inactiveDate; + SetNextUpdateTime(0); // force an immediate update on the auction location + } + if (status >= AuctionMarket::ACTIVE && status <= AuctionMarket::REMOVED) + { + WARNING((status != nextStatus[GetStatus()][status]), ("Location status inconsistency, old status = %d, new status = %d, expected status = %d", GetStatus(), status, nextStatus[GetStatus()][status])); + SetStatus(status); + } + + CMUpdateLocationMessage msg( + m_locationId, + m_ownerId, + m_location, + m_salesTax, + m_salesTaxBankId, + m_emptyDate, + m_lastAccessDate, + m_inactiveDate, + m_status, + m_searchEnabled, + m_entranceCharge); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + if (oldStatus == AuctionMarket::EMPTY && GetStatus() == AuctionMarket::ACTIVE) + AuctionMarket::getInstance().OnVendorStatusChange(-1, m_locationId, ARC_VendorStatusNotEmpty); +} + +// ---------------------------------------------------------------------- + +int AuctionLocation::GetStatus() const +{ + return m_status & cs_statusMask; +} + +// ---------------------------------------------------------------------- + +int AuctionLocation::GetFullStatus() const +{ + return m_status; +} + +// ---------------------------------------------------------------------- + +void AuctionLocation::SetStatus(int const status) +{ + AuctionMarket::getInstance().removeAuctionLocationFromLocationIndex(this); + + m_status = (m_status & ~cs_statusMask) | (status & cs_statusMask); + + AuctionMarket::getInstance().addAuctionLocationToLocationIndex(this); + SetNextUpdateTime(0); // force an immediate update on the auction location +} + +// ---------------------------------------------------------------------- + +void AuctionLocation::SetFullStatus(int const status, bool const upperBitsOnly) +{ + AuctionMarket::getInstance().removeAuctionLocationFromLocationIndex(this); + + if (upperBitsOnly) + m_status = (m_status & cs_statusMask) | (status & ~cs_statusMask); + else + m_status = status; + + AuctionMarket::getInstance().addAuctionLocationToLocationIndex(this); + SetNextUpdateTime(0); // force an immediate update on the auction location +} + +// ---------------------------------------------------------------------- + +bool AuctionLocation::IsPacked() const +{ + return m_status & cs_packedFlag; +} + +// ---------------------------------------------------------------------- + +std::map & AuctionLocation::GetAuctionsByType(int type) +{ + std::map >::iterator const iterFind = m_auctionsIndexedByType.find(type); + if (iterFind != m_auctionsIndexedByType.end()) + return iterFind->second; + + return emptyAuctionList; +} + +// ---------------------------------------------------------------------- + +std::map & AuctionLocation::GetAuctionsByParentTypeExactMatch(int type) +{ + std::map >::iterator const iterFind = m_auctionsIndexedByParentTypeExactMatch.find(type); + if (iterFind != m_auctionsIndexedByParentTypeExactMatch.end()) + return iterFind->second; + + return emptyAuctionList; +} + +// ---------------------------------------------------------------------- + +std::map & AuctionLocation::GetAuctionsByTemplate(int type, int templateId) +{ + std::map, std::map >::iterator const iterFind = m_auctionsIndexedByTemplate.find(std::make_pair(type, templateId)); + if (iterFind != m_auctionsIndexedByTemplate.end()) + return iterFind->second; + + return emptyAuctionList; +} + +// ====================================================================== diff --git a/engine/server/application/CommoditiesServer/src/shared/AuctionLocation.h b/engine/server/application/CommoditiesServer/src/shared/AuctionLocation.h new file mode 100644 index 00000000..3401b050 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/AuctionLocation.h @@ -0,0 +1,120 @@ +// ====================================================================== +// +// AuctionLocation.h +// copyright (c) 2004 Sony Online Entertainment +// +// (refactorof original code only to the degree to make it work with new) +// (server & database framework ... i.e. none of the logic has changed) +// +// Original Author: Matt Severenson +// Refactored by : Doug Mellencamp +// +// ====================================================================== + +#ifndef AuctionLocation_h +#define AuctionLocation_h + +#include "serverNetworkMessages/AuctionBase.h" +#include "Auction.h" + +#include +#include +#include "sharedFoundation/NetworkId.h" + +#define PUBLIC_OWNER 0 + +// ====================================================================== + +class AuctionLocation +{ +private: + AuctionLocation(); + AuctionLocation(const AuctionLocation&); + AuctionLocation& operator= (const AuctionLocation&); + +protected: + const NetworkId m_locationId; + NetworkId m_ownerId; + std::string m_location; + std::string m_locationPlanet; + std::string m_locationRegion; + int m_salesTax; + NetworkId m_salesTaxBankId; + int m_emptyDate; + int m_lastAccessDate; + int m_vendorFirstTimerExpiredAuctionDate; // time that first unsold auction expired by timer since vendor was last accessed + int m_inactiveDate; + int m_nextUpdateTime; + int m_status; + bool m_searchEnabled; + int m_entranceCharge; + int m_auctionItemCount; + std::map m_auctions; + std::map > m_auctionsIndexedByType; + std::map > m_auctionsIndexedByParentTypeExactMatch; + std::map, std::map > m_auctionsIndexedByTemplate; + std::map m_auctionsResourceContainer; + std::map m_vendorOffers; + +public: + AuctionLocation(const NetworkId & locationId, const std::string & location, const NetworkId & ownerId, int salesTax, const NetworkId & salesTaxBankId, int emptyDate, int lastAccessDate, int inactiveDate, int status, bool searchEnabled, int entranceCharge); + ~AuctionLocation(); + + void CancelVendorSale(Auction *auction); + + bool AddAuction(Auction *auction); + bool RemoveAuction(const NetworkId & itemId); + bool RemoveAuction(Auction *auction); + Auction * GetAuction(const NetworkId & itemId); + bool MatchLocation(const std::string & planet, const std::string & region, const NetworkId & locationId, bool checkLocationInfo, bool searchMyVendorsOnly, bool overrideVendorSearchFlag, const NetworkId & playerId, bool allowSearchVendors, const NetworkId & vendorId, const int searchType) const; + + bool IsVendorMarket() const {return m_ownerId.getValue() != PUBLIC_OWNER;} + bool IsOwner(const NetworkId & ownerId) const {return (ownerId == m_ownerId);} + int GetAuctionItemCount() const {return m_auctionItemCount;} + + const NetworkId & GetLocationId() const {return m_locationId;} + const NetworkId & GetOwnerId() const {return m_ownerId;} + int GetEmptyDate() const {return m_emptyDate;} + int GetLastAccessDate() const {return m_lastAccessDate;} + int GetVendorFirstTimerExpiredAuctionDate() const {return m_vendorFirstTimerExpiredAuctionDate;} + void SetVendorFirstTimerExpiredAuctionDate(int vendorFirstTimerExpiredAuctionDate) {m_vendorFirstTimerExpiredAuctionDate = vendorFirstTimerExpiredAuctionDate;} + int GetInactiveDate() const {return m_inactiveDate;} + int GetNextUpdateTime() const {return m_nextUpdateTime;} + void SetNextUpdateTime(int nextUpdateTime); + bool GetSearchEnabled() const {return m_searchEnabled;} + int GetEntranceCharge() const {return m_entranceCharge;} + void Update(int emptyDate, int lastAccessDate, int inactiveDate, int status); + + int GetValue() const; + + void SetOwnerId(const NetworkId & ownerId); + void SetLocationString( const std::string & newstr ); + void SetSalesTax(int salesTax, const NetworkId & bankId); + void SetSearchedEnabled(bool enabled); + void SetEntranceCharge(int entranceCharge) {m_entranceCharge = entranceCharge;} + int GetSalesTax() const {return m_salesTax;}; + const NetworkId & GetSalesTaxBankId() const {return m_salesTaxBankId;}; + const std::string & GetLocationString() const {return m_location;} + const std::string & GetLocationPlanet() const {return m_locationPlanet;} + const std::string & GetLocationRegion() const {return m_locationRegion;} + + std::map & GetAuctions() {return m_auctions;} + std::map & GetAuctionsByType(int type); + std::map & GetAuctionsByParentTypeExactMatch(int type); + std::map & GetAuctionsByTemplate(int type, int templateId); + std::map & GetAuctionsResourceContainer() {return m_auctionsResourceContainer;} + std::map & GetVendorOffers() {return m_vendorOffers;} + static void Initialization(); + + int GetStatus() const; + int GetFullStatus() const; + + void SetStatus(int const status); + void SetFullStatus(int const status, bool const upperBitsOnly); + + bool IsPacked() const; +}; + +#endif + +// ====================================================================== diff --git a/engine/server/application/CommoditiesServer/src/shared/AuctionMarket.cpp b/engine/server/application/CommoditiesServer/src/shared/AuctionMarket.cpp new file mode 100644 index 00000000..f5549484 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/AuctionMarket.cpp @@ -0,0 +1,5179 @@ +// ====================================================================== +// +// AuctionMarket.cpp (refactor of original Commodities Market code) +// copyright (c) 2004 Sony Online Entertainment +// +// Original Author: Matt Severenson +// Refactored by : Doug Mellencamp +// +// ====================================================================== + +#include "FirstCommodityServer.h" +#include "CommodityServer.h" +#include "AuctionMarket.h" +#include "GameServerConnection.h" +#include "ConfigCommodityServer.h" +#include "DatabaseServerConnection.h" +#include "StringId.h" +#include "sharedFoundation/Crc.h" +#include "sharedLog/Log.h" +#include "serverNetworkMessages/AuctionBase.h" +#include "serverNetworkMessages/CMCreateAuctionMessage.h" +#include "serverNetworkMessages/CMCreateAuctionBidMessage.h" +#include "serverNetworkMessages/CMCreateLocationMessage.h" +#include "serverNetworkMessages/CMDeleteAuctionMessage.h" +#include "serverNetworkMessages/CMDeleteLocationMessage.h" +#include "serverNetworkMessages/CMUpdateAuctionMessage.h" +#include "serverNetworkMessages/CMUpdateLocationMessage.h" +#include "sharedNetworkMessages/DeleteCharacterMessage.h" +#include "serverNetworkMessages/LoadCommoditiesMessage.h" +#include "serverNetworkMessages/OnAcceptHighBidMessage.h" +#include "serverNetworkMessages/OnAddAuctionMessage.h" +#include "serverNetworkMessages/OnAddBidMessage.h" +#include "serverNetworkMessages/OnAuctionExpiredMessage.h" +#include "serverNetworkMessages/OnCancelAuctionMessage.h" +#include "serverNetworkMessages/OnCleanupInvalidItemRetrievalMessage.h" +#include "serverNetworkMessages/OnCreateVendorMarketMessage.h" +#include "serverNetworkMessages/OnGetItemDetailsMessage.h" +#include "serverNetworkMessages/OnGetItemMessage.h" +#include "serverNetworkMessages/OnGetPlayerVendorCountMessage.h" +#include "serverNetworkMessages/OnGetVendorOwnerMessage.h" +#include "serverNetworkMessages/OnGetVendorValueMessage.h" +#include "serverNetworkMessages/OnItemExpiredMessage.h" +#include "serverNetworkMessages/OnPermanentAuctionPurchasedMessage.h" +#include "serverNetworkMessages/OnQueryAuctionHeadersMessage.h" +#include "serverNetworkMessages/OnVendorRefuseItemMessage.h" +#include "serverNetworkMessages/OnUpdateVendorSearchOptionMessage.h" +#include "serverNetworkMessages/QueryVendorItemCountMessage.h" +#include "serverNetworkMessages/OnQueryVendorItemCountReplyMessage.h" +#include "serverNetworkMessages/UpdateVendorStatusMessage.h" +#include "serverNetworkMessages/VendorStatusChangeMessage.h" +#include "sharedFoundation/CalendarTime.h" +#include "sharedGame/CommoditiesAdvancedSearchAttribute.h" +#include "sharedGame/GameObjectTypes.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" + +#include "utf8.h" +#include "UnicodeUtils.h" + +namespace AuctionMarketNamespace +{ + std::string const g_dummyName = "INVALID_CHARACTER"; + NetworkId const zeroNetworkId(static_cast(0)); + NetworkId const negOneNetworkId(static_cast(-1)); + char const * vendorStatus[] = {"Active", "Empty", "Unaccessed", "EmptyAndUnaccessed", "Endangered", "Removed"}; + + // ====================================================================== + + void encodeOOB(const Unicode::String & str, std::string & HexString ) + { + char buffer [5]; + Unicode::String localCopy(str); + Unicode::String::iterator z = localCopy.begin(); + while (z != localCopy.end()) + { + if (sprintf (buffer, "%04X", *z) < 0) + { + WARNING(true, ("[Commodities Server ] : Writing converted OOB hex value to buffer failed in: TaskCreateAuction::encodeOOB.\n")); + } + else + { + HexString += buffer; + } + z++; + } + + DEBUG_REPORT_LOG(ConfigCommodityServer::getShowAllDebugInfo(), ("[Commodities Server ][HEX OOB IN] : %s \n", HexString.c_str())); + + } + + // ---------------------------------------------------------------------- + + void GetHighBidInfo( + Auction const * const auction, + int & highBidOut, + NetworkId & highBidderIdOut + ) + { + if (auction->IsImmediate()) + { + highBidOut = auction->GetBuyNowPriceWithSalesTax(); + if (auction->GetHighBid()) + { + highBidderIdOut = auction->GetHighBid()->GetBidderId(); + } + } + else if (auction->GetHighBid()) + { + highBidOut = auction->GetHighBid()->GetBid(); + highBidderIdOut = auction->GetHighBid()->GetBidderId(); + } + else + { + highBidOut = auction->GetMinBid(); + } + } + + // ---------------------------------------------------------------------- + + AuctionDataHeader *MakeDataHeader( + NetworkId const & playerId, + Auction const * const auction, + int const type, + int const entranceCharge, + AuctionBid const * const playerBid = NULL + ) + { + AuctionDataHeader *header = new AuctionDataHeader; + + header->type = type; + header->auctionId = auction->GetItem().GetItemId(); + header->itemId = auction->GetItem().GetItemId(); + header->itemNameLength = auction->GetItem().GetNameLength(); + header->itemName = auction->GetItem().GetName(); + header->minBid = auction->GetMinBid(); + header->entranceCharge = entranceCharge; + + time_t currentTime = time(0); + if (auction->IsActive()) + { + if (auction->GetAuctionTimer() < currentTime) + { + header->timer = 0; + } + else + { + header->timer = auction->GetAuctionTimer() - currentTime; + } + } + else + { + if (auction->GetItem().GetItemTimer() < currentTime) + { + header->timer = 0; + } + else + { + header->timer = auction->GetItem().GetItemTimer() - currentTime; + } + } + header->buyNowPrice = auction->GetBuyNowPrice(); + header->location = auction->GetLocation().GetLocationString(); + header->ownerId = auction->GetCreatorId(); + + // Determine the high bid info + GetHighBidInfo(auction, header->highBid, header->highBidderId); + + if (type == AST_ByPlayerBids) + { + if (playerBid) + { + header->maxProxyBid = playerBid->GetMaxProxyBid(); + header->myBid = playerBid->GetBid(); + } + } + header->itemType = auction->GetItem().GetCategory(); + header->resourceContainerClassCrc = auction->GetItem().GetResourceContainerClassCrc(); + header->flags = auction->GetFlags(); + if (auction->IsActive()) + { + header->flags |= AUCTION_ACTIVE; + } + + return header; + } + + // ---------------------------------------------------------------------- + + bool IsTextFilterMatch( + Unicode::String const & itemName, + Unicode::UnicodeStringVector const & textFilterAllTokens, + Unicode::UnicodeStringVector const & textFilterAnyTokens) + { + bool isTextMatch = true; + + // We are doing a case insensitive search + Unicode::String const lowerCaseName = Unicode::toLower(itemName); + + if (!textFilterAllTokens.empty()) + { + // See if all of the tokens for the text filter can be found in the name + Unicode::UnicodeStringVector::const_iterator i; + for (i = textFilterAllTokens.begin(); i != textFilterAllTokens.end(); ++i) + { + if (lowerCaseName.find(*i) == Unicode::String::npos) + { + // We could not find a token so we do not match + isTextMatch = false; + break; + } + } + } + + // If the name has all the required tokens, make sure it has + // at least one of the "any" tokens + if (isTextMatch) + { + if (!textFilterAnyTokens.empty()) + { + // Assume we won't find a match + isTextMatch = false; + + // See if any of the tokens for the text filter can be found in the name + Unicode::UnicodeStringVector::const_iterator i; + for (i = textFilterAnyTokens.begin(); i != textFilterAnyTokens.end(); ++i) + { + if (lowerCaseName.find(*i) != Unicode::String::npos) + { + // We found a token so we match + isTextMatch = true; + break; + } + } + } + } + + return isTextMatch; + } + + // ---------------------------------------------------------------------- + + bool IsPriceFilterMatch( + Auction const * const auction, + int const entranceCharge, + int const priceFilterMin, + int const priceFilterMax, + bool const isPriceFilterToIncludeFee) + { + bool isPriceMatch = true; + if ((priceFilterMin != 0) || (priceFilterMax != 0)) + { + // Get the high bid info for the auction + int highBid; + NetworkId highBidderId; + GetHighBidInfo(auction, highBid, highBidderId); + + // Include the entrance fee for the price if necessary + if (isPriceFilterToIncludeFee) + { + highBid += entranceCharge; + } + + // Is this price less than the min specified? + if ((priceFilterMin != 0) && (highBid < priceFilterMin)) + { + isPriceMatch = false; + } + else + { + // Is this price greater than the max specified? + if ((priceFilterMax != 0) && (highBid > priceFilterMax)) + { + isPriceMatch = false; + } + } + } + + return isPriceMatch; + } + + // ---------------------------------------------------------------------- + + struct GetItemAttributeDataRequest + { + std::string action; + int requestingGameServerId; + NetworkId requester; + int gameObjectType; + bool exactGameObjectTypeMatch; + int throttleNumberItemsPerFrame; + int numberItemsProcessed; + NetworkId lastItemProcessed; + + // for GetItemAttributeData + std::string outputFileName; + std::map > > > allItemAttributes; + bool ignoreSearchableAttribute; + + // for GetItemAttributeDataValues + std::string attributeName; + int numberItemsMatchGameObjectType; + std::map attributeValue; + }; + + GetItemAttributeDataRequest * getItemAttributeDataRequest = NULL; + + void processItemAttributeData(std::map const & auctions); + + // ---------------------------------------------------------------------- + + void skipField(std::string const &source, unsigned int &pos, char const separator) + { + while (source[pos] && source[pos] != separator) + ++pos; + if (source[pos] == separator) + ++pos; + } + + // ---------------------------------------------------------------------- + + void nextInt(std::string const &source, unsigned int &pos, int &ret, char const separator) + { + ret = atoi(source.c_str()+pos); + skipField(source, pos, separator); + } + + // ---------------------------------------------------------------------- + + void nextString(std::string const &source, unsigned int &pos, std::string &ret, char const separator) + { + unsigned int oldPos = pos; + while (source[pos] && source[pos] != separator) + ++pos; + ret = source.substr(oldPos, pos-oldPos); + if (source[pos] == separator) + ++pos; + } + + // ---------------------------------------------------------------------- + + void nextOid(std::string const &source, unsigned int &pos, NetworkId &ret, char const separator) + { + unsigned int oldPos = pos; + skipField(source, pos, separator); + ret = NetworkId(source.substr(oldPos, pos-oldPos)); + } + + // ---------------------------------------------------------------------- + + void removeAuctionLocationFromList(std::map & auctionLocationList, const AuctionLocation * auctionLocation) + { + if (auctionLocation) + { + std::map::iterator const iterFind = auctionLocationList.find(auctionLocation->GetLocationId()); + if ((iterFind != auctionLocationList.end()) && (iterFind->second == auctionLocation)) + { + auctionLocationList.erase(iterFind); + } + } + } + +}; // namespace AuctionMarketNamespace + +// ====================================================================== + +void AuctionMarketNamespace::processItemAttributeData(std::map const & auctions) +{ + if (!getItemAttributeDataRequest) + return; + + int count = 0; + std::map::const_iterator iterAuction = auctions.upper_bound(getItemAttributeDataRequest->lastItemProcessed); + for (; iterAuction != auctions.end(); ++iterAuction) + { + if (getItemAttributeDataRequest->action == "GetItemAttributeData") + { + bool proceed = true; + if (getItemAttributeDataRequest->gameObjectType > 0) + { + if (getItemAttributeDataRequest->exactGameObjectTypeMatch) + { + if (iterAuction->second->GetItem().GetCategory() != getItemAttributeDataRequest->gameObjectType) + { + proceed = false; + } + } + else + { + if (!GameObjectTypes::isTypeOf(iterAuction->second->GetItem().GetCategory(), getItemAttributeDataRequest->gameObjectType)) + { + proceed = false; + } + } + } + + if (proceed) + { + std::map const * skipAttribute = NULL; + std::map const * skipAttributeAlias = NULL; + if (getItemAttributeDataRequest->ignoreSearchableAttribute) + { + std::map const & sa = CommoditiesAdvancedSearchAttribute::getSearchAttributeForGameObjectType(iterAuction->second->GetItem().GetCategory()); + if (!sa.empty()) + { + skipAttribute = &sa; + } + + if (skipAttribute) + { + std::map const & saAlias = CommoditiesAdvancedSearchAttribute::getSearchAttributeNameAliasesForGameObjectType(iterAuction->second->GetItem().GetCategory()); + if (!saAlias.empty()) + { + skipAttributeAlias = &saAlias; + } + } + } + + std::pair > > & itemAttributeData = getItemAttributeDataRequest->allItemAttributes[iterAuction->second->GetItem().GetCategory()]; + ++itemAttributeData.first; + + std::map > & itemAttributes = itemAttributeData.second; + + std::pair > > & parentItemAttributeData = getItemAttributeDataRequest->allItemAttributes[GameObjectTypes::getMaskedType(iterAuction->second->GetItem().GetCategory())]; + if (&itemAttributeData.first != &parentItemAttributeData.first) + ++parentItemAttributeData.first; + + std::map > & parentItemAttributes = parentItemAttributeData.second; + + std::vector > const & attributes = iterAuction->second->GetAttributes(); + for (std::vector >::const_iterator iterAttribute = attributes.begin(); iterAttribute != attributes.end(); ++iterAttribute) + { + if (skipAttribute && (skipAttribute->count(iterAttribute->first) >= 1)) + { + continue; + } + + if (skipAttributeAlias && (skipAttributeAlias->count(iterAttribute->first) >= 1)) + { + continue; + } + + std::map >::iterator const iterFindAttribute = itemAttributes.find(iterAttribute->first); + if (iterFindAttribute != itemAttributes.end()) + { + ++iterFindAttribute->second.first; + + if (iterFindAttribute->second.second.empty()) + iterFindAttribute->second.second = Unicode::wideToNarrow(iterAttribute->second); + } + else + { + itemAttributes.insert(std::make_pair(iterAttribute->first, std::make_pair(1, Unicode::wideToNarrow(iterAttribute->second)))); + } + + if (&itemAttributeData.first != &parentItemAttributeData.first) + { + std::map >::iterator const iterFindParentAttribute = parentItemAttributes.find(iterAttribute->first); + if (iterFindParentAttribute != parentItemAttributes.end()) + { + ++iterFindParentAttribute->second.first; + + if (iterFindParentAttribute->second.second.empty()) + iterFindParentAttribute->second.second = Unicode::wideToNarrow(iterAttribute->second); + } + else + { + parentItemAttributes.insert(std::make_pair(iterAttribute->first, std::make_pair(1, Unicode::wideToNarrow(iterAttribute->second)))); + } + } + } + } + } + else if (getItemAttributeDataRequest->action == "GetItemAttributeDataValues") + { + bool proceed = true; + if (getItemAttributeDataRequest->gameObjectType > 0) + { + if (getItemAttributeDataRequest->exactGameObjectTypeMatch) + { + if (iterAuction->second->GetItem().GetCategory() != getItemAttributeDataRequest->gameObjectType) + { + proceed = false; + } + } + else + { + if (!GameObjectTypes::isTypeOf(iterAuction->second->GetItem().GetCategory(), getItemAttributeDataRequest->gameObjectType)) + { + proceed = false; + } + } + } + + if (proceed) + { + ++getItemAttributeDataRequest->numberItemsMatchGameObjectType; + + std::vector > const & attributes = iterAuction->second->GetAttributes(); + for (std::vector >::const_iterator iterAttribute = attributes.begin(); iterAttribute != attributes.end(); ++iterAttribute) + { + if (iterAttribute->first == getItemAttributeDataRequest->attributeName) + { + std::string const value = Unicode::wideToNarrow(iterAttribute->second); + std::map::iterator const iterValue = getItemAttributeDataRequest->attributeValue.find(value); + if (iterValue != getItemAttributeDataRequest->attributeValue.end()) + { + ++iterValue->second; + } + else + { + getItemAttributeDataRequest->attributeValue.insert(std::make_pair(value, 1)); + } + } + } + } + } + + ++getItemAttributeDataRequest->numberItemsProcessed; + + ++count; + if (count >= getItemAttributeDataRequest->throttleNumberItemsPerFrame) + { + getItemAttributeDataRequest->lastItemProcessed = iterAuction->first; + break; + } + } + + if (iterAuction == auctions.end()) + { + std::string output; + char buffer[2048]; + + if (getItemAttributeDataRequest->action == "GetItemAttributeData") + { + for (std::map > > >::const_iterator iterOutputGot = getItemAttributeDataRequest->allItemAttributes.begin(); iterOutputGot != getItemAttributeDataRequest->allItemAttributes.end(); ++iterOutputGot) + { + snprintf(buffer, sizeof(buffer)-1, "%s (count=%d)", GameObjectTypes::getCanonicalName(iterOutputGot->first).c_str(), iterOutputGot->second.first); + buffer[sizeof(buffer)-1] = '\0'; + + output += buffer; + output += "\r\n"; + + for (std::map >::const_iterator iterOutputAttribute = iterOutputGot->second.second.begin(); iterOutputAttribute != iterOutputGot->second.second.end(); ++iterOutputAttribute) + { + snprintf(buffer, sizeof(buffer)-1, " %s (%s) (count=%d)", iterOutputAttribute->first.c_str(), iterOutputAttribute->second.second.c_str(), iterOutputAttribute->second.first); + buffer[sizeof(buffer)-1] = '\0'; + + output += buffer; + output += "\r\n"; + } + + output += "\r\n"; + } + + if (output.empty()) + { + output = "No Data"; + } + } + else if (getItemAttributeDataRequest->action == "GetItemAttributeDataValues") + { + snprintf(buffer, sizeof(buffer)-1, "%s (count=%d) attribute name=(%s)", GameObjectTypes::getCanonicalName(getItemAttributeDataRequest->gameObjectType).c_str(), getItemAttributeDataRequest->numberItemsMatchGameObjectType, getItemAttributeDataRequest->attributeName.c_str()); + buffer[sizeof(buffer)-1] = '\0'; + + output = buffer; + output += "\r\n"; + + for (std::map::const_iterator iter = getItemAttributeDataRequest->attributeValue.begin(); iter != getItemAttributeDataRequest->attributeValue.end(); ++iter) + { + snprintf(buffer, sizeof(buffer)-1, " (%s) (count=%d)", iter->first.c_str(), iter->second); + buffer[sizeof(buffer)-1] = '\0'; + + output += buffer; + output += "\r\n"; + } + } + + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(getItemAttributeDataRequest->requestingGameServerId); + if (gameServerConn) + { + if (getItemAttributeDataRequest->action == "GetItemAttributeData") + { + GenericValueTypeMessage, std::string> > const msg("GetItemAttributeDataRsp", std::make_pair(std::make_pair(getItemAttributeDataRequest->requester, getItemAttributeDataRequest->outputFileName), output)); + gameServerConn->send(msg, true); + } + else if (getItemAttributeDataRequest->action == "GetItemAttributeDataValues") + { + GenericValueTypeMessage > const msg("DisplayStringForPlayer", std::make_pair(getItemAttributeDataRequest->requester, output)); + gameServerConn->send(msg, true); + } + } + + delete getItemAttributeDataRequest; + getItemAttributeDataRequest = NULL; + } +} + +// ====================================================================== + +using namespace AuctionMarketNamespace; + +// ====================================================================== + +AuctionMarket::AuctionMarket() : +Singleton(), +m_locationIdMap(), +m_playerVendorListMap(), +m_allBazaar(), +m_bazaarByPlanet(), +m_bazaarByRegion(), +m_allSearchableVendor(), +m_searchableVendorByPlanet(), +m_searchableVendorByRegion(), +m_auctions(), +m_auctionsCountByGameObjectType(), +m_auctionsCountByGameObjectTypeChanged(), +m_auctionCountMap(), +m_resourceTreeHierarchy(), +m_itemTypeMap(), +m_itemTypeMapVersionNumber(0), +m_resourceTypeMap(), +m_resourceTypeMapVersionNumber(0), +m_gameTime(0), +m_showAllDebugInfo(ConfigCommodityServer::getShowAllDebugInfo()), +m_completedAuctions(), +m_priorityQueueAuctionTimer(), +m_priorityQueueItemTimer() +{ + // + // DO NOT DO ANYTHING HERE. DO IT IN SingletonInialize() + // +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::SingletonInialize() +{ + // ideally, these should be in the constructor, but they will result + // in calling the Singleton's getInstance() method while the + // Singleton is in the process of creating the Singleton, so + // it tries to create another Singleton leading to an infinite loop; + // we'll call this after the Singleton has been created + GetLocation(std::string("PUBLIC_LOCATION")); + + // initialize list of auctions count by game object type + GameObjectTypes::TypeStringMap const & gameObjectTypes = GameObjectTypes::getTypeStringMap(); + for (GameObjectTypes::TypeStringMap::const_iterator iter = gameObjectTypes.begin(); iter != gameObjectTypes.end(); ++iter) + { + m_auctionsCountByGameObjectType[iter->second] = 0; + m_auctionsCountByGameObjectTypeChanged.insert(iter->second); + } +} + +// ---------------------------------------------------------------------- + +AuctionMarket::~AuctionMarket() +{ + //We need to delete the auction and auction location objects + for (std::map::iterator i = m_auctions.begin(); i != m_auctions.end(); ++i) + { + if ((*i).second) + delete (*i).second; + } + for (std::map::iterator i = m_locationIdMap.begin(); i != m_locationIdMap.end(); ++i) + { + if ((*i).second) + delete (*i).second; + } +} + +// ---------------------------------------------------------------------- + +AuctionLocation *AuctionMarket::CreateLocation(const NetworkId & ownerId, const std::string & locationString, int entranceCharge) +{ + std::string locationId; + + NetworkId loc_id = GetLocationId(locationString); + AuctionLocation *auctionLocation = new AuctionLocation(loc_id, locationString, ownerId, 0, zeroNetworkId, 0, m_gameTime, 0, ACTIVE, true, entranceCharge); + + m_locationIdMap.insert(std::make_pair(loc_id, auctionLocation)); + if (ownerId != zeroNetworkId) + { + AddPlayerVendor(ownerId, loc_id, auctionLocation); + } + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new CreateLocationMessage.\n")); + + CMCreateLocationMessage msg( + auctionLocation->GetLocationId(), + auctionLocation->GetLocationString(), + auctionLocation->GetOwnerId(), + auctionLocation->GetSalesTax(), + auctionLocation->GetSalesTaxBankId(), + 0, + m_gameTime, + 0, + ACTIVE, + true, + entranceCharge + ); + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + + return auctionLocation; +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::InitializeFromDB() +{ + LoadCommoditiesMessage msg(1); + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + LOG("CommoditiesServer", ("send LoadCommoditiesMessage to SwgDatabaseServer")); + if (dbServer) + dbServer->send(msg, true); + else + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Cannot find dbServer to send LoadCommodities message.\n")); +} + +// ---------------------------------------------------------------------- + +AuctionLocation &AuctionMarket::GetLocation(const NetworkId &locationId) +{ + std::map::const_iterator i = + m_locationIdMap.find(locationId); + if (i != m_locationIdMap.end()) + { + return (* ((*i).second) ); + } + + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Couldnot find location_id %s from auction_locations.\n", locationId.getValueString().c_str())); + + AuctionLocation *location = CreateLocation(zeroNetworkId, "PUBLIC_LOCATION", 0); + return *location; +} + +// ---------------------------------------------------------------------- + +AuctionLocation &AuctionMarket::GetLocation(const std::string &locationString) +{ + NetworkId locationId(GetLocationId(locationString)); + std::map::const_iterator i = + m_locationIdMap.find(locationId); + if (i != m_locationIdMap.end()) + { + return (* ((*i).second) ); + } + + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Couldnot find location_id %s from auction_locations.\n", locationId.getValueString().c_str())); + + AuctionLocation *location = CreateLocation(zeroNetworkId, locationString, 0); + return *location; +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::ModifyAuctionCount(const NetworkId & playerId, int delta) +{ + std::map::iterator f = m_auctionCountMap.find(playerId); + int currentAmount = 0; + if (f != m_auctionCountMap.end()) + { + currentAmount = (*f).second; + } + + m_auctionCountMap[playerId] = (currentAmount + delta); +} + +// ---------------------------------------------------------------------- + +bool AuctionMarket::HasOpenAuctionSlots(const NetworkId & playerId) +{ + std::map::iterator f = m_auctionCountMap.find(playerId); + if (f != m_auctionCountMap.end()) + { + if ((*f).second >= MAX_AUCTIONS_PER_PLAYER) + { + return false; + } + } + return true; +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::AddPlayerVendor(const NetworkId & playerId, const NetworkId & vendorId, AuctionLocation * auctionLocation) +{ + (m_playerVendorListMap[playerId])[vendorId] = auctionLocation; +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::RemovePlayerVendor(const NetworkId & playerId, const NetworkId & vendorId) +{ + std::map >::iterator const iterPlayer = m_playerVendorListMap.find(playerId); + if (iterPlayer != m_playerVendorListMap.end()) + { + iterPlayer->second.erase(vendorId); + if (iterPlayer->second.empty()) + { + m_playerVendorListMap.erase(iterPlayer); + } + } +} + +// ---------------------------------------------------------------------- + +int AuctionMarket::GetVendorCount(const NetworkId & playerId) +{ + std::map >::const_iterator const iterPlayer = m_playerVendorListMap.find(playerId); + if (iterPlayer != m_playerVendorListMap.end()) + { + return iterPlayer->second.size(); + } + + return 0; +} + +// ---------------------------------------------------------------------- + +int AuctionMarket::GetItemCount(const NetworkId & playerId) +{ + int itemCount = 0; + + std::map >::const_iterator const iterPlayer = m_playerVendorListMap.find(playerId); + if (iterPlayer != m_playerVendorListMap.end()) + { + for (std::map::const_iterator iterAuctionLocation = iterPlayer->second.begin(); iterAuctionLocation != iterPlayer->second.end(); ++iterAuctionLocation) + { + itemCount += iterAuctionLocation->second->GetAuctionItemCount(); + } + } + + return itemCount; +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::AddAuctionToPriorityQueue(const Auction & auction) +{ + if (!(auction.GetFlags() & AUCTION_ALWAYS_PRESENT)) + { + if (auction.IsActive() && (auction.GetAuctionTimer() > 0)) + m_priorityQueueAuctionTimer.insert(std::make_pair(auction.GetAuctionTimer(), auction.GetItem().GetItemId())); + + if (auction.GetItem().GetItemTimer() > 0) + m_priorityQueueItemTimer.insert(std::make_pair(auction.GetItem().GetItemTimer(), auction.GetItem().GetItemId())); + } +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::AddAuctionLocationToPriorityQueue(const AuctionLocation & auctionLocation) +{ + m_priorityQueueAuctionLocation.insert(std::make_pair(auctionLocation.GetNextUpdateTime(), auctionLocation.GetLocationId())); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::RemoveAuctionLocationFromPriorityQueue(const AuctionLocation & auctionLocation) +{ + m_priorityQueueAuctionLocation.erase(std::make_pair(auctionLocation.GetNextUpdateTime(), auctionLocation.GetLocationId())); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::AddAuction(Auction *auction) +{ + assert(auction != NULL); + + AuctionLocation &location = auction->GetLocation(); + if (!location.IsOwner(auction->GetItem().GetOwnerId())) + { + ModifyAuctionCount(auction->GetItem().GetOwnerId(), 1); + } + + if ((auction->GetItem().GetItemTemplateId() != 0) && (auction->GetItem().GetCategory() != 0)) + { + bool newItemType = false; + + std::set & itemTypeList = m_itemTypeMap[auction->GetItem().GetCategory()]; + if (itemTypeList.count(auction->GetItem().GetItemTemplateId()) == 0) + { + newItemType = true; + IGNORE_RETURN(itemTypeList.insert(auction->GetItem().GetItemTemplateId())); + } + + if (newItemType) + { + ++m_itemTypeMapVersionNumber; + GenericValueTypeMessage > > msg("CommoditiesItemTypeAdded", std::make_pair(m_itemTypeMapVersionNumber, std::make_pair(auction->GetItem().GetCategory(), auction->GetItem().GetItemTemplateId()))); + CommodityServer::getInstance().sendToAllGameServers(msg); + } + } + + m_auctions.insert(std::make_pair(auction->GetItem().GetItemId(), auction)); + + std::string const & gameObjectType = GameObjectTypes::getCanonicalName(auction->GetItem().GetCategory()); + std::map::iterator iterAuctionsCountByGameObjectType = m_auctionsCountByGameObjectType.find(gameObjectType); + if (iterAuctionsCountByGameObjectType != m_auctionsCountByGameObjectType.end()) + { + ++iterAuctionsCountByGameObjectType->second; + m_auctionsCountByGameObjectTypeChanged.insert(gameObjectType); + + if (GameObjectTypes::isSubType(auction->GetItem().GetCategory())) + { + std::string const & gameParentObjectType = GameObjectTypes::getCanonicalName(GameObjectTypes::getMaskedType(auction->GetItem().GetCategory())); + std::map::iterator iterAuctionsCountByParentGameObjectType = m_auctionsCountByGameObjectType.find(gameParentObjectType); + if (iterAuctionsCountByParentGameObjectType != m_auctionsCountByGameObjectType.end()) + { + ++iterAuctionsCountByParentGameObjectType->second; + m_auctionsCountByGameObjectTypeChanged.insert(gameParentObjectType); + } + } + } + + location.AddAuction(auction); + AddAuctionToPriorityQueue(*auction); + + if (auction->IsActive() && auction->IsSold()) + AddAuctionToCompletedAuctionsList(*auction); + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new CreateAuctionMessage.\n")); + LOG("CommoditiesServer", ("Player %s put item %s for sale at location %s for %d", + auction->GetCreatorId().getValueString().c_str(), + auction->GetItem().GetItemId().getValueString().c_str(), + auction->GetLocation().GetLocationId().getValueString().c_str(), + auction->GetBuyNowPrice() + auction->GetMinBid())); + LOG("CustomerService", ("Auction: Player %s put item %s for sale at location %s for %d", + auction->GetCreatorId().getValueString().c_str(), + auction->GetItem().GetItemId().getValueString().c_str(), + auction->GetLocation().GetLocationId().getValueString().c_str(), + auction->GetBuyNowPrice() + auction->GetMinBid())); + Unicode::String itemName(auction->GetItem().GetName()); + if (itemName.size() >= 1024) + { + itemName.assign(itemName, 0, 1023); + } + Unicode::String userDesc(auction->GetUserDescription()); + if (userDesc.size() >= 1024) + { + userDesc.assign(userDesc, 0, 1023); + } + CMCreateAuctionMessage msg( + auction->GetCreatorId(), + auction->GetMinBid(), + auction->GetAuctionTimer(), + auction->GetBuyNowPrice(), + userDesc.size(), + userDesc, + auction->GetAttributes(), + auction->GetLocation().GetLocationId(), + auction->GetItem().GetItemId(), + auction->GetItem().GetCategory(), + auction->GetItem().GetItemTemplateId(), + auction->GetItem().GetItemTimer(), + itemName.size(), + itemName, + auction->GetItem().GetOwnerId(), + (1 | auction->GetFlags()), + auction->GetItem().GetSize()); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::DestroyAuction(std::map::iterator &i) +{ + if (i != m_auctions.end()) + { + Auction *auction = (*i).second; + const NetworkId itemId = auction->GetItem().GetItemId(); + m_auctions.erase(i); + + std::string const & gameObjectType = GameObjectTypes::getCanonicalName(auction->GetItem().GetCategory()); + std::map::iterator iterAuctionsCountByGameObjectType = m_auctionsCountByGameObjectType.find(gameObjectType); + if ((iterAuctionsCountByGameObjectType != m_auctionsCountByGameObjectType.end()) && (iterAuctionsCountByGameObjectType->second > 0)) + { + --iterAuctionsCountByGameObjectType->second; + m_auctionsCountByGameObjectTypeChanged.insert(gameObjectType); + + if (GameObjectTypes::isSubType(auction->GetItem().GetCategory())) + { + std::string const & gameParentObjectType = GameObjectTypes::getCanonicalName(GameObjectTypes::getMaskedType(auction->GetItem().GetCategory())); + std::map::iterator iterAuctionsCountByParentGameObjectType = m_auctionsCountByGameObjectType.find(gameParentObjectType); + if ((iterAuctionsCountByParentGameObjectType != m_auctionsCountByGameObjectType.end()) && (iterAuctionsCountByParentGameObjectType->second > 0)) + { + --iterAuctionsCountByParentGameObjectType->second; + m_auctionsCountByGameObjectTypeChanged.insert(gameParentObjectType); + } + } + } + + AuctionLocation &location = auction->GetLocation(); + if (!location.IsOwner(auction->GetItem().GetOwnerId())) + { + ModifyAuctionCount(auction->GetItem().GetOwnerId(), -1); + } + location.RemoveAuction(auction); + m_priorityQueueAuctionTimer.erase(std::make_pair(auction->GetAuctionTimer(), itemId)); + m_priorityQueueItemTimer.erase(std::make_pair(auction->GetItem().GetItemTimer(), itemId)); + + delete auction; + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new DeleteAuctionMessage.\n")); + CMDeleteAuctionMessage msg(itemId); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Item ItemId : %s.\n", msg.GetItemId().getValueString().c_str())); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + } + else + { + printf("Yo this is whacked\n"); + } +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::UpdateLiveAuctions(int gameTime) +{ + if (getItemAttributeDataRequest) + processItemAttributeData(m_auctions); + + // build the list of auctions that needs to be processed + std::set auctionsToBeProcessed; + + // auctions that have completed but not yet processed + for (std::vector::const_iterator iterCompletedAuctions = m_completedAuctions.begin(); iterCompletedAuctions != m_completedAuctions.end(); ++iterCompletedAuctions) + auctionsToBeProcessed.insert(*iterCompletedAuctions); + + m_completedAuctions.clear(); + + // auctions whose auction timer has expired + for (std::set >::iterator iterAuctionTimer = m_priorityQueueAuctionTimer.begin(); iterAuctionTimer != m_priorityQueueAuctionTimer.end();) + { + if (gameTime >= (*iterAuctionTimer).first) + { + auctionsToBeProcessed.insert((*iterAuctionTimer).second); + m_priorityQueueAuctionTimer.erase(iterAuctionTimer++); + } + else + { + break; + } + } + + // auctions whose item timer has expired + for (std::set >::iterator iterItemTimer = m_priorityQueueItemTimer.begin(); iterItemTimer != m_priorityQueueItemTimer.end();) + { + if (gameTime > (*iterItemTimer).first) + { + auctionsToBeProcessed.insert((*iterItemTimer).second); + m_priorityQueueItemTimer.erase(iterItemTimer++); + } + else + { + break; + } + } + + // process auctions needing to be processed + std::set::const_iterator iterAuctionsToBeProcessed; + std::vector::iterator> completedAuctions; + std::map::iterator auctionsIterator; + + for (iterAuctionsToBeProcessed = auctionsToBeProcessed.begin(); iterAuctionsToBeProcessed != auctionsToBeProcessed.end(); ++iterAuctionsToBeProcessed) + { + auctionsIterator = m_auctions.find(*iterAuctionsToBeProcessed); + if (auctionsIterator != m_auctions.end()) + { + if ((*auctionsIterator).second->Update(gameTime) == false) + { + //item is finished. + const AuctionItem &item = (*auctionsIterator).second->GetItem(); + const AuctionLocation &location = (*auctionsIterator).second->GetLocation(); + OnItemExpired(item.GetOwnerId(), item.GetItemId(), + item.GetNameLength(), item.GetName(), + location.GetLocationString(), location.GetLocationId()); + completedAuctions.push_back(auctionsIterator); + } + } + } + + std::vector::iterator>::iterator ri = + completedAuctions.begin(); + while (ri != completedAuctions.end()) + { + auctionsIterator = (*ri); + LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because auction has expired (gametime: %d, itemTimer: %d).", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str(), gameTime, (*auctionsIterator).second->GetItem().GetItemTimer())); + LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because auction has expired (gametime: %d, itemTimer: %d).", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str(), gameTime, (*auctionsIterator).second->GetItem().GetItemTimer())); + DestroyAuction(auctionsIterator); + ++ri; + } + + std::list auctionLocationsToBeProcessed; + { + for (std::set >::iterator iterAuctionLocationToBeProcessed = m_priorityQueueAuctionLocation.begin(); iterAuctionLocationToBeProcessed != m_priorityQueueAuctionLocation.end();) + { + if (gameTime > (*iterAuctionLocationToBeProcessed).first) + { + std::map::iterator iterFind = m_locationIdMap.find((*iterAuctionLocationToBeProcessed).second); + if (iterFind != m_locationIdMap.end()) + { + auctionLocationsToBeProcessed.push_back(iterFind->second); + } + + m_priorityQueueAuctionLocation.erase(iterAuctionLocationToBeProcessed++); + } + else + { + break; + } + } + } + + for (std::list::iterator locationIterator = auctionLocationsToBeProcessed.begin(); locationIterator != auctionLocationsToBeProcessed.end(); ++locationIterator) + { + if ((*locationIterator)->IsVendorMarket()) + { + VendorStatusCode status = (VendorStatusCode) (*locationIterator)->GetStatus(); + VendorStatusCode newStatus = status; + int emptyDate = (*locationIterator)->GetEmptyDate(); + int lastAccessDate = (*locationIterator)->GetLastAccessDate(); + int inactiveDate = (*locationIterator)->GetInactiveDate(); + int newEmptyDate = -1, newLastAccessDate = -1, newInactiveDate = -1; + switch (status) { + case ACTIVE: + if ((*locationIterator)->GetAuctionItemCount() == 0) + { + newStatus = EMPTY; + newEmptyDate = m_gameTime; + } + else + { + int const unaccessedTime = lastAccessDate + (ConfigCommodityServer::getMinutesActiveToUnaccessed() * 60); + if (m_gameTime >= unaccessedTime) + { + newStatus = UNACCESSED; + } + else + { + (*locationIterator)->SetNextUpdateTime(unaccessedTime); + } + } + break; + case EMPTY: + { + int const endangeredTime = emptyDate + (ConfigCommodityServer::getMinutesEmptyToEndangered() * 60); + int const emptyAndUnaccessedTime = lastAccessDate + (ConfigCommodityServer::getMinutesUnaccessedToEndangered() * 60); + if (m_gameTime >= endangeredTime) + { + newStatus = ENDANGERED; + newInactiveDate = m_gameTime; + } + else if (m_gameTime >= emptyAndUnaccessedTime) + { + newStatus = EMPTY_AND_UNACCESSED; + } + else + { + (*locationIterator)->SetNextUpdateTime((endangeredTime < emptyAndUnaccessedTime) ? endangeredTime : emptyAndUnaccessedTime); + } + } + break; + case UNACCESSED: + { + int const endangeredTime = lastAccessDate + ((ConfigCommodityServer::getMinutesActiveToUnaccessed() + ConfigCommodityServer::getMinutesUnaccessedToEndangered()) * 60); + if (m_gameTime >= endangeredTime) + { + newStatus = ENDANGERED; + newInactiveDate = m_gameTime; + } + else if (emptyDate > 0) + { + int const emptyAndUnaccessedTime = emptyDate + (ConfigCommodityServer::getMinutesEmptyToEndangered() * 60); + if (m_gameTime >= emptyAndUnaccessedTime) + { + newStatus = EMPTY_AND_UNACCESSED; + } + else + { + (*locationIterator)->SetNextUpdateTime((endangeredTime < emptyAndUnaccessedTime) ? endangeredTime : emptyAndUnaccessedTime); + } + } + else + { + (*locationIterator)->SetNextUpdateTime(endangeredTime); + } + } + break; + case EMPTY_AND_UNACCESSED: + { + int const endangeredTime1 = emptyDate + (ConfigCommodityServer::getMinutesEmptyToEndangered() * 60); + int const endangeredTime2 = lastAccessDate + ((ConfigCommodityServer::getMinutesActiveToUnaccessed() + ConfigCommodityServer::getMinutesUnaccessedToEndangered()) * 60); + if ((m_gameTime >= endangeredTime1) || (m_gameTime >= endangeredTime2)) + { + newStatus = ENDANGERED; + newInactiveDate = m_gameTime; + } + else + { + (*locationIterator)->SetNextUpdateTime((endangeredTime1 < endangeredTime2) ? endangeredTime1 : endangeredTime2); + } + } + break; + case ENDANGERED: + { + int const removedTime = inactiveDate + (ConfigCommodityServer::getMinutesEndangeredToRemoved() * 60); + if (m_gameTime >= removedTime) + { + newStatus = REMOVED; + } + else + { + (*locationIterator)->SetNextUpdateTime(removedTime); + } + } + break; + case REMOVED: + newStatus = REMOVED; + } + if (status != newStatus) + { + (*locationIterator)->Update(newEmptyDate, newLastAccessDate, newInactiveDate, newStatus); + LOG("CustomerService", ("Vendor: Vendor %s (owner %s) status changed from %s to %s", (*locationIterator)->GetLocationId().getValueString().c_str(), (*locationIterator)->GetOwnerId().getValueString().c_str(), vendorStatus[status], vendorStatus[newStatus])); + LOG("CommoditiesServer", ("Vendor %s (owner %s) status changed from %s to %s", (*locationIterator)->GetLocationId().getValueString().c_str(), (*locationIterator)->GetOwnerId().getValueString().c_str(), vendorStatus[status], vendorStatus[newStatus])); + AuctionResultCode arc; + switch (newStatus) { + case EMPTY: + arc = ARC_VendorStatusEmpty; + break; + case UNACCESSED: + arc = ARC_VendorUnaccessed; + break; + case EMPTY_AND_UNACCESSED: + if (status == EMPTY) + arc = ARC_VendorUnaccessed; + else + arc = ARC_VendorStatusEmpty; + break; + case ENDANGERED: + arc = ARC_VendorEndangered; + LOG("CommoditiesServer", ("Vendor %s becomes endangered being removed from game.", + (*locationIterator)->GetLocationId().getValueString().c_str())); + LOG("CuxtomerService", ("Vendor: Vendor %s becomes endangered being removed from game.", + (*locationIterator)->GetLocationId().getValueString().c_str())); + break; + case REMOVED: + arc = ARC_VendorRemoved; + LOG("CommoditiesServer", ("Vendor %s will be removed from game due to empty or inactivity.", + (*locationIterator)->GetLocationId().getValueString().c_str())); + LOG("CustomerService", ("Vendor: Vendor %s will be removed from game due to empty or inactivity.", + (*locationIterator)->GetLocationId().getValueString().c_str())); + break; + default: + // newStatus is ACTIVE, which is impossible. + // code added to avoid error in release build + arc = ARC_Success; + } + OnVendorStatusChange(-1, (*locationIterator)->GetLocationId(), arc); + } + } + } + + // if a processed auction is still valid (i.e. not yet deleted), + // add it back to the priority queue so it can be processed + // at its next timer expiration time + for (iterAuctionsToBeProcessed = auctionsToBeProcessed.begin(); iterAuctionsToBeProcessed != auctionsToBeProcessed.end(); ++iterAuctionsToBeProcessed) + { + auctionsIterator = m_auctions.find(*iterAuctionsToBeProcessed); + + if (auctionsIterator != m_auctions.end()) + { + AddAuctionToPriorityQueue(*(auctionsIterator->second)); + + if (auctionsIterator->second->IsActive() && auctionsIterator->second->IsSold()) + AddAuctionToCompletedAuctionsList(*(auctionsIterator->second)); + } + } +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::DestroyExpiredItems(int gameTime) +{ +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::Update(int gameTime) +{ + m_gameTime = time(0); + DestroyExpiredItems(gameTime); + UpdateLiveAuctions(gameTime); +} + +// ====================================================================== +// +// AuctionMarket Network Message Handlers +// +// ====================================================================== + +void AuctionMarket::AddAuction(const AddAuctionMessage &message) +{ + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : OwnerName : %s.\n", message.GetOwnerName().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : MinimumBid : %d.\n", message.GetMinimumBid())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : AuctionTimer : %d.\n", message.GetAuctionTimer())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemNameLength : %d.\n", message.GetItemNameLength())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemName : %s.\n", Unicode::wideToNarrow(message.GetItemName()).c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemType : %d.\n", message.GetItemType())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemTemplateId : %d.\n", message.GetItemTemplateId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ExpireTimer : %d.\n", message.GetExpireTimer())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : LocationId : %s.\n", message.GetLocationId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : Location : %s.\n", message.GetLocation().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : Flags : %d.\n", message.GetFlags())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : UserDescriptionLength : %d.\n", message.GetUserDescriptionLength())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : UserDescription : %s.\n", Unicode::wideToNarrow(message.GetUserDescription()).c_str())); +// DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : OobLength : %d.\n", message.GetOobLength())); +// DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : OobActualLength : %d.\n", message.GetOobData().size())); +// DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : OobData : %s.\n", Unicode::wideToNarrow(message.GetOobData()).c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ItemSize : %d.\n", message.GetItemSize())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : Vendor Limit : %d.\n", message.GetVendorLimit())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : Vendor Item Limit : %d.\n", message.GetVendorItemLimit())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddAuctionMessage] : TrackId : %d.\n", message.GetTrackId())); + + std::map::iterator exists = m_auctions.find( + message.GetItemId()); + AuctionLocation &auctionLocation = GetLocation(std::string(message.GetLocation())); + if (exists != m_auctions.end()) + { + OnAddAuction(message.GetTrackId(), ARC_AuctionAlreadyExists, + message.GetResponseId(), + message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(), + auctionLocation.GetOwnerId(), + auctionLocation.GetLocationString()); + return; + } + if (!auctionLocation.IsOwner(message.GetOwnerId()) && !HasOpenAuctionSlots(message.GetOwnerId())) + { + OnAddAuction(message.GetTrackId(), ARC_TooManyAuctions, + message.GetResponseId(), + message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(), + auctionLocation.GetOwnerId(), + auctionLocation.GetLocationString()); + return; + } + + if (auctionLocation.IsVendorMarket()) + { + OnAddAuction(message.GetTrackId(), ARC_AuctionAtVendorMarket, + message.GetResponseId(), + message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(), + auctionLocation.GetOwnerId(), + auctionLocation.GetLocationString()); + return; + } + int itemSize = (message.GetItemSize() <2) ? 1 : (message.GetItemSize()-1); + + Auction *auction = new Auction( + message.GetOwnerId(), + message.GetMinimumBid(), + message.GetAuctionTimer(), + message.GetItemId(), + message.GetItemNameLength(), + message.GetItemName(), + message.GetItemType(), + message.GetItemTemplateId(), + message.GetExpireTimer(), + itemSize, + auctionLocation, + message.GetFlags(), + 0, + message.GetUserDescriptionLength(), + message.GetUserDescription(), + 0, + Unicode::emptyString, + message.GetAttributes()); + + AddAuction(auction); + + OnAddAuction(message.GetTrackId(), ARC_Success, + message.GetResponseId(), + message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(), + auctionLocation.GetOwnerId(), + auctionLocation.GetLocationString()); + +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::AddImmediateAuction(const AddImmediateAuctionMessage &message) +{ + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : OwnerName : %s.\n", message.GetOwnerName().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : AuctionTimer : %d.\n", message.GetAuctionTimer())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : GetPrice : %d.\n", message.GetPrice())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemNameLength : %d.\n", message.GetItemNameLength())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemName : %s.\n", Unicode::wideToNarrow(message.GetItemName()).c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemType : %d.\n", message.GetItemType())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemTemplateId : %d.\n", message.GetItemTemplateId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ExpireTimer : %d.\n", message.GetExpireTimer())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : LocationId : %s.\n", message.GetLocationId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Location : %s.\n", message.GetLocation().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Flags : %d.\n", message.GetFlags())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : UserDescriptionLength : %d.\n", message.GetUserDescriptionLength())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : UserDescription : %s.\n", Unicode::wideToNarrow(message.GetUserDescription()).c_str())); +// DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : OobLength : %d.\n", message.GetOobLength())); +// DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : OobActualLength : %d.\n", message.GetOobData().size())); +// DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : OobData : %s.\n", Unicode::wideToNarrow(message.GetOobData()).c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ItemSize : %d.\n", message.GetItemSize())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Limit : %d.\n", message.GetVendorLimit())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Item Limit : %d.\n", message.GetVendorItemLimit())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : TrackId : %d.\n", message.GetTrackId())); + + std::map::iterator exists = m_auctions.find( + message.GetItemId()); + + // force a 30 day stock/restock timer for player vendors. + int auctionTimer = (ConfigCommodityServer::getMinutesVendorAuctionTimer() * 60) + time(0); + // force the expire timer to be 30 days after the auction timer has finished + // The expire timer should be large to allow for time to sit in the stockroom before it is deleted. + int expireTimer = auctionTimer + (ConfigCommodityServer::getMinutesVendorItemTimer() * 60); + + if (message.GetFlags() & AUCTION_VENDOR_TRANSFER) + { + if (exists == m_auctions.end()) + { + OnAddAuction(message.GetTrackId(), ARC_AuctionDoesNotExist, + message.GetResponseId(), + message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(), + zeroNetworkId, + std::string()); + return; + } + Auction *oldAuction = (*exists).second; + if (oldAuction->GetItem().GetOwnerId() != message.GetOwnerId()) + { + OnAddAuction(message.GetTrackId(), ARC_NotItemOwner, + message.GetResponseId(), + message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(), + zeroNetworkId, + std::string()); + return; + } + AuctionLocation &location = oldAuction->GetLocation(); + + // This catches the restock path + if( location.IsVendorMarket() ) + { + // check the player's vendor limit + if (GetVendorCount(message.GetOwnerId()) > message.GetVendorLimit()) + { + OnAddAuction(message.GetTrackId(), + ARC_AuctionVendorLimitExceeded, + message.GetResponseId(), + message.GetItemId(), + message.GetOwnerId(), + message.GetOwnerName(), + zeroNetworkId, + std::string()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetVendorCount(message.GetOwnerId()), message.GetVendorLimit())); + return; + } + if (GetItemCount(message.GetOwnerId()) >= message.GetVendorItemLimit()) + { + OnAddAuction(message.GetTrackId(), + ARC_AuctionVendorItemLimitExceeded, + message.GetResponseId(), + message.GetItemId(), + message.GetOwnerId(), + message.GetOwnerName(), + zeroNetworkId, + std::string()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Item Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetItemCount(message.GetOwnerId()), message.GetVendorItemLimit())); + return; + } + } + // If this is not a player vendor, then use the values sent in from the message + else + { + auctionTimer = message.GetAuctionTimer(); + expireTimer = message.GetExpireTimer(); + } + + // cannot use "relist" on an item bought as a vendor offer; + // must use "sell" and enter a new selling price for the item + if ((oldAuction->GetFlags() & AUCTION_OFFERED_ITEM) && (message.GetPrice() < 0)) + { + OnAddAuction(message.GetTrackId(), + ARC_InvalidBid, + message.GetResponseId(), + message.GetItemId(), + message.GetOwnerId(), + message.GetOwnerName(), + zeroNetworkId, + std::string()); + return; + } + + // make sure price is valid + int const price = ((message.GetPrice() >= 0) ? message.GetPrice() : oldAuction->GetBuyNowPrice()); + if (price < 0) + { + OnAddAuction(message.GetTrackId(), + ARC_InvalidBid, + message.GetResponseId(), + message.GetItemId(), + message.GetOwnerId(), + message.GetOwnerName(), + zeroNetworkId, + std::string()); + return; + } + + Auction *auction = new Auction( + message.GetOwnerId(), + 0, auctionTimer, + message.GetItemId(), + ((message.GetItemNameLength() > 0) ? message.GetItemNameLength() : oldAuction->GetItem().GetNameLength()), + ((message.GetItemNameLength() > 0) ? message.GetItemName() : oldAuction->GetItem().GetName()), + oldAuction->GetItem().GetCategory(), + oldAuction->GetItem().GetItemTemplateId(), + expireTimer, + oldAuction->GetItem().GetSize(), + oldAuction->GetLocation(), + (oldAuction->GetFlags() & (~AUCTION_OFFERED_ITEM)), + price, + ((message.GetPrice() >= 0) ? message.GetUserDescriptionLength() : oldAuction->GetUserDescriptionLength()), + ((message.GetPrice() >= 0) ? message.GetUserDescription() : oldAuction->GetUserDescription()), + oldAuction->GetOobLength(), + oldAuction->GetOobData(), + oldAuction->GetAttributes()); + + LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because auction is about to be relisted.", (*exists).second->GetItem().GetItemId().getValueString().c_str())); + LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because auction is about to be relisted.", (*exists).second->GetItem().GetItemId().getValueString().c_str())); + + DestroyAuction(exists); + + AddAuction(auction); + + OnAddAuction(message.GetTrackId(), ARC_Success, + message.GetResponseId(), + message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(), + location.GetOwnerId(), + location.GetLocationString()); + if (location.IsVendorMarket() && location.IsOwner(message.GetOwnerId())) + { + if (location.GetStatus() != ACTIVE) + { + LOG("CustomerService", ("Vendor: Vendor %s (owner %s) status changed from %s to Active", location.GetLocationId().getValueString().c_str(), location.GetOwnerId().getValueString().c_str(), vendorStatus[location.GetStatus()])); + LOG("CommoditiesServer", ("Vendor %s (owner %s) status changed from %s to Active", location.GetLocationId().getValueString().c_str(), location.GetOwnerId().getValueString().c_str(), vendorStatus[location.GetStatus()])); + } + location.Update(0, m_gameTime, 0, ACTIVE); + } + return; + } + + int itemSize = (message.GetItemSize() <2) ? 1 : (message.GetItemSize()-1); + AuctionLocation &auctionLocation = GetLocation(std::string(message.GetLocation())); + if (exists != m_auctions.end()) + { + static Unicode::String const emptyUnicodeString; + if (message.GetOwnerName() == "Restoring object") + { + DestroyAuction(exists); + Auction *auction = new Auction( + message.GetOwnerId(), + 0, + auctionTimer, + message.GetItemId(), + message.GetItemNameLength(), + message.GetItemName(), + message.GetItemType(), + message.GetItemTemplateId(), + expireTimer, + itemSize, + auctionLocation, + message.GetFlags(), + message.GetPrice(), + message.GetUserDescriptionLength(), + message.GetUserDescription(), + 0, + emptyUnicodeString, + message.GetAttributes()); + AddAuction(auction); + } + OnAddAuction(message.GetTrackId(), ARC_AuctionAlreadyExists, + message.GetResponseId(), + message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(), + auctionLocation.GetOwnerId(), + auctionLocation.GetLocationString()); + return; + } + + if( auctionLocation.IsVendorMarket() && auctionLocation.IsOwner(message.GetOwnerId())) + { + // check the player's vendor limit + if (GetVendorCount(message.GetOwnerId()) > message.GetVendorLimit()) + { + OnAddAuction(message.GetTrackId(), + ARC_AuctionVendorLimitExceeded, + message.GetResponseId(), + message.GetItemId(), + message.GetOwnerId(), + message.GetOwnerName(), + zeroNetworkId, + std::string()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetVendorCount(message.GetOwnerId()), message.GetVendorLimit())); + return; + } + if (GetItemCount(message.GetOwnerId()) >= message.GetVendorItemLimit()) + { + OnAddAuction(message.GetTrackId(), + ARC_AuctionVendorItemLimitExceeded, + message.GetResponseId(), + message.GetItemId(), + message.GetOwnerId(), + message.GetOwnerName(), + zeroNetworkId, + std::string()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddImmediateAuctionMessage] : Vendor Item Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetItemCount(message.GetOwnerId()), message.GetVendorItemLimit())); + return; + } + } + else if (!HasOpenAuctionSlots(message.GetOwnerId())) + { + OnAddAuction(message.GetTrackId(), ARC_TooManyAuctions, + message.GetResponseId(), + message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(), + auctionLocation.GetOwnerId(), + auctionLocation.GetLocationString()); + return; + } + + // If this is not a player vendor, then use the values sent in from the message + if( !auctionLocation.IsVendorMarket() ) + { + auctionTimer = message.GetAuctionTimer(); + expireTimer = message.GetExpireTimer(); + } + + static Unicode::String const emptyUnicodeString; + Auction *auction = new Auction( + message.GetOwnerId(), + 0, auctionTimer, + message.GetItemId(), + message.GetItemNameLength(), + message.GetItemName(), + message.GetItemType(), + message.GetItemTemplateId(), + expireTimer, + itemSize, + auctionLocation, + message.GetFlags(), + message.GetPrice(), + message.GetUserDescriptionLength(), + message.GetUserDescription(), + 0, + emptyUnicodeString, + message.GetAttributes()); + + AddAuction(auction); + + OnAddAuction(message.GetTrackId(), ARC_Success, + message.GetResponseId(), + message.GetItemId(), message.GetOwnerId(), message.GetOwnerName(), + auctionLocation.GetOwnerId(), + auctionLocation.GetLocationString()); + if (auctionLocation.IsVendorMarket() && auctionLocation.IsOwner(message.GetOwnerId())) + { + if (auctionLocation.GetStatus() != ACTIVE) + { + LOG("CustomerService", ("Vendor: Vendor %s (owner %s) status changed from %s to Active", auctionLocation.GetLocationId().getValueString().c_str(), auctionLocation.GetOwnerId().getValueString().c_str(), vendorStatus[auctionLocation.GetStatus()])); + LOG("CommoditiesServer", ("Vendor %s (owner %s) status changed from %s to Active", auctionLocation.GetLocationId().getValueString().c_str(), auctionLocation.GetOwnerId().getValueString().c_str(), vendorStatus[auctionLocation.GetStatus()])); + } + auctionLocation.Update(0, m_gameTime, 0, ACTIVE); + } +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::AddBid(const AddBidMessage &message) +{ + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : GetAuctionId : %s.\n", message.GetAuctionId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : GetPlayerId : %s.\n", message.GetPlayerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : GetBid : %d.\n", message.GetBid())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : GetMaxProxyBid : %d.\n", message.GetMaxProxyBid())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : GetPlayerName : %s.\n", message.GetPlayerName().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AddBidMessage] : TrackId : %d.\n", message.GetTrackId())); + + std::map::iterator iter = m_auctions.find( + message.GetAuctionId()); + if (iter == m_auctions.end()) + { + OnAddBid(message.GetTrackId(), ARC_AuctionDoesNotExist, + message.GetResponseId(), zeroNetworkId, message.GetAuctionId(), + message.GetPlayerId(), zeroNetworkId, message.GetBid(), 0, + message.GetMaxProxyBid(), "PUBLIC_VENDOR", + 0, Unicode::String(), 0, zeroNetworkId); + return; + } + if (!(*iter).second->IsActive()) + { + OnAddBid(message.GetTrackId(), ARC_AuctionDoesNotExist, + message.GetResponseId(), zeroNetworkId, message.GetAuctionId(), + message.GetPlayerId(), zeroNetworkId, message.GetBid(), 0, + message.GetMaxProxyBid(), "PUBLIC_VENDOR", + 0, Unicode::String(), 0, zeroNetworkId); + return; + } + + Auction *auction = (*iter).second; + + // if it's an immediate auction, the bid value must be + // exactly the same as the buy now price + sales tax; + // the client won't let you enter a different bid price + // for an immediate auction, but a player could use a + // hacked client to change the bid price, and we need + // to catch that, and generate a customer service log + // if the bid price is not the same as the buy now + // price + sales tax; note that we could also get here + // legitimately if the sales tax was changed but the + // client had not refreshed the auction to reflect + // the price with the new sales tax + if (auction->IsImmediate() && ((message.GetBid() != auction->GetBuyNowPriceWithSalesTax()) || (message.GetMaxProxyBid() != auction->GetBuyNowPriceWithSalesTax()))) + { + std::string itemName = Unicode::wideToNarrow(auction->GetItem().GetName()); + + LOG("CustomerService", ("Auction: Player %s (%s) sent an invalid bid (bid=%d, max proxy bid=%d) for immediate auction %s (%s) (buy now price=%d, buy now price with sales tax=%d) at location (%s)", + message.GetPlayerName().c_str(), message.GetPlayerId().getValueString().c_str(), + message.GetBid(), message.GetMaxProxyBid(), + auction->GetItem().GetItemId().getValueString().c_str(), itemName.c_str(), + auction->GetBuyNowPrice(), auction->GetBuyNowPriceWithSalesTax(), + auction->GetLocation().GetLocationString().c_str())); + + OnAddBid(message.GetTrackId(), ARC_InvalidBid, + message.GetResponseId(), zeroNetworkId, message.GetAuctionId(), + message.GetPlayerId(), zeroNetworkId, message.GetBid(), 0, + message.GetMaxProxyBid(), "PUBLIC_VENDOR", + 0, Unicode::String(), 0, zeroNetworkId); + + return; + } + + int oldHighBidAmount = auction->GetHighBidAmount(); + + AuctionResultCode result = auction->AddBid( + message.GetPlayerId(), message.GetBid(), message.GetMaxProxyBid()); + + if (result == ARC_SuccessPermanentAuction) + { + //printf("AddBid is PermanentAuction.\n"); + OnPermanentAuctionPurchased( + message.GetTrackId(), + auction->GetCreatorId(), message.GetPlayerId(), + message.GetBid(), message.GetAuctionId(), + auction->GetLocation().GetLocationString(), + auction->GetItem().GetNameLength(), + auction->GetItem().GetName(), + auction->GetAttributes()); + + OnAddBid(message.GetTrackId(), result, + message.GetResponseId(), auction->GetCreatorId(), + message.GetAuctionId(), + message.GetPlayerId(), zeroNetworkId, message.GetBid(), + 0, message.GetMaxProxyBid(), + auction->GetLocation().GetLocationString(), + auction->GetItem().GetNameLength(), auction->GetItem().GetName(), 0, zeroNetworkId); + + return; + } + + const AuctionBid *highBid = auction->GetHighBid(); + + if ((highBid) && + ((result == ARC_Success) || (oldHighBidAmount < highBid->GetBid()))) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new CreateAuctionBidMessage.\n")); + + CMCreateAuctionBidMessage msg( + auction->GetItem().GetItemId(), + highBid->GetBidderId(), + highBid->GetBid(), + highBid->GetMaxProxyBid() + ); + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + } + + const AuctionBid *previousBid = auction->GetPreviousBid(); + NetworkId previousBidder = zeroNetworkId; + int previousBidAmount = 0; + std::string previousBidderName; + int maxProxyBid = message.GetMaxProxyBid(); + int salesTaxAmount = 0; + NetworkId bankId = zeroNetworkId; + + if (previousBid) + { + previousBidder = previousBid->GetBidderId(); + previousBidAmount = previousBid->GetMaxProxyBid(); + //printf("AddBid is Auction.\n"); + } + if (auction->GetBuyNowPrice() != 0) + { + //its an instant auction, set the previous bidder to -1 to signify + previousBidder = negOneNetworkId; + maxProxyBid = auction->GetBuyNowPrice(); + salesTaxAmount = auction->GetBuyNowPriceWithSalesTax() - auction->GetBuyNowPrice(); + bankId = auction->GetLocation().GetSalesTaxBankId(); + //printf("AddBid is Immediate.\n"); + } + + OnAddBid(message.GetTrackId(), result, + message.GetResponseId(), auction->GetCreatorId(), + message.GetAuctionId(), + message.GetPlayerId(), previousBidder, message.GetBid(), + previousBidAmount, maxProxyBid, + auction->GetLocation().GetLocationString(), + auction->GetItem().GetNameLength(), auction->GetItem().GetName(), + salesTaxAmount, bankId); + LOG("CommoditiesServer", ("Player %s put a bid %d on item %s", + message.GetPlayerId().getValueString().c_str(), + message.GetBid(), + message.GetAuctionId().getValueString().c_str())); + LOG("CustomerService", ("Auction: Player %s put a bid %d on item %s", + message.GetPlayerId().getValueString().c_str(), + message.GetBid(), + message.GetAuctionId().getValueString().c_str())); + + AuctionLocation &loc = auction->GetLocation(); + if (loc.IsVendorMarket() && (!loc.IsOwner(message.GetPlayerId()))) + { + if (loc.GetStatus() != ACTIVE) + { + LOG("CustomerService", ("Vendor: Vendor %s (owner %s) status changed from %s to Active", loc.GetLocationId().getValueString().c_str(), loc.GetOwnerId().getValueString().c_str(), vendorStatus[loc.GetStatus()])); + LOG("CommoditiesServer", ("Vendor %s (owner %s) status changed from %s to Active", loc.GetLocationId().getValueString().c_str(), loc.GetOwnerId().getValueString().c_str(), vendorStatus[loc.GetStatus()])); + } + loc.Update(0, m_gameTime, 0, ACTIVE); + } + + // if an item got bought off a vendor, we must send the auction + // complete/expire message to the game server where the item is + // bought, because that game server is where some additional + // processing/validation needs to be done for this transaction; + // we store the game server id in Auction, and in Auction::Update(), + // it will send the auction complete/expire message to the game server + if (loc.IsVendorMarket() && auction->IsImmediate() && auction->IsSold()) + auction->SetTrackId(message.GetTrackId()); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::CancelAuction(const CancelAuctionMessage &message) +{ + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CancelAuctionMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CancelAuctionMessage] : AuctionId : %s.\n", message.GetAuctionId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CancelAuctionMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CancelAuctionMessage] : TrackId : %d.\n", message.GetTrackId())); + + std::map::iterator iter = m_auctions.find(message.GetAuctionId()); + if (iter == m_auctions.end()) + { + OnCancelAuction(message.GetTrackId(), ARC_AuctionDoesNotExist, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId(), zeroNetworkId, 0, "PUBLIC_LOCATION"); + return; + } + + Auction *auction = (*iter).second; + LOG("CommoditiesServer", ("Player %s canceled auction for item %s at location %s", + auction->GetItem().GetOwnerId().getValueString().c_str(), + auction->GetItem().GetItemId().getValueString().c_str(), + auction->GetLocation().GetLocationId().getValueString().c_str())); + LOG("CustomerService", ("Auction: Player %s canceled auction for item %s at location %s", + auction->GetItem().GetOwnerId().getValueString().c_str(), + auction->GetItem().GetItemId().getValueString().c_str(), + auction->GetLocation().GetLocationId().getValueString().c_str())); + + if (auction->GetLocation().IsVendorMarket() && auction->GetLocation().IsOwner(message.GetPlayerId())) + { + if (auction->GetItem().GetOwnerId() == message.GetPlayerId()) + { + if (auction->IsActive()) + { + //The vendor owner is cancelling his own sale + OnCancelAuction(message.GetTrackId(), ARC_Success, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId(), zeroNetworkId, 0, + auction->GetLocation().GetLocationString()); + auction->Expire(false, false, message.GetTrackId()); + if (auction->GetLocation().GetStatus() != ACTIVE) + { + LOG("CustomerService", ("Vendor: Vendor %s (owner %s) status changed from %s to Active", auction->GetLocation().GetLocationId().getValueString().c_str(), auction->GetLocation().GetOwnerId().getValueString().c_str(), vendorStatus[auction->GetLocation().GetStatus()])); + LOG("CommoditiesServer", ("Vendor %s (owner %s) status changed from %s to Active", auction->GetLocation().GetLocationId().getValueString().c_str(), auction->GetLocation().GetOwnerId().getValueString().c_str(), vendorStatus[auction->GetLocation().GetStatus()])); + } + auction->GetLocation().Update(0, m_gameTime, 0, ACTIVE); + } + else + { + OnCancelAuction(message.GetTrackId(), ARC_VendorOwnerCanceledCompletedAuction, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId(), zeroNetworkId, 0, + auction->GetLocation().GetLocationString()); + return; + + } + } + // make sure the sale is still active before deciding it's the owner refusing to buy an offer. + // Fixes a crediting duping exploit where the owner + // of the vendor withdraws a sale after someone buys it. + else if( auction->GetItem().GetOwnerId() != message.GetPlayerId() && !auction->IsActive() ) + { + OnCancelAuction(message.GetTrackId(), ARC_VendorOwnerCanceledCompletedAuction, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId(), zeroNetworkId, 0, + auction->GetLocation().GetLocationString()); + return; + } + // owner of the vendor is refusing an offer to his vendor + else + { + //The vendor owner doesn't want your crap! + OnVendorRefuseItem(message.GetTrackId(), ARC_Success, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId(), auction->GetCreatorId()); + auction->Expire(false, false, message.GetTrackId()); + } + return; + } + else if (message.GetPlayerId() != auction->GetCreatorId()) + { + OnCancelAuction(message.GetTrackId(), ARC_NotItemOwner, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId(), zeroNetworkId, 0, + auction->GetLocation().GetLocationString()); + return; + } + else if ((message.GetPlayerId() == auction->GetCreatorId()) && + !auction->IsActive()) + { + OnCancelAuction(message.GetTrackId(), ARC_AuctionAlreadyCompleted, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId(), zeroNetworkId, 0, + auction->GetLocation().GetLocationString()); + return; + } + + auction->Expire(false, false, message.GetTrackId()); + + const AuctionBid *highBid = auction->GetHighBid(); + NetworkId highBidderId = zeroNetworkId; + int highBidAmount = 0; + if (highBid) + { + highBidderId = highBid->GetBidderId(); + highBidAmount = highBid->GetMaxProxyBid(); + } + + OnCancelAuction(message.GetTrackId(), ARC_Success, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId(), highBidderId, highBidAmount, + auction->GetLocation().GetLocationString()); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::AcceptHighBid(const AcceptHighBidMessage &message) +{ + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AcceptHighBidMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AcceptHighBidMessage] : AuctionId : %s.\n", message.GetAuctionId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AcceptHighBidMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server AcceptHighBidMessage] : TrackId : %d.\n", message.GetTrackId())); + + Auction *auction = NULL; + AuctionResultCode result = ARC_Success; + std::map::iterator iter = m_auctions.find( + message.GetAuctionId()); + if (iter == m_auctions.end()) + { + result = ARC_AuctionDoesNotExist; + } + else + { + auction = (*iter).second; + if (message.GetPlayerId() != auction->GetCreatorId()) + { + result = ARC_NotItemOwner; + } + else if (auction->GetHighBid() == NULL) + { + result = ARC_NoBids; + } + else if (!auction->IsActive()) + { + result = ARC_AuctionAlreadyCompleted; + } + } + + if (result == ARC_Success) + { + auction->Expire(true, false, message.GetTrackId()); + } + + OnAcceptHighBid(message.GetTrackId(), result, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId()); + +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::QueryAuctionHeaders( + const QueryAuctionHeadersMessage &message +) +{ + // Break the text filter string for matching ALL tokens into lower-case tokens + Unicode::UnicodeStringVector textFilterAllTokens; + IGNORE_RETURN(Unicode::tokenize(Unicode::toLower(message.GetTextFilterAll()), textFilterAllTokens)); + + // Break the text filter string for matching ANY tokens into lower-case tokens + Unicode::UnicodeStringVector textFilterAnyTokens; + IGNORE_RETURN(Unicode::tokenize(Unicode::toLower(message.GetTextFilterAny()), textFilterAnyTokens)); + + std::string debugOutput; + +#ifdef _DEBUG + if (m_showAllDebugInfo || message.GetOverrideVendorSearchFlag()) +#else + if (message.GetOverrideVendorSearchFlag()) +#endif + { + debugOutput = "Commodities Server QueryAuctionHeadersMessage:\r\n"; + + char buffer[4096]; + + snprintf(buffer, sizeof(buffer)-1, "ResponseId = (%d)", message.GetResponseId()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "TrackId = (%d)", message.GetTrackId()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "PlayerId = (%s)", message.GetPlayerId().getValueString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "VendorId = (%s)", message.GetVendorId().getValueString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + if (message.GetQueryType() == AST_ByCategory) + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByCategory)", message.GetQueryType()); + } + else if (message.GetQueryType() == AST_ByLocation) + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByLocation)", message.GetQueryType()); + } + else if (message.GetQueryType() == AST_ByAll) + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByAll)", message.GetQueryType()); + } + else if (message.GetQueryType() == AST_ByPlayerSales) + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByPlayerSales)", message.GetQueryType()); + } + else if (message.GetQueryType() == AST_ByPlayerBids) + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByPlayerBids)", message.GetQueryType()); + } + else if (message.GetQueryType() == AST_ByPlayerStockroom) + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByPlayerStockroom)", message.GetQueryType()); + } + else if (message.GetQueryType() == AST_ByVendorOffers) + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByVendorOffers)", message.GetQueryType()); + } + else if (message.GetQueryType() == AST_ByVendorSelling) + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByVendorSelling)", message.GetQueryType()); + } + else if (message.GetQueryType() == AST_ByVendorStockroom) + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByVendorStockroom)", message.GetQueryType()); + } + else if (message.GetQueryType() == AST_ByPlayerOffersToVendor) + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d, AST_ByPlayerOffersToVendor)", message.GetQueryType()); + } + else + { + snprintf(buffer, sizeof(buffer)-1, "QueryType = (%d)", message.GetQueryType()); + } + + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "ItemType = (%d, %s)", message.GetItemType(), GameObjectTypes::getCanonicalName(message.GetItemType()).c_str()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "ItemTypeExactMatch = (%s)", (message.GetItemTypeExactMatch() ? "yes" : "no")); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "ItemTemplate = (%d)", message.GetItemTemplateId()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "TextFilterAll = (%s)", Unicode::wideToNarrow(message.GetTextFilterAll()).c_str()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + for (Unicode::UnicodeStringVector::const_iterator iterTextFilterAllTokens = textFilterAllTokens.begin(); iterTextFilterAllTokens != textFilterAllTokens.end(); ++iterTextFilterAllTokens) + { + snprintf(buffer, sizeof(buffer)-1, "TextFilterAll = (%s)", Unicode::wideToNarrow(*iterTextFilterAllTokens).c_str()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + } + + snprintf(buffer, sizeof(buffer)-1, "TextFilterAny = (%s)", Unicode::wideToNarrow(message.GetTextFilterAny()).c_str()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + for (Unicode::UnicodeStringVector::const_iterator iterTextFilterAnyTokens = textFilterAnyTokens.begin(); iterTextFilterAnyTokens != textFilterAnyTokens.end(); ++iterTextFilterAnyTokens) + { + snprintf(buffer, sizeof(buffer)-1, "TextFilterAny = (%s)", Unicode::wideToNarrow(*iterTextFilterAnyTokens).c_str()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + } + + snprintf(buffer, sizeof(buffer)-1, "MinPrice = (%d)", message.GetPriceFilterMin()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "MaxPrice = (%d)", message.GetPriceFilterMax()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "PriceIncludesEntranceFee = (%s)", (message.GetPriceFilterIncludesFee() ? "yes" : "no")); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "LocationPlanet = (%s)", message.GetSearchStringPlanet().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "LocationRegion = (%s)", message.GetSearchStringRegion().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "LocationAuctionLocationId = (%s)", message.GetSearchAuctionLocationId().getValueString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "SearchMyVendorsOnly = (%s)", (message.GetSearchMyVendorsOnly() ? "yes" : "no")); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "OverrideVendorSearchFlag = (%s)", (message.GetOverrideVendorSearchFlag() ? "yes" : "no")); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + snprintf(buffer, sizeof(buffer)-1, "QueryOffset = (%u)", message.GetQueryOffset()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + if (!message.getAdvancedSearch().empty()) + { + if (message.getAdvancedSearchMatchAllAny() == AuctionQueryHeadersMessage::ASMAA_match_all) + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = ASMAA_match_all"); + } + else if (message.getAdvancedSearchMatchAllAny() == AuctionQueryHeadersMessage::ASMAA_match_any) + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = ASMAA_match_any"); + } + else if (message.getAdvancedSearchMatchAllAny() == AuctionQueryHeadersMessage::ASMAA_not_match_all) + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = ASMAA_not_match_all"); + } + else if (message.getAdvancedSearchMatchAllAny() == AuctionQueryHeadersMessage::ASMAA_not_match_any) + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = ASMAA_not_match_any"); + } + else + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = UNKNOWN (%d)", static_cast(message.getAdvancedSearchMatchAllAny())); + } + + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + std::map const & sa = CommoditiesAdvancedSearchAttribute::getSearchAttributeForGameObjectType(message.GetItemType()); + std::string attributeName; + + for (std::list::const_iterator iter = message.getAdvancedSearch().begin(); iter != message.getAdvancedSearch().end(); ++iter) + { + attributeName.clear(); + if (!sa.empty()) + { + for (std::map::const_iterator iterSa = sa.begin(); iterSa != sa.end(); ++iterSa) + { + if (iterSa->second->attributeNameCrc == iter->attributeNameCrc) + { + attributeName = iterSa->second->attributeName; + break; + } + } + } + + if (iter->comparison == AuctionQueryHeadersMessage::SCC_int) + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_int (%d, %d) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->intMin, iter->intMax, (iter->requiredAttribute ? "yes" : "no")); + } + else if (iter->comparison == AuctionQueryHeadersMessage::SCC_float) + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_float (%.2f, %.2f) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->floatMin, iter->floatMax, (iter->requiredAttribute ? "yes" : "no")); + } + else if (iter->comparison == AuctionQueryHeadersMessage::SCC_string_equal) + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_string_equal (%s) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->stringValue.c_str(), (iter->requiredAttribute ? "yes" : "no")); + } + else if (iter->comparison == AuctionQueryHeadersMessage::SCC_string_not_equal) + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_string_not_equal (%s) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->stringValue.c_str(), (iter->requiredAttribute ? "yes" : "no")); + } + else if (iter->comparison == AuctionQueryHeadersMessage::SCC_string_contain) + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_string_contain (%s) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->stringValue.c_str(), (iter->requiredAttribute ? "yes" : "no")); + } + else if (iter->comparison == AuctionQueryHeadersMessage::SCC_string_not_contain) + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) SCC_string_not_contain (%s) required (%s)", attributeName.c_str(), iter->attributeNameCrc, iter->stringValue.c_str(), (iter->requiredAttribute ? "yes" : "no")); + } + else + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (%s, %lu) UNKNOWN COMPARISON (%d) (%d, %d) (%.2f, %.2f) (%s) required (%s)", attributeName.c_str(), iter->attributeNameCrc, static_cast(iter->comparison), iter->intMin, iter->intMax, iter->floatMin, iter->floatMax, iter->stringValue.c_str(), (iter->requiredAttribute ? "yes" : "no")); + } + + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + } + } + else + { + snprintf(buffer, sizeof(buffer)-1, "AdvancedSearch = (none)"); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + } + } + + // The item template we are looking for + int const itemTemplateId = message.GetItemTemplateId(); + + // The item category we are looking for + int const itemCategory = message.GetItemType(); + bool const itemCategoryMatchExact = (message.GetItemTypeExactMatch() && (itemCategory != 0) && !GameObjectTypes::isSubType(itemCategory) && (itemTemplateId == 0)); + + // the combination of values of itemCategory and + // itemTemplateId indicate what type of a search it is + // + // if itemCategory is 0xffffffff, then it is a search + // for a resource container with a specific name. + // itemTemplateId contains the crc value of the resource name + // + // else if itemCategory is GOT type GOT_resource_container + // and itemTemplateId is != 0, then it is a search + // for a resource container of a particular resource + // class (or derives from the particular resource class). + // itemTemplateId contains the crc value + // of the name of the resource class + // + // else if itemTemplateId is == 0, then it is a + // search for items belonging to the GOT type specified + // by itemCategory + // + // else if itemTemplateId is != 0, then it is a + // search for a specific item type. itemCategory + // specifies the GOT and itemTemplateId is the + // crc value of the object template + + // The min and max price of the items we are looking for + int const priceFilterMin = message.GetPriceFilterMin(); + int const priceFilterMax = message.GetPriceFilterMax(); + + // Advanced "attribute value" search + std::list const & advancedSearch = message.getAdvancedSearch(); + bool const useAdvancedSearch = !advancedSearch.empty(); + + // For the price filter, do we want to include the entrance fee? + bool const priceFilterIncludesFee = message.GetPriceFilterIncludesFee(); + + // Indicates searching for resource containers + bool const searchForResourceContainer = (itemCategory != 0) && ((static_cast(itemCategory) == 0xffffffff) || (AuctionItem::IsCategoryResourceContainer(itemCategory))); + + bool hasMorePages = false; + uint queryOffset = message.GetQueryOffset(); + uint numOffset = 0; + int numAuctions = 0; + std::vector headers; + + bool allowSearchVendors = true; + + if (message.GetQueryType() != AST_ByPlayerOffersToVendor && + message.GetQueryType() != AST_ByVendorSelling && + message.GetQueryType() != AST_ByPlayerStockroom && + message.GetQueryType() != AST_ByVendorOffers && + message.GetQueryType() != AST_ByVendorStockroom) + { + allowSearchVendors = false; + } + + bool checkLocationInfo = false; + static std::map emptyAuctionLocationList; + std::map::iterator locationIter = emptyAuctionLocationList.begin();; + std::map::iterator locationIterEnd = emptyAuctionLocationList.end(); + + // specific vendor is specified + // covers all cases of a non vendor owner accessing a vendor and all cases + // where "this vendor" radio button is selected from the location filter + if (message.GetSearchAuctionLocationId().isValid()) + { + locationIter = m_locationIdMap.find(message.GetSearchAuctionLocationId()); + locationIterEnd = locationIter; + + if (locationIterEnd != m_locationIdMap.end()) + { + ++locationIterEnd; + } + } + // only search vendors owned by the player + // covers all cases of a vendor owner accessing a vendor he owns + else if (message.GetSearchMyVendorsOnly()) + { + checkLocationInfo = true; + std::map >::iterator iterFind = m_playerVendorListMap.find(message.GetPlayerId()); + if (iterFind != m_playerVendorListMap.end()) + { + locationIter = iterFind->second.begin(); + locationIterEnd = iterFind->second.end(); + } + } + // the rest of the cases just need to cover the various cases of browsing the bazaar + // bazaar "all auctions" + else if (message.GetQueryType() == AST_ByAll) + { + if (message.GetSearchStringPlanet().empty()) + { + locationIter = m_allBazaar.begin(); + locationIterEnd = m_allBazaar.end(); + } + else if (message.GetSearchStringRegion().empty()) + { + std::map >::iterator iterFind = m_bazaarByPlanet.find(message.GetSearchStringPlanet()); + if (iterFind != m_bazaarByPlanet.end()) + { + locationIter = iterFind->second.begin(); + locationIterEnd = iterFind->second.end(); + } + } + else + { + std::map, std::map >::iterator iterFind = m_bazaarByRegion.find(std::make_pair(message.GetSearchStringPlanet(), message.GetSearchStringRegion())); + if (iterFind != m_bazaarByRegion.end()) + { + locationIter = iterFind->second.begin(); + locationIterEnd = iterFind->second.end(); + } + } + } + // bazaar "my bids" and "my sales" + else if ((message.GetQueryType() == AST_ByPlayerBids) || (message.GetQueryType() == AST_ByPlayerSales)) + { + locationIter = m_allBazaar.begin(); + locationIterEnd = m_allBazaar.end(); + } + // bazaar "available items" + else if (message.GetQueryType() == AST_ByPlayerStockroom) + { + locationIter = m_locationIdMap.begin(); + locationIterEnd = m_locationIdMap.end(); + } + // bazaar "vendor location" + else if (message.GetQueryType() == AST_ByVendorSelling) + { + if (message.GetOverrideVendorSearchFlag()) + { + checkLocationInfo = true; + locationIter = m_locationIdMap.begin(); + locationIterEnd = m_locationIdMap.end(); + } + else if (message.GetSearchStringPlanet().empty()) + { + locationIter = m_allSearchableVendor.begin(); + locationIterEnd = m_allSearchableVendor.end(); + } + else if (message.GetSearchStringRegion().empty()) + { + std::map >::iterator iterFind = m_searchableVendorByPlanet.find(message.GetSearchStringPlanet()); + if (iterFind != m_searchableVendorByPlanet.end()) + { + locationIter = iterFind->second.begin(); + locationIterEnd = iterFind->second.end(); + } + } + else + { + std::map, std::map >::iterator iterFind = m_searchableVendorByRegion.find(std::make_pair(message.GetSearchStringPlanet(), message.GetSearchStringRegion())); + if (iterFind != m_searchableVendorByRegion.end()) + { + locationIter = iterFind->second.begin(); + locationIterEnd = iterFind->second.end(); + } + } + } + + int debugNumberLocationsTested = 0; + int debugNumberLocationsMatched = 0; + int debugNumberAuctionsTested = 0; + + std::map *auctionsPtr = NULL; + int entranceCharge = 0; + AuctionLocation *locationPtr = NULL; + Auction *auctionPtr = NULL; + std::map::const_iterator auctionIterator; + AuctionDataHeader *header = NULL; + bool checkItemTemplate; + while (locationIter != locationIterEnd) + { + ++debugNumberLocationsTested; + + checkItemTemplate = false; + auctionsPtr = NULL; + entranceCharge = 0; + locationPtr = (*locationIter).second; + + if (locationPtr->MatchLocation(message.GetSearchStringPlanet(), message.GetSearchStringRegion(), message.GetSearchAuctionLocationId(), checkLocationInfo, message.GetSearchMyVendorsOnly(), message.GetOverrideVendorSearchFlag(), message.GetPlayerId(), allowSearchVendors, message.GetVendorId(), message.GetQueryType())) + { + ++debugNumberLocationsMatched; + + entranceCharge = locationPtr->GetEntranceCharge(); + + if (message.GetQueryType() == AST_ByVendorOffers || + message.GetQueryType() == AST_ByPlayerOffersToVendor || + message.GetQueryType() == AST_ByVendorStockroom || + (message.GetQueryType() == AST_ByPlayerStockroom && + locationPtr->IsVendorMarket())) + { + // we are using a list of all items, so we will need to check + // to see if the player specified a template and/or item type, + // and if so, ignore any items that doesn't match the template + // and/or item type + // + // in all other cases, we use the template and/or item type + // that the player specified, and only look at the item list + // of that particular template and/or item type, so we know that + // every item in that list matches the specified template and/or + // item type + checkItemTemplate = true; + + auctionsPtr = &(locationPtr->GetVendorOffers()); + } + else + { + if (searchForResourceContainer) + { + auctionsPtr = &(locationPtr->GetAuctionsResourceContainer()); + } + else if (itemCategory != 0) + { + if (itemTemplateId == 0) + { + if (itemCategoryMatchExact) + { + auctionsPtr = &(locationPtr->GetAuctionsByParentTypeExactMatch(itemCategory)); + } + else + { + auctionsPtr = &(locationPtr->GetAuctionsByType(itemCategory)); + } + } + else + { + auctionsPtr = &(locationPtr->GetAuctionsByTemplate(itemCategory, itemTemplateId)); + } + } + else + { + auctionsPtr = &(locationPtr->GetAuctions()); + } + } + } + + if (auctionsPtr) + { + for (auctionIterator = auctionsPtr->begin(); auctionIterator != auctionsPtr->end(); ++auctionIterator) + { + ++debugNumberAuctionsTested; + + auctionPtr = (*auctionIterator).second; + const AuctionItem &item = auctionPtr->GetItem(); + header = NULL; + + // Check to see if the item template matches + if (searchForResourceContainer && (itemTemplateId != 0)) + { + if (checkItemTemplate && !AuctionItem::IsCategoryResourceContainer(item.GetCategory())) + { + continue; + } + + if (static_cast(itemCategory) == 0xffffffff) + { + if (item.GetResourceNameCrc() != itemTemplateId) + { + continue; + } + } + else if (!IsResourceClassDerivedFrom(item.GetResourceContainerClassCrc(), itemTemplateId)) + { + continue; + } + } + else if (checkItemTemplate && (itemCategory != 0)) + { + if (itemCategoryMatchExact) + { + if (itemCategory != item.GetCategory()) + { + continue; + } + } + else if (!GameObjectTypes::isTypeOf(item.GetCategory(), itemCategory)) + { + continue; + } + + if ((itemTemplateId != 0) && (itemTemplateId != item.GetItemTemplateId())) + { + continue; + } + } + + // Check to see if the text matches + if (!((textFilterAllTokens.empty() && textFilterAnyTokens.empty()) || + IsTextFilterMatch(item.GetName(), textFilterAllTokens, textFilterAnyTokens))) + { + continue; + } + + // Check to see if the price matches + if (!(((priceFilterMin == 0) && (priceFilterMax == 0)) || + IsPriceFilterMatch(auctionPtr, entranceCharge, priceFilterMin, priceFilterMax, priceFilterIncludesFee))) + { + continue; + } + + // Check to see if the advanced search matches + if (!(!useAdvancedSearch || auctionPtr->IsAdvancedFilterMatch(advancedSearch, static_cast(message.getAdvancedSearchMatchAllAny())))) + { + continue; + } + + switch(message.GetQueryType()) + { + case AST_ByLocation: + case AST_ByAll: + case AST_ByVendorOffers: + case AST_ByVendorSelling: + if (auctionPtr->IsActive()) + { + if (numOffset >= queryOffset) + { + header = MakeDataHeader( + message.GetPlayerId(), auctionPtr, + static_cast(message.GetQueryType()), entranceCharge); + } + else + { + ++numOffset; + } + } + break; + + case AST_ByPlayerSales: + if (auctionPtr->IsActive() && + auctionPtr->GetCreatorId() == message.GetPlayerId()) + { + if (numOffset >= queryOffset) + { + header = MakeDataHeader( + message.GetPlayerId(), auctionPtr, + static_cast(message.GetQueryType()), entranceCharge); + } + else + { + ++numOffset; + } + } + break; + + case AST_ByPlayerStockroom: + case AST_ByVendorStockroom: + if (!auctionPtr->IsActive() && + auctionPtr->GetItem().GetOwnerId() == message.GetPlayerId()) + { + if (numOffset >= queryOffset) + { + header = MakeDataHeader( + message.GetPlayerId(), auctionPtr, + static_cast(message.GetQueryType()), entranceCharge); + } + else + { + ++numOffset; + } + } + break; + + case AST_ByPlayerOffersToVendor: + if (auctionPtr->IsActive() && + auctionPtr->GetCreatorId() == message.GetPlayerId()) + { + if (numOffset >= queryOffset) + { + header = MakeDataHeader( + message.GetPlayerId(), auctionPtr, + static_cast(message.GetQueryType()), entranceCharge); + } + else + { + ++numOffset; + } + } + break; + + case AST_ByPlayerBids: + { + if (!auctionPtr->IsActive()) + { + break; + } + const AuctionBid *bid = auctionPtr->GetPlayerBid( + message.GetPlayerId()); + if (bid) + { + if (numOffset >= queryOffset) + { + header = MakeDataHeader( + message.GetPlayerId(), auctionPtr, + static_cast(message.GetQueryType()), entranceCharge, + bid); + } + else + { + ++numOffset; + } + } + break; + } + + case AST_ByCategory: + if (auctionPtr->IsActive()) + { + if (numOffset >= queryOffset) + { + header = MakeDataHeader( + message.GetPlayerId(), auctionPtr, + static_cast(message.GetQueryType()), entranceCharge); + } + else + { + ++numOffset; + } + } + break; + } + + if (header) + { + headers.push_back(*header); + delete header; + + ++numAuctions; + if (numAuctions >= ConfigCommodityServer::getMaxAuctionsPerPage()) + { + hasMorePages = true; + break; + } + } + } + } + + // If we found enough auctions, stop looking + if (numAuctions >= ConfigCommodityServer::getMaxAuctionsPerPage()) + { + break; + } + + ++locationIter; + } + +#ifdef _DEBUG + if (m_showAllDebugInfo || message.GetOverrideVendorSearchFlag()) +#else + if (message.GetOverrideVendorSearchFlag()) +#endif + { + char buffer[4096]; + + snprintf(buffer, sizeof(buffer)-1, "(%d / %d / %d) locations tested, (%d / %d) auctions tested", debugNumberLocationsMatched, debugNumberLocationsTested, m_locationIdMap.size(), debugNumberAuctionsTested, m_auctions.size()); + buffer[sizeof(buffer)-1] = '\0'; + debugOutput += buffer; + debugOutput += "\r\n"; +#ifdef _DEBUG + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryAuctionHeadersMessage] : %s\n", buffer)); +#endif + + if (message.GetOverrideVendorSearchFlag()) + { + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(message.GetTrackId()); + if (gameServerConn) + { + GenericValueTypeMessage > const msg("DisplayStringForPlayer", std::make_pair(message.GetPlayerId(), debugOutput)); + gameServerConn->send(msg, true); + } + } + } + + OnQueryAuctionHeaders(message.GetTrackId(), ARC_Success, + message.GetResponseId(), message.GetPlayerId(), + message.GetQueryType(), headers, queryOffset, hasMorePages); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::SetGameTime(const SetGameTimeMessage &message) +{ + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetGameTimeMessage] : GameTime : %d.\n", message.GetGameTime())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetGameTimeMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetGameTimeMessage] : TrackId : %d.\n", message.GetTrackId())); + + m_gameTime = message.GetGameTime(); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::GetItemDetails(const GetItemDetailsMessage &message) +{ + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemDetailsMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemDetailsMessage] : AuctionId : %s.\n", message.GetAuctionId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemDetailsMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemDetailsMessage] : TrackId : %d.\n", message.GetTrackId())); + + std::map::iterator iter = m_auctions.find( + message.GetAuctionId()); + if (iter == m_auctions.end()) + { + static const std::vector > emptyAttributes; + OnGetItemDetails(message.GetTrackId(), ARC_AuctionDoesNotExist, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId(), 0, Unicode::emptyString, 0, Unicode::emptyString, emptyAttributes); + return; + } + + Auction *auction = (*iter).second; + OnGetItemDetails(message.GetTrackId(), ARC_Success, + message.GetResponseId(), message.GetAuctionId(), + message.GetPlayerId(), + auction->GetUserDescriptionLength(), auction->GetUserDescription(), + auction->GetOobLength(), auction->GetOobData(), + auction->GetAttributes()); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::GetItem(const GetItemMessage &message) +{ + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemMessage] : Location : %s.\n", message.GetLocation().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetItemMessage] : TrackId : %d.\n", message.GetTrackId())); + + AuctionLocation &location = GetLocation(std::string(message.GetLocation())); + Auction *auction = location.GetAuction(message.GetItemId()); + if (!auction) + { + OnGetItem(message.GetTrackId(), ARC_AuctionDoesNotExist, + message.GetResponseId(), message.GetItemId(), + message.GetPlayerId(), message.GetLocation()); + return; + } + if (auction->GetItem().GetOwnerId() != message.GetPlayerId()) + { + OnGetItem(message.GetTrackId(), ARC_NotItemOwner, + message.GetResponseId(), message.GetItemId(), + message.GetPlayerId(), message.GetLocation()); + return; + } + + LOG("CommoditiesServer", ("Player %s retrived item %s at location %s", + auction->GetItem().GetOwnerId().getValueString().c_str(), + auction->GetItem().GetItemId().getValueString().c_str(), + auction->GetLocation().GetLocationId().getValueString().c_str())); + LOG("CustomerService", ("Auction: Player %s retrived item %s at location %s", + auction->GetItem().GetOwnerId().getValueString().c_str(), + auction->GetItem().GetItemId().getValueString().c_str(), + auction->GetLocation().GetLocationId().getValueString().c_str())); + std::map::iterator i = m_auctions.find(auction->GetItem().GetItemId()); + if (i != m_auctions.end()) + { + LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because item is being retrieved.", (*i).second->GetItem().GetItemId().getValueString().c_str())); + LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because item is being retrieved.", (*i).second->GetItem().GetItemId().getValueString().c_str())); + DestroyAuction(i); + } + + OnGetItem(message.GetTrackId(), ARC_Success, + message.GetResponseId(), message.GetItemId(), + message.GetPlayerId(), message.GetLocation()); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::CleanupInvalidItemRetrieval( const CleanupInvalidItemRetrievalMessage &message) +{ + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CleanupInvalidItemRetrievalMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CleanupInvalidItemRetrievalMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CleanupInvalidItemRetrievalMessage] : TrackId : %d.\n", message.GetTrackId())); + + //printf( "Received command to cleanup an invalid item.\n"); + std::map::iterator itemIterator = m_auctions.find( message.GetItemId()); + if( itemIterator != m_auctions.end() ) + { + LOG("CommoditiesServer", ("CleanupInvalidItemRetrieval for item %s.", + message.GetItemId().getValueString().c_str())); + LOG("CustomerService", ("Auction: CleanupInvalidItemRetrieval for item %s.", + message.GetItemId().getValueString().c_str())); + int reimburseAmt = 0; + Auction *item = (*itemIterator).second; + if( item->GetCreatorId() != item->GetItem().GetOwnerId() ) + { + //printf("Player needs reimbursed for item = %d.\n", item->GetItem().GetItemId() ); + + // figure out the price. + // For instant sales, the buy now price + if( item->IsImmediate() ) + { + reimburseAmt = item->GetBuyNowPriceWithSalesTax(); + //printf( "Reimbursing player %d credits for invalid instant auction.\n", reimburseAmt ); + } + else + { + reimburseAmt = item->GetHighBid()->GetBid(); + //printf( "Reimbursing player %d credits for invalid bid auction.\n", reimburseAmt ); + } + // For bid items, the highest bid + } + OnCleanupInvalidItemRetrieval(message.GetTrackId(), message.GetResponseId(), item->GetItem().GetItemId(), item->GetItem().GetOwnerId(), item->GetCreatorId(), reimburseAmt); + LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because of cleanup of invalied item retieval.", (*itemIterator).second->GetItem().GetItemId().getValueString().c_str())); + LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because of cleanup of invalied item retieval.", (*itemIterator).second->GetItem().GetItemId().getValueString().c_str())); + + //printf( "Deleting auction item = %d\n", item->GetItem().GetItemId() ); + DestroyAuction(itemIterator); + } +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::DestroyVendorMarket(const DestroyVendorMarketMessage &message) +{ + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DestroyVendorMarketMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DestroyVendorMarketMessage] : OwnerName : %s.\n", message.GetOwnerName().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DestroyVendorMarketMessage] : Location : %s.\n", message.GetLocation().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DestroyVendorMarketMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DestroyVendorMarketMessage] : TrackId : %d.\n", message.GetTrackId())); + + std::map::iterator i = m_locationIdMap.find(GetLocationId(message.GetLocation())); + if( i != m_locationIdMap.end() ) + { + LOG("CommoditiesServer", ("Remove location %s owned by %s (%s) from Commodities Server", + GetLocationId(message.GetLocation()).getValueString().c_str(), + message.GetOwnerName().c_str(), + message.GetOwnerId().getValueString().c_str())); + LOG("CustomerService", ("Vendor: Remove location %s owned by %s (%s) from Commodities Server", + GetLocationId(message.GetLocation()).getValueString().c_str(), + message.GetOwnerName().c_str(), + message.GetOwnerId().getValueString().c_str())); + std::vector::iterator> destroyedAuctions; + std::map::iterator item; + // get all the auctions for this location and get an iterator from the real auctions map + for( std::map::iterator j = (*i).second->GetAuctions().begin(); j != (*i).second->GetAuctions().end(); j++ ) + { + item = m_auctions.find((*j).first); + if( item != m_auctions.end() ) + { + destroyedAuctions.push_back(item); + } + } + + // do it again for all vendor offers + for( std::map::iterator k = (*i).second->GetVendorOffers().begin(); k != (*i).second->GetVendorOffers().end(); k++ ) + { + item = m_auctions.find((*k).first); + if( item != m_auctions.end() ) + { + destroyedAuctions.push_back(item); + } + } + + + // destroy the auctions + std::vector::iterator>::iterator ri = destroyedAuctions.begin(); + std::map::iterator auctionsIterator; + while (ri != destroyedAuctions.end()) + { + auctionsIterator = *ri; + //(*auctionsIterator).second->Expire(false, false); + LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because vendor is being destroyed by the owner.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str())); + LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because vendor is being destroyed by the owner.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str())); + DestroyAuction(auctionsIterator); + ++ri; + } + + // get rid of the location from m_locationMap + AuctionLocation *al = (*i).second; + if (al->GetOwnerId() != zeroNetworkId) + { + RemovePlayerVendor(al->GetOwnerId(), al->GetLocationId()); + } + m_locationIdMap.erase(i); + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new DeleteLocationMessage.\n")); + + CMDeleteLocationMessage msg(al->GetLocationId()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Id : %s.\n", msg.GetLocationId().getValueString().c_str())); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + + delete al; + } +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::DeleteAuctionLocation(const DeleteAuctionLocationMessage &message) +{ + std::string replyMessage; + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server DeleteAuctionLocationMessage] : LocationId : %s.\n", message.GetLocationId().getValueString().c_str())); + + std::map::iterator i = m_locationIdMap.find(message.GetLocationId()); + if( i != m_locationIdMap.end() ) + { + LOG("CommoditiesServer", ("Remove location %s owned by %s from Commodities Server", + message.GetLocationId().getValueString().c_str(), + (*i).second->GetOwnerId().getValueString().c_str())); + + LOG("CustomerService", ("Vendor: Remove location %s owned by %s from Commodities Server", + message.GetLocationId().getValueString().c_str(), + (*i).second->GetOwnerId().getValueString().c_str())); + std::vector::iterator> destroyedAuctions; + std::map::iterator item; + // get all the auctions for this location and get an iterator from the real auctions map + for( std::map::iterator j = (*i).second->GetAuctions().begin(); j != (*i).second->GetAuctions().end(); j++ ) + { + item = m_auctions.find((*j).first); + if( item != m_auctions.end() ) + { + destroyedAuctions.push_back(item); + } + } + + // do it again for all vendor offers + for( std::map::iterator k = (*i).second->GetVendorOffers().begin(); k != (*i).second->GetVendorOffers().end(); k++ ) + { + item = m_auctions.find((*k).first); + if( item != m_auctions.end() ) + { + destroyedAuctions.push_back(item); + } + } + + + // destroy the auctions + std::vector::iterator>::iterator ri = destroyedAuctions.begin(); + std::map::iterator auctionsIterator; + while (ri != destroyedAuctions.end()) + { + auctionsIterator = *ri; + //(*auctionsIterator).second->Expire(false, false); + LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because auction location is being deleted from DeleteAuctionLocationMessage request.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str())); + LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because auction location is being deleted from DeleteAuctionLocationMessage request.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str())); + DestroyAuction(auctionsIterator); + ++ri; + } + + // get rid of the location from m_locationMap + AuctionLocation *al = (*i).second; + if (al->GetOwnerId() != zeroNetworkId) + { + RemovePlayerVendor(al->GetOwnerId(), al->GetLocationId()); + } + m_locationIdMap.erase(i); + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new DeleteLocationMessage.\n")); + + replyMessage = std::string("Location ") + message.GetLocationId().getValueString().c_str() + " owned by " + al->GetOwnerId().getValueString().c_str() + " is deleted."; + CMDeleteLocationMessage msg(al->GetLocationId()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Id : %s.\n", msg.GetLocationId().getValueString().c_str())); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + + delete al; + } + else + replyMessage = std::string("Location ") + message.GetLocationId().getValueString().c_str() + " does not exist."; + + GenericValueTypeMessage > + reply("OnCommodityReplyMessage", + std::make_pair(message.GetWhoRequested(), replyMessage)); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(message.GetTrackId()); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnCommodityReplyMessage callback to GamerServer ID: %d.\n", message.GetTrackId())); + gameServerConn->send(reply, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAddAuctionMessage.\n", message.GetTrackId())); + } + +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::UpdateVendorStatus(const UpdateVendorStatusMessage &message) +{ + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : VendorId : %s.\n", message.GetVendorId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : Location : %s.\n", message.GetLocation().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : Status : 0x%0X.\n", message.GetStatus())); + + std::map::const_iterator i = m_locationIdMap.find(GetLocationId(message.GetLocation())); + + if (i != m_locationIdMap.end()) + { + (*i).second->SetLocationString(message.GetLocation()); + (*i).second->SetFullStatus(message.GetStatus(), true); + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : LocationId : %s.\n", (*i).second->GetLocationId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : Full Status : 0x%0X.\n", (*i).second->GetFullStatus())); + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateLocationMessage.\n")); + CMUpdateLocationMessage msg( + (*i).second->GetLocationId(), + (*i).second->GetOwnerId(), + (*i).second->GetLocationString(), + (*i).second->GetSalesTax(), + (*i).second->GetSalesTaxBankId(), + (*i).second->GetEmptyDate(), + (*i).second->GetLastAccessDate(), + (*i).second->GetInactiveDate(), + (*i).second->GetFullStatus(), + (*i).second->GetSearchEnabled(), + (*i).second->GetEntranceCharge() + ); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + } + else + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorStatus] : Update failed - Vendor not found!\n")); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::UpdateVendorLocation(const NetworkId &locationId, const std::string &locationString) +{ + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorLocation] : VendorId : %s.\n", locationId.getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorLocation] : Location : %s.\n", locationString.c_str())); + + std::map::const_iterator i = m_locationIdMap.find(locationId); + + if (i != m_locationIdMap.end()) + { + if ((*i).second->GetLocationString() != locationString) + { + LOG("CustomerService", ("Vendor: Fixing up vendor %s (owner %s) location from (%s) to (%s)", (*i).second->GetLocationId().getValueString().c_str(), (*i).second->GetOwnerId().getValueString().c_str(), (*i).second->GetLocationString().c_str(), locationString.c_str())); + + (*i).second->SetLocationString(locationString); + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateLocationMessage.\n")); + CMUpdateLocationMessage msg( + (*i).second->GetLocationId(), + (*i).second->GetOwnerId(), + (*i).second->GetLocationString(), + (*i).second->GetSalesTax(), + (*i).second->GetSalesTaxBankId(), + (*i).second->GetEmptyDate(), + (*i).second->GetLastAccessDate(), + (*i).second->GetInactiveDate(), + (*i).second->GetFullStatus(), + (*i).second->GetSearchEnabled(), + (*i).second->GetEntranceCharge() + ); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + } + } + else + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorLocation] : Update failed - Vendor not found!\n")); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::CreateVendorMarket(const CreateVendorMarketMessage &message) +{ + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Location : %s.\n", message.GetLocation().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Vendor Limit : %d.\n", message.GetVendorLimit())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Entrance Charge : %d.\n", message.GetEntranceCharge())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : TrackId : %d.\n", message.GetTrackId())); + + std::map::const_iterator i = + m_locationIdMap.find(GetLocationId(message.GetLocation())); + if (i != m_locationIdMap.end()) + { + // check the current owner and location string - update if needed + if (((*i).second->GetOwnerId() != message.GetOwnerId()) || ((*i).second->GetLocationString() != message.GetLocation())) + { + // check the player's vendor limit + if (GetVendorCount(message.GetOwnerId()) >= message.GetVendorLimit()) + { + OnCreateVendorMarket(message.GetTrackId(), + ARC_LocationVendorLimitExceeded, + message.GetResponseId(), + message.GetOwnerId(), + message.GetLocation()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Vendor Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetVendorCount(message.GetOwnerId()), message.GetVendorLimit())); + return; + } + + RemovePlayerVendor((*i).second->GetOwnerId(), (*i).second->GetLocationId()); + AddPlayerVendor(message.GetOwnerId(), (*i).second->GetLocationId(), (*i).second); + (*i).second->SetOwnerId(message.GetOwnerId()); + (*i).second->SetLocationString(message.GetLocation()); + (*i).second->SetEntranceCharge(message.GetEntranceCharge()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateLocationMessage.\n")); + CMUpdateLocationMessage msg( + (*i).second->GetLocationId(), + (*i).second->GetOwnerId(), + (*i).second->GetLocationString(), + (*i).second->GetSalesTax(), + (*i).second->GetSalesTaxBankId(), + (*i).second->GetEmptyDate(), + (*i).second->GetLastAccessDate(), + (*i).second->GetInactiveDate(), + (*i).second->GetFullStatus(), + (*i).second->GetSearchEnabled(), + (*i).second->GetEntranceCharge() + ); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Id : %s.\n", msg.GetLocationId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location OwnerId : %s.\n", msg.GetOwnerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Name : %s.\n", msg.GetLocationString().c_str())); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + } + // This should only be for the reinitialize case + else if (GetVendorCount(message.GetOwnerId()) > message.GetVendorLimit()) + { + OnCreateVendorMarket(message.GetTrackId(), + ARC_LocationVendorLimitExceeded, + message.GetResponseId(), + message.GetOwnerId(), + message.GetLocation()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Vendor Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetVendorCount(message.GetOwnerId()), message.GetVendorLimit())); + return; + } + + OnCreateVendorMarket(message.GetTrackId(), + ARC_LocationAlreadyExists, + message.GetResponseId(), + message.GetOwnerId(), + message.GetLocation()); + return; + } + + // check the player's vendor limit + if (GetVendorCount(message.GetOwnerId()) >= message.GetVendorLimit()) + { + OnCreateVendorMarket(message.GetTrackId(), + ARC_LocationVendorLimitExceeded, + message.GetResponseId(), + message.GetOwnerId(), + message.GetLocation()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server CreateVendorMarketMessage] : Vendor Limit Exceeded for Player %s. (Current: %d, Limit: %d)\n", message.GetOwnerId().getValueString().c_str(), GetVendorCount(message.GetOwnerId()), message.GetVendorLimit())); + return; + } + + CreateLocation(message.GetOwnerId(), message.GetLocation(), message.GetEntranceCharge()); + + OnCreateVendorMarket(message.GetTrackId(), + ARC_Success, + message.GetResponseId(), + message.GetOwnerId(), + message.GetLocation()); +} + +// ---------------------------------------------------------------------- + +// returns the containerId as a string given a location string +bool AuctionMarket::GetContainerIdString( const std::string &loc, std::string &output ) +{ + // format of location string is as follows: + // planetname.regionname.vendorname.containerId#xLoc,zLoc + const std::string delims1("."); + const std::string delims2("#"); + bool retval = false; + + std::string::size_type begIdx, endIdx; + + begIdx = loc.find_first_not_of(delims1); + // skip over first 3 '.'s + for( int i=0; i<3; i++ ) + { + begIdx = loc.find_first_of(delims1, begIdx); + if( begIdx != std::string::npos ) + { + begIdx = loc.find_first_not_of(delims1, begIdx); + } + } + + if( begIdx != std::string::npos ) + { + endIdx = loc.find_first_of(delims2, begIdx); + if( endIdx != std::string::npos ) + { + output = loc.substr(begIdx, endIdx-begIdx); + retval = true; + } + } + + return retval; +} + +// ---------------------------------------------------------------------- + +// returns the locationId as a number given a location string +NetworkId AuctionMarket::GetLocationId(const std::string &loc) +{ + // format of location string is as follows: + // planetname.regionname.vendorname.containerId#xLoc,zLoc + const std::string delims1("."); + const std::string delims2("#"); + std::string output; + bool found = false; + + std::string::size_type begIdx, endIdx; + + begIdx = loc.find_first_not_of(delims1); + // skip over first 3 '.'s + for( int i=0; i<3; i++ ) + { + begIdx = loc.find_first_of(delims1, begIdx); + if( begIdx != std::string::npos ) + { + begIdx = loc.find_first_not_of(delims1, begIdx); + } + } + + if( begIdx != std::string::npos ) + { + endIdx = loc.find_first_of(delims2, begIdx); + if( endIdx != std::string::npos ) + { + output = loc.substr(begIdx, endIdx-begIdx); + found = true; + } + } + + if (found) + { + NetworkId retval(output); + return retval; + } + else + { + NetworkId retval(int64(0)); + return retval; + } +} + +// ---------------------------------------------------------------------- + +// This function checks to see if the embedded containerId matches with any existing +// vendor location string. If it does, it updates the location string for that match +// +// returns true if it fixed something, false otherwise +bool AuctionMarket::FixVendorLocation( const std::string &loc ) +{ + std::map::iterator i = m_locationIdMap.begin(); + + std::string containerIdString; + if( !GetContainerIdString(loc, containerIdString) ) + { + return false; + } + + while( i != m_locationIdMap.end() ) + { + AuctionLocation *al = (*i).second; + if( al ) + { + std::string oldStrLoc(al->GetLocationString()); + //printf( "Old strloc: %s\n", oldStrLoc); + std::string checkId; + //printf( "checking %s with %s\n", checkId, containerIdString); + + if( GetContainerIdString( oldStrLoc, checkId ) && checkId == containerIdString ) + { + // update the location string + al->SetLocationString( loc ); + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateLocationMessage.\n")); + CMUpdateLocationMessage msg( + al->GetLocationId(), + al->GetOwnerId(), + loc, + al->GetSalesTax(), + al->GetSalesTaxBankId(), + al->GetEmptyDate(), + al->GetLastAccessDate(), + al->GetInactiveDate(), + al->GetFullStatus(), + al->GetSearchEnabled(), + al->GetEntranceCharge() + ); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Id : %s.\n", msg.GetLocationId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Name : %s.\n", msg.GetLocationString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Sales Tax : %d.\n", msg.GetSalesTax())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Bank Id : %s.\n", msg.GetBankId().getValueString().c_str())); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + + return true; + } + } + + i++; + } + + return false; +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::GetVendorOwner(const GetVendorOwnerMessage &message) +{ + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorOwnerMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorOwnerMessage] : Location : %s.\n", message.GetLocation().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorOwnerMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorOwnerMessage] : TrackId : %d.\n", message.GetTrackId())); + + std::map::const_iterator i = + m_locationIdMap.find(GetLocationId(message.GetLocation())); + if (i == m_locationIdMap.end()) + { + // if the region name changes, we lose track of an existing vendor + // this function will fix up those vendors. + if( FixVendorLocation(message.GetLocation()) ) + { + // try again now... + i = m_locationIdMap.find(GetLocationId(message.GetLocation())); + if( i == m_locationIdMap.end() ) + { + // still couldn't find the vendor + OnGetVendorOwner(message.GetTrackId(), ARC_LocationAlreadyExists, + message.GetResponseId(), zeroNetworkId, + message.GetOwnerId(), message.GetLocation()); + return; + } + } + else + { // couldn't find the vendor + OnGetVendorOwner(message.GetTrackId(), ARC_LocationAlreadyExists, + message.GetResponseId(), zeroNetworkId, + message.GetOwnerId(), message.GetLocation()); + return; + } + } + AuctionLocation *auctionLocation = (*i).second; + + OnGetVendorOwner(message.GetTrackId(), ARC_LocationAlreadyExists, + message.GetResponseId(), auctionLocation->GetOwnerId(), + message.GetOwnerId(), message.GetLocation()); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::GetVendorValue(const GetVendorValueMessage &message) +{ + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorValueMessage] : Location : %s.\n", message.GetLocation().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorValueMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetVendorValueMessage] : TrackId : %d.\n", message.GetTrackId())); + + std::map::const_iterator i = + m_locationIdMap.find(GetLocationId(message.GetLocation())); + if (i == m_locationIdMap.end()) + { + OnGetVendorValue(message.GetTrackId(), message.GetResponseId(), + message.GetLocation(), 0); + return; + } + AuctionLocation *auctionLocation = (*i).second; + + OnGetVendorValue(message.GetTrackId(), message.GetResponseId(), + message.GetLocation(), auctionLocation->GetValue()); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::SetSalesTax(const SetSalesTaxMessage &message) +{ + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetSalesTaxMessage] : GetBankId : %s.\n", message.GetBankId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetSalesTaxMessage] : GetSalesTax : %d.\n", message.GetSalesTax())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetSalesTaxMessage] : Location : %s.\n", message.GetLocation().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetSalesTaxMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetSalesTaxMessage] : TrackId : %d.\n", message.GetTrackId())); + + // printf("Received SetSalesTax request: sales tax=%ld, bankId=%Ld, location='%s'\n", message.GetSalesTax(), message.GetBankId().getValue(), message.GetLocation() ); + + AuctionLocation &al = GetLocation(message.GetLocation()); + // make sure we got a real location + if( al.GetLocationString() == message.GetLocation() ) + { + if ((al.GetSalesTax() != message.GetSalesTax()) || (al.GetSalesTaxBankId() != message.GetBankId())) + { + al.SetSalesTax(message.GetSalesTax(), message.GetBankId()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateLocationMessage.\n")); + CMUpdateLocationMessage msg( + al.GetLocationId(), + al.GetOwnerId(), + al.GetLocationString(), + al.GetSalesTax(), + al.GetSalesTaxBankId(), + al.GetEmptyDate(), + al.GetLastAccessDate(), + al.GetInactiveDate(), + al.GetFullStatus(), + al.GetSearchEnabled(), + al.GetEntranceCharge() + ); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Id : %s.\n", msg.GetLocationId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Name : %s.\n", msg.GetLocationString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Sales Tax : %d.\n", msg.GetSalesTax())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Location Bank Id : %s.\n", msg.GetBankId().getValueString().c_str())); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + } + } +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::QueryVendorItemCount(const QueryVendorItemCountMessage &message) +{ + AuctionLocation &loc = GetLocation(message.GetVendorId()); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryVendorItemCountMessage] : TrackId : %d\n", message.GetTrackId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryVendorItemCountMessage] : VendorId : %s\n", message.GetVendorId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server QueryVendorItemCountMessage] : ItemCount : %d\n", loc.GetAuctionItemCount())); + + OnQueryVendorItemCount(message.GetResponseId(), message.GetTrackId(), message.GetVendorId(), loc.GetAuctionItemCount(), loc.GetSearchEnabled()); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::GetPlayerVendorCount(const GetPlayerVendorCountMessage &message) +{ + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetPlayerVendorCountMessage] : TrackId : %d\n", message.GetTrackId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetPlayerVendorCountMessage] : VendorId : %s\n", message.GetPlayerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server GetPlayerVendorCountMessage] : ItemCount : %d\n", GetVendorCount(message.GetPlayerId()))); + + std::vector vendorList; + std::map >::const_iterator const iterPlayer = m_playerVendorListMap.find(message.GetPlayerId()); + if (iterPlayer != m_playerVendorListMap.end()) + { + for (std::map::const_iterator iterAuctionLocation = iterPlayer->second.begin(); iterAuctionLocation != iterPlayer->second.end(); ++iterAuctionLocation) + { + vendorList.push_back(iterAuctionLocation->first); + } + } + + OnGetPlayerVendorCount(message.GetResponseId(), message.GetTrackId(), message.GetPlayerId(), vendorList.size(), vendorList); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::UpdateVendorSearchOption(const UpdateVendorSearchOptionMessage &message) +{ + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorSearchOptionMessage] : TrackId : %d\n", message.GetTrackId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorSearchOptionMessage] : VendorId : %s\n", message.GetVendorId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server UpdateVendorSearchOptionMessage] : Enabled : %d\n", message.GetEnabled())); + + AuctionLocation &loc = GetLocation(message.GetVendorId()); + loc.SetSearchedEnabled(message.GetEnabled()); + CMUpdateLocationMessage msg( + loc.GetLocationId(), + loc.GetOwnerId(), + loc.GetLocationString(), + loc.GetSalesTax(), + loc.GetSalesTaxBankId(), + loc.GetEmptyDate(), + loc.GetLastAccessDate(), + loc.GetInactiveDate(), + loc.GetFullStatus(), + message.GetEnabled(), + loc.GetEntranceCharge() + ); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + + OnUpdateVendorSearchOptionMessage reply(message.GetPlayerId(), message.GetEnabled()); + + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(message.GetTrackId()); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnUpdateVendorSearchOptionMessage callback to GamerServer ID: %d\n", message.GetTrackId())); + gameServerConn->send(reply, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAddAuctionMessage.\n", message.GetTrackId())); + } +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::SetEntranceCharge(const SetEntranceChargeMessage &message) +{ + + bool tempv = m_showAllDebugInfo; + m_showAllDebugInfo = true; + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetEntranceChargeMessage] : TrackId : %d\n", message.GetTrackId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetEntranceChargeMessage] : VendorId : %s\n", message.GetVendorId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server SetEntranceChargeMessage] : EntranceCharge : %d\n", message.GetEntranceCharge())); + m_showAllDebugInfo = tempv; + + AuctionLocation &loc = GetLocation(message.GetVendorId()); + loc.SetEntranceCharge(message.GetEntranceCharge()); + CMUpdateLocationMessage msg( + loc.GetLocationId(), + loc.GetOwnerId(), + loc.GetLocationString(), + loc.GetSalesTax(), + loc.GetSalesTaxBankId(), + loc.GetEmptyDate(), + loc.GetLastAccessDate(), + loc.GetInactiveDate(), + loc.GetFullStatus(), + loc.GetSearchEnabled(), + loc.GetEntranceCharge() + ); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); + +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::DeleteCharacter(const DeleteCharacterMessage &message) +{ + std::map::iterator auctionsIterator = m_auctions.begin(); + std::vector::iterator> auctionsToDelete; + + while (auctionsIterator != m_auctions.end()) + { + if ((*auctionsIterator).second->GetItem().GetOwnerId() == message.getCharacterId()) + auctionsToDelete.push_back(auctionsIterator); + ++auctionsIterator; + } + + std::vector::iterator>::iterator iter = auctionsToDelete.begin(); + while (iter != auctionsToDelete.end()) + { + auctionsIterator = (*iter); + LOG("CommoditiesServer", ("Auction: Auction for item %s being deleted by the Commodities Server because character %s is deleted.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str(), message.getCharacterId().getValueString().c_str())); + LOG("CustomerService", ("Auction: Auction for item %s being deleted by the Commodities Server because character %s is deleted.", (*auctionsIterator).second->GetItem().GetItemId().getValueString().c_str(), message.getCharacterId().getValueString().c_str())); + DestroyAuction(auctionsIterator); + ++iter; + } + +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::SendItemTypeMap(GameServerConnection &gameServerConnection) +{ + GenericValueTypeMessage > > > msg("CommoditiesItemTypeMap", std::make_pair(m_itemTypeMapVersionNumber, m_itemTypeMap)); + gameServerConnection.send(msg, true); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::AddResourceType(int resourceClassCrc, const std::string & resourceName) +{ + std::set & resourceNameList = m_resourceTypeMap[resourceClassCrc]; + if (resourceNameList.count(resourceName) == 0) + { + ++m_resourceTypeMapVersionNumber; + IGNORE_RETURN(resourceNameList.insert(resourceName)); + + GenericValueTypeMessage > > msg("CommoditiesResourceTypeAdded", std::make_pair(m_resourceTypeMapVersionNumber, std::make_pair(resourceClassCrc, resourceName))); + CommodityServer::getInstance().sendToAllGameServers(msg); + } +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::SendResourceTypeMap(GameServerConnection &gameServerConnection) +{ + GenericValueTypeMessage > > > msg("CommoditiesResourceTypeMap", std::make_pair(m_resourceTypeMapVersionNumber, m_resourceTypeMap)); + gameServerConnection.send(msg, true); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::RemoveFromAuctionTimerPriorityQueue(int timer, const NetworkId & item) +{ + m_priorityQueueAuctionTimer.erase(std::make_pair(timer, item)); +} + +// ---------------------------------------------------------------------- + +void AuctionMarket::AddAuctionToCompletedAuctionsList(const Auction & auction) +{ + m_completedAuctions.push_back(auction.GetItem().GetItemId()); +} + +// ====================================================================== +// +// AuctionMarket Message Callback Handlers +// +// ====================================================================== + +void AuctionMarket::OnAddAuction( + int trackId, + int result, + int responseId, + const NetworkId & itemId, + const NetworkId & ownerId, + const std::string & ownerName, + const NetworkId & vendorId, + const std::string & location +) +{ + OnAddAuctionMessage message(responseId, result, itemId, ownerId, ownerName, vendorId, location); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnAddAuctionMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAddAuctionMessage.\n", trackId)); + } + + +} + +void AuctionMarket::OnAddBid( + int trackId, + int result, + int responseId, + const NetworkId & ownerId, + const NetworkId & itemId, + const NetworkId & bidderId, + const NetworkId & previousBidderId, + int bidAmount, + int previousBidAmount, + int maxProxyBid, + const std::string & location, + int itemNameLength, + const Unicode::String & itemName, + int salesTaxAmount, + const NetworkId & salesTaxBankId +) +{ + OnAddBidMessage message(responseId, result, itemId, ownerId, bidderId, previousBidderId, bidAmount, previousBidAmount, maxProxyBid, location, itemNameLength, itemName, salesTaxAmount, salesTaxBankId); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnAddBidMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAddBidMessage.\n", trackId)); + } + +} + +void AuctionMarket::OnCancelAuction( + int trackId, + int result, + int responseId, + const NetworkId & itemId, + const NetworkId & playerId, + const NetworkId & highBidderId, + int highBid, + const std::string & location +) +{ + OnCancelAuctionMessage message(responseId, result, itemId, playerId, highBidderId, highBid, location); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnCancelAuctionMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnCancelAuctionMessage.\n", trackId)); + } + +} + +void AuctionMarket::OnAcceptHighBid( + int trackId, + int result, + int responseId, + const NetworkId & itemId, + const NetworkId & playerId +) +{ + OnAcceptHighBidMessage message(responseId, result, itemId, playerId); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnAcceptHighBidMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAcceptHighBidMessage.\n", trackId)); + } + + +} + +void AuctionMarket::OnQueryAuctionHeaders( + int trackId, + int result, + int responseId, + const NetworkId & playerId, + int queryType, + std::vector & auctions, + unsigned int queryOffset, + bool hasMorePages +) +{ + OnQueryAuctionHeadersMessage message(responseId, result, playerId, queryType, auctions, queryOffset, hasMorePages); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnQueryAuctionHeadersMessage callback to GamerServer ID: %d.\n\n", trackId)); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : QueryType : %d.\n", message.GetQueryType())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : NumAuctions : %d.\n", message.GetNumAuctions())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : GetResultCode : %d.\n", message.GetResultCode())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : QueryOffset : %u.\n", message.GetQueryOffset())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : HasMorePages : %d.\n", message.HasMorePages())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : TrackId : %d.\n", message.GetTrackId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnQueryAuctionHeadersMessage] : Auctions : %d.\n", message.GetAuctionData().size())); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnQueryAuctionHeadersMessage.\n", trackId)); + } + +} + +void AuctionMarket::OnGetItemDetails( + int trackId, + int result, + int responseId, + const NetworkId & itemId, + const NetworkId & playerId, + int userDescriptionLength, + const Unicode::String & userDescription, + int oobDataLength, + const Unicode::String & oobData, + std::vector > const & attributes +) +{ + OnGetItemDetailsMessage message(responseId, result, itemId, playerId, userDescriptionLength, userDescription, oobDataLength, oobData, attributes); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnGetItemDetailsMessage callback to GamerServer ID: %d.\n", trackId)); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : Result : %d.\n", message.GetResultCode())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : PlayerId : %s.\n", message.GetPlayerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : UserDescriptionLength : %d.\n", message.GetUserDescriptionLength())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : UserDescription : %s.\n", Unicode::wideToNarrow(message.GetUserDescription()).c_str())); +// DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : OobLength : %d.\n", message.GetOobLength())); +// DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : OobActualLength : %d.\n", message.GetOobData().size())); +// DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : OobData : ")); +// if (m_showAllDebugInfo) +// { +// Unicode::String temp = message.GetOobData(); +// Unicode::String::iterator i = temp.begin(); +// while (i != temp.end()) +// { printf(" %X", (*i)); +// ++i; +// } +// printf("\n"); +// } + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnGetItemDetailsMessage] : TrackId : %d.\n", message.GetTrackId())); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnGetItemDetailsMessage.\n", trackId)); + } + + +} + +void AuctionMarket::OnAuctionExpired( + const NetworkId & ownerId, + bool sold, const int flags, + const NetworkId & buyerId, + int highBidAmount, + const NetworkId & itemId, + int highBidMaxProxy, + const std::string & location, + bool immediate, + int itemNameLength, + const Unicode::String & itemName, + const NetworkId & itemOwnerId, + int track_id, + bool sendSellerMail +) +{ + + OnAuctionExpiredMessage message(ownerId, sold, buyerId, highBidAmount, itemId, highBidMaxProxy, location, immediate, itemNameLength, itemName, sendSellerMail); + message.SetTrackId(track_id); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(track_id); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnAuctionExpiredMessage callback to GamerServer ID: %d.\n\n", track_id)); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : BuyerId : %s.\n", message.GetBuyerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : Bid : %d.\n", message.GetBid())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : MaxProxyBid : %d.\n", message.GetMaxProxyBid())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : Location : %s.\n", message.GetLocation().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : IsSold : %d.\n", message.IsSold())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : IsImmediate : %d.\n", message.IsImmediate())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : ItemName : %s.\n", Unicode::wideToNarrow(message.GetItemName()).c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnAuctionExpiredMessage] : TrackId : %d.\n", message.GetTrackId())); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnAuctionExpiredMessage.\n", track_id)); + } + + if (sold) + { + AuctionLocation &auctionLocation = GetLocation(location); + if (!auctionLocation.IsOwner(ownerId)) + { + ModifyAuctionCount(ownerId, -1); + } + if (!auctionLocation.IsOwner(buyerId)) + { + ModifyAuctionCount(buyerId, 1); + } + const_cast(ownerId) = buyerId; + } + + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Creating new UpdateAuctionMessage.\n")); + CMUpdateAuctionMessage msg( + itemId, + itemOwnerId, + (flags & (~3)) + ); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Id : %s.\n", msg.GetItemId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Item Owner : %s.\n", msg.GetOwnerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("Auction Flags : %d.\n", msg.GetFlags())); + + DatabaseServerConnection* dbServer = CommodityServer::getInstance().getDatabaseServer(); + if (dbServer) + dbServer->send(msg, true); +} + +void AuctionMarket::OnItemExpired( + const NetworkId & ownerId, + const NetworkId & itemId, + int itemNameLength, + const Unicode::String & itemName, + const std::string & locationName, + const NetworkId & locationId +) +{ + OnItemExpiredMessage message(ownerId, itemId, itemNameLength, itemName, locationName, locationId); + message.SetTrackId(-1); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(-1); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnItemExpiredMessage callback to GamerServer ID: %d.\n\n", -1)); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnItemExpiredMessage] : ItemId : %s.\n", message.GetItemId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnItemExpiredMessage] : OwnerId : %s.\n", message.GetOwnerId().getValueString().c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnItemExpiredMessage] : ItemName : %s.\n", Unicode::wideToNarrow(message.GetItemName()).c_str())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnItemExpiredMessage] : ResponseId : %d.\n", message.GetResponseId())); + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server OnItemExpiredMessage] : TrackId : %d.\n", message.GetTrackId())); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnItemExpiredMessage.\n", -1)); + } + + +} + +void AuctionMarket::OnGetItem( + int trackId, + int result, + int responseId, + const NetworkId & itemId, + const NetworkId & playerId, + const std::string & location +) +{ + OnGetItemMessage message(responseId, result, itemId, playerId, location); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnGetItemMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnGetItemMessage.\n", trackId)); + } + + +} + +void AuctionMarket::OnCreateVendorMarket( + int trackId, + int result, + int responseId, + const NetworkId & ownerId, + const std::string & location +) +{ + OnCreateVendorMarketMessage message(responseId, result, ownerId, location); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnCreateVendorMarketMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnCreateVendorMarketMessage.\n", trackId)); + } + + +} + +void AuctionMarket::OnVendorRefuseItem( + int trackId, + int result, + int responseId, + const NetworkId & itemId, + const NetworkId & playerId, + const NetworkId & creatorId +) +{ + OnVendorRefuseItemMessage message(responseId, result, itemId, playerId, creatorId); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnVendorRefuseItemMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnVendorRefuseItemMessage.\n", trackId)); + } + +} + +void AuctionMarket::OnGetVendorOwner( + int trackId, + int result, + int responseId, + const NetworkId & ownerId, + const NetworkId & requesterId, + const std::string & location +) +{ + OnGetVendorOwnerMessage message(responseId, result, ownerId, requesterId, location); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnGetVendorOwnerMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnGetVendorOwnerMessage.\n", trackId)); + } +} + +void AuctionMarket::OnPermanentAuctionPurchased( + int trackId, + const NetworkId & ownerId, + const NetworkId & buyerId, + int price, + const NetworkId & itemId, + const std::string & location, + int itemNameLength, + const Unicode::String & itemName, + std::vector > const & attributes + ) +{ + OnPermanentAuctionPurchasedMessage message(ownerId, buyerId, price, itemId, location, itemNameLength, itemName, attributes); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnPermanentAuctionPurchasedMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnPermanentAuctionPurchasedMessage.\n", trackId)); + } + +} + +void AuctionMarket::OnGetVendorValue( + int trackId, + int responseId, + const std::string & location, + int value) +{ + OnGetVendorValueMessage message(responseId, location, value); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnGetVendorValueMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnGetVendorValueMessage.\n", trackId)); + } + +} + +void AuctionMarket::OnCleanupInvalidItemRetrieval( + int trackId, + int responseId, + const NetworkId & itemId, + const NetworkId & playerId, + const NetworkId & creatorId, + int reimburseAmt) +{ + OnCleanupInvalidItemRetrievalMessage message(responseId, itemId, playerId, creatorId, reimburseAmt); + message.SetTrackId(trackId); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnCleanupInvalidItemRetrievalMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnCleanupInvalidItemRetrievalMessage.\n", trackId)); + } + +} + +void AuctionMarket::OnQueryVendorItemCount ( + const int responseId, + const int trackId, + const NetworkId &vendorId, + const int itemCount, + const bool searchEnabled) +{ + OnQueryVendorItemCountReplyMessage message(responseId, vendorId, itemCount, searchEnabled); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnQueryVendorItemCountMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnQueryVendorItemCountMessage.\n", trackId)); + } +} + +void AuctionMarket::OnGetPlayerVendorCount ( + const int responseId, + const int trackId, + const NetworkId &playerId, + const int vendorCount, + std::vector vendorList) +{ + OnGetPlayerVendorCountMessage message(responseId, playerId, vendorCount, vendorList); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending OnGetPlayerVendorCountMessage callback to GamerServer ID: %d.\n", trackId)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send OnGetPlayerVendorCountMessage.\n", trackId)); + } +} + +void AuctionMarket::OnVendorStatusChange ( + int trackId, + const NetworkId &vendorId, + int newStatus) +{ + if (newStatus == ARC_VendorRemoved) + { + RemovePlayerVendor(GetLocation(vendorId).GetOwnerId(), vendorId); + } + VendorStatusChangeMessage message(vendorId, newStatus); + GameServerConnection* gameServerConn; + gameServerConn = CommodityServer::getInstance().getGameServer(trackId); + if (gameServerConn) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Sending VendorStatusChangeMessage callback to GamerServer ID: %d, vendorId = %s, newStatus = %d.\n", trackId, vendorId.getValueString().c_str(), newStatus)); + gameServerConn->send(message, true); + } + else + { + WARNING(true, ("[Commodities Server] : No Gameserver connection at ID: %d to send VendorStatusChangeMessage.\n", trackId)); + } +} + +void static decodeOOB(const std::string & UTF8String, Unicode::String & UniString) +{ + + std::string::iterator c = const_cast (UTF8String.begin()); + std::string tempstring; + unsigned short unicharvalue; + char * pEnd; + + while (c != UTF8String.end()) + { + tempstring.push_back(*c); + if (tempstring.length() == 4) + { + unicharvalue = static_cast(strtoul(tempstring.c_str(), &pEnd, 16)); + if (pEnd) + { + // WARNING(true, ("[Commodities Server ] : Conversion of string hex values to unsigned short failed in: TaskGetAuctionList::decodeOOB.\n")); + } + UniString.push_back(unicharvalue); + tempstring.clear(); + } + c++; + } + if (tempstring.length() != 0) + { + WARNING(true, ("[Commodities Server ] : Unconverted OOB data in - TaskGetAuctionList::decodeOOB.\n")); + } +} + +void AuctionMarket::onReceiveAuctionLocations (const NetworkId &locationId, const std::string &locationName, const NetworkId &ownerId, const int salesTax, const NetworkId &salesTaxBankId, const int emptyDate, const int lastAccessDate, const int inactiveDate, const int status, const bool searchEnabled, const int entranceCharge) +{ + + AuctionLocation *auctionLocation = new AuctionLocation(locationId, locationName, ownerId, salesTax, salesTaxBankId, emptyDate, lastAccessDate, inactiveDate, status, searchEnabled, entranceCharge); + + m_locationIdMap.insert(std::make_pair(auctionLocation->GetLocationId(), auctionLocation)); + if ((ownerId != zeroNetworkId) && (auctionLocation->GetStatus() < REMOVED)) + { + AddPlayerVendor(ownerId, locationId, auctionLocation); + } +} + +void AuctionMarket::onReceiveMarketAuctions (const NetworkId &itemId, const NetworkId &ownerId, const NetworkId &creatorId, const NetworkId &locationId, const int minBid, const int buyNowPrice, const int auctionTimer, const std::string &oob, const Unicode::String &userDescription, const int category, const int itemTemplateId, const Unicode::String &itemName, const int itemTimer, const int active, const int itemSize) +{ + AuctionLocation &location = GetLocation(locationId); + + Unicode::String oobData; + decodeOOB(oob, oobData); + + std::vector > attributes; + + Auction *auction = new Auction( + creatorId, + minBid, + auctionTimer, + itemId, + itemName.size(), + itemName, + category, + itemTemplateId, + itemTimer, + itemSize, + location, + active, + buyNowPrice, + userDescription.size(), + userDescription, + oobData.size(), + oobData, + attributes, + (active & 1), + (active & 2)); + + auction->GetItem().SetOwnerId(ownerId); + + if ((auction->GetItem().GetItemTemplateId() != 0) && (auction->GetItem().GetCategory() != 0)) + { + std::set & itemTypeList = m_itemTypeMap[auction->GetItem().GetCategory()]; + if (itemTypeList.count(auction->GetItem().GetItemTemplateId()) == 0) + { + ++m_itemTypeMapVersionNumber; + IGNORE_RETURN(itemTypeList.insert(auction->GetItem().GetItemTemplateId())); + } + } + + m_auctions.insert(std::make_pair(auction->GetItem().GetItemId(), auction)); + + std::string const & gameObjectType = GameObjectTypes::getCanonicalName(auction->GetItem().GetCategory()); + std::map::iterator iterAuctionsCountByGameObjectType = m_auctionsCountByGameObjectType.find(gameObjectType); + if (iterAuctionsCountByGameObjectType != m_auctionsCountByGameObjectType.end()) + { + ++iterAuctionsCountByGameObjectType->second; + m_auctionsCountByGameObjectTypeChanged.insert(gameObjectType); + + if (GameObjectTypes::isSubType(auction->GetItem().GetCategory())) + { + std::string const & gameParentObjectType = GameObjectTypes::getCanonicalName(GameObjectTypes::getMaskedType(auction->GetItem().GetCategory())); + std::map::iterator iterAuctionsCountByParentGameObjectType = m_auctionsCountByGameObjectType.find(gameParentObjectType); + if (iterAuctionsCountByParentGameObjectType != m_auctionsCountByGameObjectType.end()) + { + ++iterAuctionsCountByParentGameObjectType->second; + m_auctionsCountByGameObjectTypeChanged.insert(gameParentObjectType); + } + } + } + + if (!location.IsOwner(auction->GetItem().GetOwnerId())) + { + ModifyAuctionCount(auction->GetItem().GetOwnerId(), 1); + } + + location.AddAuction(auction); + AddAuctionToPriorityQueue(*auction); + + if (auction->IsActive() && auction->IsSold()) + AddAuctionToCompletedAuctionsList(*auction); +} + +void AuctionMarket::onReceiveMarketAuctionAttributes(const NetworkId &itemId, const std::string &attributeName, const Unicode::String &attributeValue) +{ + std::map::iterator iter = m_auctions.find(itemId); + + if (iter != m_auctions.end()) + { + Auction *auction = (*iter).second; + + auction->AddAttributes(attributeName, attributeValue); + } + else + { + WARNING(true,("[Commodities Server] : There are orphaned auction attributes records for item %s.", itemId.getValueString().c_str())); + } +} + +void AuctionMarket::onReceiveMarketAuctionBids (const NetworkId &itemId, const NetworkId &bidderId, const int bid, const int maxProxyBid) +{ + std::map::iterator iter = m_auctions.find(itemId); + + if (iter != m_auctions.end()) + { + Auction *auction = (*iter).second; + + auction->AddLoadedBid(bidderId, bid, maxProxyBid); + } + else + { + WARNING(true,("[Commodities Server] : There are orphaned bid records for item %s.", itemId.getValueString().c_str())); + } +} + +void AuctionMarket::printAuctionTables() +{ + + DEBUG_REPORT_LOG(true, (" Print AUCTION_LOCATIONS data:\n")); + std::map::iterator auctionLocationIterator = + m_locationIdMap.begin(); + while (auctionLocationIterator != m_locationIdMap.end()) + { + DEBUG_REPORT_LOG(true, (" LocId = %s, LocName = %s\n OwnerId = %s, SalesTax = %d, SalesTaxBankId = %s, EntranceCharge = %d\n", auctionLocationIterator->second->GetLocationId().getValueString().c_str(), auctionLocationIterator->second->GetLocationString().c_str(), auctionLocationIterator->second->GetOwnerId().getValueString().c_str(), auctionLocationIterator->second->GetSalesTax(), auctionLocationIterator->second->GetSalesTaxBankId().getValueString().c_str(), auctionLocationIterator->second->GetEntranceCharge())); + ++auctionLocationIterator; + } + + DEBUG_REPORT_LOG(true, (" Print MARKET_AUCTIONS data:\n")); + std::map::iterator marketAuctionsIterator = m_auctions.begin(); + while (marketAuctionsIterator != m_auctions.end()) + { + Auction *auction = marketAuctionsIterator->second; + UNREF(auction); + DEBUG_REPORT_LOG(true, (" ItemId = %s, OwnerId = %s, CreatorId = %s, LocId = %s\n MinBid = %d, BuyNowPrice = %d, AuctionTimer = %d, Category = %d\n", + auction->GetItem().GetItemId().getValueString().c_str(), + auction->GetItem().GetOwnerId().getValueString().c_str(), + auction->GetCreatorId().getValueString().c_str(), + auction->GetLocation().GetLocationId().getValueString().c_str(), + auction->GetMinBid(), + auction->GetBuyNowPrice(), + auction->GetAuctionTimer(), + auction->GetFlags())); + ++marketAuctionsIterator; + } +} + +void AuctionMarket::VerifyExcludedGotTypes(std::map const & excludedGotTypes) +{ + std::set processedGotTypes; + + int itemCategory, itemGeneralCategory; + std::map::const_iterator iterFind; + std::map::const_iterator marketAuctionsIterator = m_auctions.begin(); + while (marketAuctionsIterator != m_auctions.end()) + { + AuctionItem const & auctionItem = marketAuctionsIterator->second->GetItem(); + itemCategory = auctionItem.GetCategory(); + if (processedGotTypes.count(itemCategory) == 0) + { + IGNORE_RETURN(processedGotTypes.insert(itemCategory)); + + iterFind = excludedGotTypes.find(itemCategory); + if (iterFind != excludedGotTypes.end()) + { + LOG("CustomerService", ("CommoditiesMissingCategory:Item %s (%s) is in excluded category %d (%s)", + auctionItem.GetItemId().getValueString().c_str(), + Unicode::wideToNarrow(auctionItem.GetName()).c_str(), + iterFind->first, + iterFind->second.c_str())); + } + + itemGeneralCategory = itemCategory & 0xffffff00; + if (itemCategory != itemGeneralCategory) + { + // general category + iterFind = excludedGotTypes.find(itemGeneralCategory); + if (iterFind != excludedGotTypes.end()) + { + LOG("CustomerService", ("CommoditiesMissingCategory:Item %s (%s) is in excluded general category %d (%s)", + auctionItem.GetItemId().getValueString().c_str(), + Unicode::wideToNarrow(auctionItem.GetName()).c_str(), + iterFind->first, + iterFind->second.c_str())); + } + } + } + + ++marketAuctionsIterator; + } +} + +void AuctionMarket::VerifyExcludedResourceClasses(std::set const & excludedResourceClasses) +{ + int excludedClassCrc; + for (std::set::const_iterator iterExcluded = excludedResourceClasses.begin(); iterExcluded != excludedResourceClasses.end(); ++iterExcluded) + { + excludedClassCrc = static_cast(Crc::calculate(iterExcluded->c_str())); + + for (std::map::iterator locationIter = m_locationIdMap.begin(); locationIter != m_locationIdMap.end(); ++locationIter) + { + std::map const & auctionsResourceContainer = locationIter->second->GetAuctionsResourceContainer(); + for (std::map::const_iterator auctionIter = auctionsResourceContainer.begin(); auctionIter != auctionsResourceContainer.end(); ++auctionIter) + { + AuctionItem const & auctionItem = auctionIter->second->GetItem(); + if (IsResourceClassDerivedFrom(auctionItem.GetResourceContainerClassCrc(), excludedClassCrc)) + { + LOG("CustomerService", ("CommoditiesMissingResourceClass:Item %s (%s) is in excluded resource class (%s)", + auctionItem.GetItemId().getValueString().c_str(), + Unicode::wideToNarrow(auctionItem.GetName()).c_str(), + iterExcluded->c_str())); + } + } + } + } +} + +bool AuctionMarket::IsResourceClassDerivedFrom(int resourceClassCrc, int parentResourceClassCrc) +{ + if (resourceClassCrc == parentResourceClassCrc) + return true; + + std::map >::const_iterator iter = m_resourceTreeHierarchy.find(resourceClassCrc); + if (iter == m_resourceTreeHierarchy.end()) + return false; + + return (iter->second.count(parentResourceClassCrc) > 0); +} + +void AuctionMarket::SetResourceTreeHierarchy(std::map > const & resourceTreeHierarchy) +{ + m_resourceTreeHierarchy = resourceTreeHierarchy; +} + +void AuctionMarket::getItemAttributeData(int requestingGameServerId, const NetworkId & requester, const std::string & outputFileName, int gameObjectType, bool exactGameObjectTypeMatch, bool ignoreSearchableAttribute, int throttle) const +{ + if (getItemAttributeDataRequest) + { + if (getItemAttributeDataRequest->requester != requester) + { + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + char buffer[2048]; + snprintf(buffer, sizeof(buffer)-1, "There is already a pending %s request by (%s).", getItemAttributeDataRequest->action.c_str(), getItemAttributeDataRequest->requester.getValueString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + + GenericValueTypeMessage, std::string> > const msg("GetItemAttributeDataRsp", std::make_pair(std::make_pair(requester, std::string("(~!@#$%^&*)system_mesage(*&^%$#@!~)")), std::string(buffer))); + gameServerConn->send(msg, true); + } + } + else if (getItemAttributeDataRequest->action != "GetItemAttributeData") + { + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + char buffer[2048]; + snprintf(buffer, sizeof(buffer)-1, "There is already a pending %s request by (%s).", getItemAttributeDataRequest->action.c_str(), getItemAttributeDataRequest->requester.getValueString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + + GenericValueTypeMessage, std::string> > const msg("GetItemAttributeDataRsp", std::make_pair(std::make_pair(requester, std::string("(~!@#$%^&*)system_mesage(*&^%$#@!~)")), std::string(buffer))); + gameServerConn->send(msg, true); + } + } + else + { + getItemAttributeDataRequest->requestingGameServerId = requestingGameServerId; + getItemAttributeDataRequest->throttleNumberItemsPerFrame = throttle; + + getItemAttributeDataRequest->outputFileName = outputFileName; + + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + char buffer[2048]; + snprintf(buffer, sizeof(buffer)-1, "%s request modified. outputFileName=(%s), gameObjectType=(%d, %s), exactGameObjectTypeMatch=(%s), ignoreSearchableAttribute=(%s), throttle=(%d), numberItemsProcessed=(%d), totalNumberOfItems=(%d).", + getItemAttributeDataRequest->action.c_str(), + getItemAttributeDataRequest->outputFileName.c_str(), + getItemAttributeDataRequest->gameObjectType, + GameObjectTypes::getCanonicalName(getItemAttributeDataRequest->gameObjectType).c_str(), + (getItemAttributeDataRequest->exactGameObjectTypeMatch ? "yes" : "no" ), + (getItemAttributeDataRequest->ignoreSearchableAttribute ? "yes" : "no"), + getItemAttributeDataRequest->throttleNumberItemsPerFrame, + getItemAttributeDataRequest->numberItemsProcessed, + m_auctions.size()); + + buffer[sizeof(buffer)-1] = '\0'; + + GenericValueTypeMessage, std::string> > const msg("GetItemAttributeDataRsp", std::make_pair(std::make_pair(requester, std::string("(~!@#$%^&*)system_mesage(*&^%$#@!~)")), std::string(buffer))); + gameServerConn->send(msg, true); + } + } + } + else + { + getItemAttributeDataRequest = new GetItemAttributeDataRequest(); + getItemAttributeDataRequest->action = "GetItemAttributeData"; + getItemAttributeDataRequest->requestingGameServerId = requestingGameServerId; + getItemAttributeDataRequest->requester = requester; + getItemAttributeDataRequest->gameObjectType = gameObjectType; + getItemAttributeDataRequest->exactGameObjectTypeMatch = exactGameObjectTypeMatch; + getItemAttributeDataRequest->ignoreSearchableAttribute = ignoreSearchableAttribute; + getItemAttributeDataRequest->throttleNumberItemsPerFrame = throttle; + getItemAttributeDataRequest->numberItemsProcessed = 0; + getItemAttributeDataRequest->lastItemProcessed = NetworkId::cms_invalid; + + getItemAttributeDataRequest->outputFileName = outputFileName; + getItemAttributeDataRequest->allItemAttributes.clear(); + + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + char buffer[2048]; + snprintf(buffer, sizeof(buffer)-1, "%s request accepted. outputFileName=(%s), gameObjectType=(%d, %s), exactGameObjectTypeMatch=(%s), ignoreSearchableAttribute=(%s), throttle=(%d), totalNumberOfItems=(%d).", + getItemAttributeDataRequest->action.c_str(), + getItemAttributeDataRequest->outputFileName.c_str(), + getItemAttributeDataRequest->gameObjectType, + GameObjectTypes::getCanonicalName(getItemAttributeDataRequest->gameObjectType).c_str(), + (getItemAttributeDataRequest->exactGameObjectTypeMatch ? "yes" : "no" ), + (getItemAttributeDataRequest->ignoreSearchableAttribute ? "yes" : "no"), + getItemAttributeDataRequest->throttleNumberItemsPerFrame, + m_auctions.size()); + + buffer[sizeof(buffer)-1] = '\0'; + + GenericValueTypeMessage, std::string> > const msg("GetItemAttributeDataRsp", std::make_pair(std::make_pair(requester, std::string("(~!@#$%^&*)system_mesage(*&^%$#@!~)")), std::string(buffer))); + gameServerConn->send(msg, true); + } + } +} + +void AuctionMarket::getItemAttributeDataValues(int requestingGameServerId, const NetworkId & requester, int gameObjectType, bool exactGameObjectTypeMatch, const std::string & attributeName, int throttle) const +{ + if (getItemAttributeDataRequest) + { + if (getItemAttributeDataRequest->requester != requester) + { + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + char buffer[2048]; + snprintf(buffer, sizeof(buffer)-1, "There is already a pending %s request by (%s).", getItemAttributeDataRequest->action.c_str(), getItemAttributeDataRequest->requester.getValueString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + + GenericValueTypeMessage > const msg("DisplayStringForPlayer", std::make_pair(requester, std::string(buffer))); + gameServerConn->send(msg, true); + } + } + else if (getItemAttributeDataRequest->action != "GetItemAttributeDataValues") + { + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + char buffer[2048]; + snprintf(buffer, sizeof(buffer)-1, "There is already a pending %s request by (%s).", getItemAttributeDataRequest->action.c_str(), getItemAttributeDataRequest->requester.getValueString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + + GenericValueTypeMessage > const msg("DisplayStringForPlayer", std::make_pair(requester, std::string(buffer))); + gameServerConn->send(msg, true); + } + } + else + { + getItemAttributeDataRequest->requestingGameServerId = requestingGameServerId; + getItemAttributeDataRequest->throttleNumberItemsPerFrame = throttle; + + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + char buffer[2048]; + snprintf(buffer, sizeof(buffer)-1, "%s request modified. game object type=(%d, %s), exactGameObjectTypeMatch=(%s), attribute name=(%s), throttle=(%d), numberItemsProcessed=(%d), totalNumberOfItems=(%d).", + getItemAttributeDataRequest->action.c_str(), + getItemAttributeDataRequest->gameObjectType, + GameObjectTypes::getCanonicalName(getItemAttributeDataRequest->gameObjectType).c_str(), + (getItemAttributeDataRequest->exactGameObjectTypeMatch ? "yes" : "no" ), + getItemAttributeDataRequest->attributeName.c_str(), + getItemAttributeDataRequest->throttleNumberItemsPerFrame, + getItemAttributeDataRequest->numberItemsProcessed, + m_auctions.size()); + buffer[sizeof(buffer)-1] = '\0'; + + GenericValueTypeMessage > const msg("DisplayStringForPlayer", std::make_pair(requester, std::string(buffer))); + gameServerConn->send(msg, true); + } + } + } + else + { + getItemAttributeDataRequest = new GetItemAttributeDataRequest(); + getItemAttributeDataRequest->action = "GetItemAttributeDataValues"; + getItemAttributeDataRequest->requestingGameServerId = requestingGameServerId; + getItemAttributeDataRequest->requester = requester; + getItemAttributeDataRequest->throttleNumberItemsPerFrame = throttle; + getItemAttributeDataRequest->numberItemsProcessed = 0; + getItemAttributeDataRequest->lastItemProcessed = NetworkId::cms_invalid; + + getItemAttributeDataRequest->gameObjectType = gameObjectType; + getItemAttributeDataRequest->exactGameObjectTypeMatch = exactGameObjectTypeMatch; + getItemAttributeDataRequest->attributeName = attributeName; + getItemAttributeDataRequest->numberItemsMatchGameObjectType = 0; + getItemAttributeDataRequest->attributeValue.clear(); + + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + char buffer[2048]; + snprintf(buffer, sizeof(buffer)-1, "%s request accepted. game object type=(%d, %s), exactGameObjectTypeMatch=(%s), attribute name=(%s), throttle=(%d), totalNumberOfItems=(%d).", + getItemAttributeDataRequest->action.c_str(), + getItemAttributeDataRequest->gameObjectType, + GameObjectTypes::getCanonicalName(getItemAttributeDataRequest->gameObjectType).c_str(), + (getItemAttributeDataRequest->exactGameObjectTypeMatch ? "yes" : "no" ), + getItemAttributeDataRequest->attributeName.c_str(), + getItemAttributeDataRequest->throttleNumberItemsPerFrame, + m_auctions.size()); + buffer[sizeof(buffer)-1] = '\0'; + + GenericValueTypeMessage > const msg("DisplayStringForPlayer", std::make_pair(requester, std::string(buffer))); + gameServerConn->send(msg, true); + } + } +} + +void AuctionMarket::getItemAttribute(int requestingGameServerId, const NetworkId & requester, const NetworkId & item) const +{ + std::map::const_iterator iterAuction = m_auctions.find(item); + if (iterAuction != m_auctions.end()) + { + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + std::string output; + iterAuction->second->GetAttributes(output); + + GenericValueTypeMessage > const msg("DisplayStringForPlayer", std::make_pair(requester, output)); + gameServerConn->send(msg, true); + } + } + else + { + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + char buffer[2048]; + snprintf(buffer, sizeof(buffer)-1, "item (%s) is not in the commodities system", item.getValueString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + + GenericValueTypeMessage > const msg("DisplayStringForPlayer", std::make_pair(requester, std::string(buffer))); + gameServerConn->send(msg, true); + } + } +} + +void AuctionMarket::getVendorInfoForPlayer(int requestingGameServerId, const NetworkId & requester, const NetworkId & player, bool godMode) +{ + // if vendor is specified for player, replace it with the vendor's owner + NetworkId vendorOwner = player; + if (vendorOwner != requester) + { + std::map::iterator const iterFind = m_locationIdMap.find(vendorOwner); + if (iterFind != m_locationIdMap.end()) + { + vendorOwner = iterFind->second->GetOwnerId(); + } + } + + std::map > vendorInfo; + int totalOfferCount = 0; + int totalStockRoomCount = 0; + std::map >::const_iterator const iterPlayer = m_playerVendorListMap.find(vendorOwner); + if (iterPlayer != m_playerVendorListMap.end()) + { + char buffer[64]; + std::string planet; + std::string region; + std::string name; + NetworkId id; + int x, z; + int offerCount, stockRoomCount; + + unsigned int pos = 0; + + for (std::map::const_iterator iterAuctionLocation = iterPlayer->second.begin(); iterAuctionLocation != iterPlayer->second.end(); ++iterAuctionLocation) + { + pos = 0; + nextString(iterAuctionLocation->second->GetLocationString(), pos, planet, '.'); + nextString(iterAuctionLocation->second->GetLocationString(), pos, region, '.'); + nextString(iterAuctionLocation->second->GetLocationString(), pos, name, '.'); + nextOid(iterAuctionLocation->second->GetLocationString(), pos, id, '#'); + nextInt(iterAuctionLocation->second->GetLocationString(), pos, x, ','); + nextInt(iterAuctionLocation->second->GetLocationString(), pos, z, ','); + + if ((name.find("Vendor: ") == 0) && (name.size() > 8)) + { + name = name.substr(8); + } + + vendorInfo["name"].push_back(name); + + if (iterAuctionLocation->second->IsPacked()) + { + planet = "Datapad"; + } + else + { + planet = Unicode::wideToNarrow(StringId("planet_n", planet).localize()); + + snprintf(buffer, sizeof(buffer)-1, " (%d, %d)", x, z); + buffer[sizeof(buffer)-1] = '\0'; + + planet += buffer; + } + + if (godMode) + { + planet += " ("; + planet += iterAuctionLocation->second->GetLocationString(); + planet += ")"; + } + + vendorInfo["location"].push_back(planet); + + snprintf(buffer, sizeof(buffer)-1, "%d", (iterAuctionLocation->second->GetSalesTax() / 100)); + buffer[sizeof(buffer)-1] = '\0'; + vendorInfo["tax"].push_back(buffer); + + vendorInfo["taxCity"].push_back(iterAuctionLocation->second->GetSalesTaxBankId().getValueString()); + + if (iterAuctionLocation->second->GetEmptyDate() > 0) + { + vendorInfo["emptyDate"].push_back(CalendarTime::convertEpochToTimeStringLocal_YYYYMMDDHHMMSS(static_cast(iterAuctionLocation->second->GetEmptyDate()))); + } + else + { + vendorInfo["emptyDate"].push_back(""); + } + + if (iterAuctionLocation->second->GetLastAccessDate() > 0) + { + vendorInfo["lastAccessDate"].push_back(CalendarTime::convertEpochToTimeStringLocal_YYYYMMDDHHMMSS(static_cast(iterAuctionLocation->second->GetLastAccessDate()))); + } + else + { + vendorInfo["lastAccessDate"].push_back(""); + } + + if (iterAuctionLocation->second->GetInactiveDate() > 0) + { + vendorInfo["inactiveDate"].push_back(CalendarTime::convertEpochToTimeStringLocal_YYYYMMDDHHMMSS(static_cast(iterAuctionLocation->second->GetInactiveDate()))); + } + else + { + vendorInfo["inactiveDate"].push_back(""); + } + + vendorInfo["status"].push_back(vendorStatus[iterAuctionLocation->second->GetStatus()]); + + if (iterAuctionLocation->second->IsPacked()) + { + vendorInfo["searchable"].push_back("no"); + } + else + { + vendorInfo["searchable"].push_back(iterAuctionLocation->second->GetSearchEnabled() ? "yes" : "no"); + } + + snprintf(buffer, sizeof(buffer)-1, "%d", iterAuctionLocation->second->GetEntranceCharge()); + buffer[sizeof(buffer)-1] = '\0'; + vendorInfo["entranceCharge"].push_back(buffer); + + snprintf(buffer, sizeof(buffer)-1, "%d", iterAuctionLocation->second->GetAuctionItemCount()); + buffer[sizeof(buffer)-1] = '\0'; + vendorInfo["itemCount"].push_back(buffer); + + offerCount = 0; + stockRoomCount = 0; + std::map const & offers = iterAuctionLocation->second->GetVendorOffers(); + for (std::map::const_iterator iterOffer = offers.begin(); iterOffer != offers.end(); ++iterOffer) + { + if (iterOffer->second->GetItem().GetOwnerId() == vendorOwner) + { + stockRoomCount += iterOffer->second->GetItem().GetSize(); + } + else if (iterOffer->second->IsActive()) + { + offerCount += iterOffer->second->GetItem().GetSize(); + } + } + + snprintf(buffer, sizeof(buffer)-1, "%d", offerCount); + buffer[sizeof(buffer)-1] = '\0'; + vendorInfo["offerCount"].push_back(buffer); + + snprintf(buffer, sizeof(buffer)-1, "%d", stockRoomCount); + buffer[sizeof(buffer)-1] = '\0'; + vendorInfo["stockRoomCount"].push_back(buffer); + + totalOfferCount += offerCount; + totalStockRoomCount += stockRoomCount; + } + } + + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + char buffer[2048]; + + if (requester == vendorOwner) + { + snprintf(buffer, sizeof(buffer)-1, "You currently have %d initialized vendors containing %d active items, %d stockroom items, and %d offered items.", GetVendorCount(vendorOwner), GetItemCount(vendorOwner), totalStockRoomCount, totalOfferCount); + buffer[sizeof(buffer)-1] = '\0'; + } + else + { + snprintf(buffer, sizeof(buffer)-1, "Player %s currently has %d initialized vendors containing %d active items, %d stockroom items, and %d offered items.", vendorOwner.getValueString().c_str(), GetVendorCount(vendorOwner), GetItemCount(vendorOwner), totalStockRoomCount, totalOfferCount); + buffer[sizeof(buffer)-1] = '\0'; + } + + GenericValueTypeMessage, std::map > > > const msg("GetVendorInfoForPlayerRsp", std::make_pair(std::make_pair(requester, std::string(buffer)), vendorInfo)); + gameServerConn->send(msg, true); + } +} + +void AuctionMarket::getAuctionLocationPriorityQueue(int requestingGameServerId, const NetworkId & requester, int count) const +{ + std::string output; + char buffer[2048]; + int const timeNow = static_cast(::time(NULL)); + for (std::set >::const_iterator iterPQ = m_priorityQueueAuctionLocation.begin(); iterPQ != m_priorityQueueAuctionLocation.end(); ++iterPQ) + { + if (count <= 0) + break; + + std::map::const_iterator iterAuctionLocation = m_locationIdMap.find((*iterPQ).second); + if (iterAuctionLocation != m_locationIdMap.end()) + { + if ((*iterPQ).first >= timeNow) + { + snprintf(buffer, sizeof(buffer)-1, "next update in (%d, %s) for auction location (%s, %s)", (*iterPQ).first, CalendarTime::convertSecondsToDHMS(static_cast((*iterPQ).first - timeNow)).c_str(), (*iterPQ).second.getValueString().c_str(), iterAuctionLocation->second->GetLocationString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + } + else + { + snprintf(buffer, sizeof(buffer)-1, "next update in (%d, -%s) for auction location (%s, %s)", (*iterPQ).first, CalendarTime::convertSecondsToDHMS(static_cast(timeNow - (*iterPQ).first)).c_str(), (*iterPQ).second.getValueString().c_str(), iterAuctionLocation->second->GetLocationString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + } + } + else + { + if ((*iterPQ).first >= timeNow) + { + snprintf(buffer, sizeof(buffer)-1, "next update in (%d, %s) for auction location (%s)", (*iterPQ).first, CalendarTime::convertSecondsToDHMS(static_cast((*iterPQ).first - timeNow)).c_str(), (*iterPQ).second.getValueString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + } + else + { + snprintf(buffer, sizeof(buffer)-1, "next update in (%d, -%s) for auction location (%s)", (*iterPQ).first, CalendarTime::convertSecondsToDHMS(static_cast(timeNow - (*iterPQ).first)).c_str(), (*iterPQ).second.getValueString().c_str()); + buffer[sizeof(buffer)-1] = '\0'; + } + } + + output += buffer; + output += "\r\n"; + + --count; + } + + GameServerConnection * const gameServerConn = CommodityServer::getInstance().getGameServer(requestingGameServerId); + if (gameServerConn) + { + GenericValueTypeMessage > const msg("DisplayStringForPlayer", std::make_pair(requester, output)); + gameServerConn->send(msg, true); + } +} + +void AuctionMarket::BuildAuctionsSearchableAttributeList() +{ + for (std::map::iterator i = m_auctions.begin(); i != m_auctions.end(); ++i) + i->second->BuildSearchableAttributeList(); +} + +void AuctionMarket::addAuctionLocationToLocationIndex(const AuctionLocation * auctionLocation) +{ + if (!auctionLocation) + return; + + if (!auctionLocation->IsVendorMarket()) + { + m_allBazaar[auctionLocation->GetLocationId()] = const_cast(auctionLocation); + (m_bazaarByPlanet[auctionLocation->GetLocationPlanet()])[auctionLocation->GetLocationId()] = const_cast(auctionLocation); + (m_bazaarByRegion[std::make_pair(auctionLocation->GetLocationPlanet(), auctionLocation->GetLocationRegion())])[auctionLocation->GetLocationId()] = const_cast(auctionLocation); + } + else if (auctionLocation->GetSearchEnabled() && !auctionLocation->IsPacked()) + { + m_allSearchableVendor[auctionLocation->GetLocationId()] = const_cast(auctionLocation); + (m_searchableVendorByPlanet[auctionLocation->GetLocationPlanet()])[auctionLocation->GetLocationId()] = const_cast(auctionLocation); + (m_searchableVendorByRegion[std::make_pair(auctionLocation->GetLocationPlanet(), auctionLocation->GetLocationRegion())])[auctionLocation->GetLocationId()] = const_cast(auctionLocation); + } +} + +void AuctionMarket::removeAuctionLocationFromLocationIndex(const AuctionLocation * auctionLocation) +{ + if (!auctionLocation) + return; + + { + m_allBazaar.erase(auctionLocation->GetLocationId()); + } + + { + std::map >::iterator iterFind = m_bazaarByPlanet.find(auctionLocation->GetLocationPlanet()); + if (iterFind != m_bazaarByPlanet.end()) + { + iterFind->second.erase(auctionLocation->GetLocationId()); + if (iterFind->second.empty()) + { + m_bazaarByPlanet.erase(iterFind); + } + } + } + + { + std::map, std::map >::iterator iterFind = m_bazaarByRegion.find(std::make_pair(auctionLocation->GetLocationPlanet(), auctionLocation->GetLocationRegion())); + if (iterFind != m_bazaarByRegion.end()) + { + iterFind->second.erase(auctionLocation->GetLocationId()); + if (iterFind->second.empty()) + { + m_bazaarByRegion.erase(iterFind); + } + } + } + + { + m_allSearchableVendor.erase(auctionLocation->GetLocationId()); + } + + { + std::map >::iterator iterFind = m_searchableVendorByPlanet.find(auctionLocation->GetLocationPlanet()); + if (iterFind != m_searchableVendorByPlanet.end()) + { + iterFind->second.erase(auctionLocation->GetLocationId()); + if (iterFind->second.empty()) + { + m_searchableVendorByPlanet.erase(iterFind); + } + } + } + + { + std::map, std::map >::iterator iterFind = m_searchableVendorByRegion.find(std::make_pair(auctionLocation->GetLocationPlanet(), auctionLocation->GetLocationRegion())); + if (iterFind != m_searchableVendorByRegion.end()) + { + iterFind->second.erase(auctionLocation->GetLocationId()); + if (iterFind->second.empty()) + { + m_searchableVendorByRegion.erase(iterFind); + } + } + } +} + +void AuctionMarket::sanityCheckAuctionLocationBeingDestroyed(const AuctionLocation * auctionLocation) +{ + if (!auctionLocation) + return; + + { + removeAuctionLocationFromList(m_locationIdMap, auctionLocation); + } + + { + for (std::map >::iterator iter = m_playerVendorListMap.begin(); iter != m_playerVendorListMap.end(); ++iter) + { + removeAuctionLocationFromList(iter->second, auctionLocation); + } + } + + { + removeAuctionLocationFromList(m_allBazaar, auctionLocation); + } + + { + for (std::map >::iterator iter = m_bazaarByPlanet.begin(); iter != m_bazaarByPlanet.end(); ++iter) + { + removeAuctionLocationFromList(iter->second, auctionLocation); + } + } + + { + for (std::map, std::map >::iterator iter = m_bazaarByRegion.begin(); iter != m_bazaarByRegion.end(); ++iter) + { + removeAuctionLocationFromList(iter->second, auctionLocation); + } + } + + { + removeAuctionLocationFromList(m_allSearchableVendor, auctionLocation); + } + + { + for (std::map >::iterator iter = m_searchableVendorByPlanet.begin(); iter != m_searchableVendorByPlanet.end(); ++iter) + { + removeAuctionLocationFromList(iter->second, auctionLocation); + } + } + + { + for (std::map, std::map >::iterator iter = m_searchableVendorByRegion.begin(); iter != m_searchableVendorByRegion.end(); ++iter) + { + removeAuctionLocationFromList(iter->second, auctionLocation); + } + } +} + +void AuctionMarket::getPlanetAndRegionFromLocationString(const std::string &locationName, std::string &planet, std::string ®ion) +{ + unsigned int pos = 0; + nextString(locationName, pos, planet, '.'); + nextString(locationName, pos, region, '.'); +} diff --git a/engine/server/application/CommoditiesServer/src/shared/AuctionMarket.h b/engine/server/application/CommoditiesServer/src/shared/AuctionMarket.h new file mode 100644 index 00000000..78b42584 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/AuctionMarket.h @@ -0,0 +1,235 @@ +// ====================================================================== +// +// AuctionMarket.h (refactor of original Commodities Market code) +// copyright (c) 2004 Sony Online Entertainment +// +// Original Author: Matt Severenson +// Refactored by : Doug Mellencamp +// +// All the Commodities Market logic is part of this class. Changes were +// made to this class only to the degree necessary to make it work with +// the new server infrastructure. In other words ... the logic is +// estentially unchanged and there are still many issues with the logic +// code itself. +// +// ====================================================================== + +#ifndef AuctionMarket_h +#define AuctionMarket_h + +#include "sharedFoundation/NetworkId.h" +#include "Singleton/Singleton.h" + +#include "serverNetworkMessages/AcceptHighBidMessage.h" +#include "serverNetworkMessages/AddAuctionMessage.h" +#include "serverNetworkMessages/AddBidMessage.h" +#include "serverNetworkMessages/AddImmediateAuctionMessage.h" +#include "serverNetworkMessages/AuctionBase.h" +#include "serverNetworkMessages/CancelAuctionMessage.h" +#include "serverNetworkMessages/CleanupInvalidItemRetrievalMessage.h" +#include "serverNetworkMessages/CreateVendorMarketMessage.h" +#include "serverNetworkMessages/DeleteAuctionLocationMessage.h" +#include "serverNetworkMessages/DestroyVendorMarketMessage.h" +#include "serverNetworkMessages/GetItemDetailsMessage.h" +#include "serverNetworkMessages/GetItemMessage.h" +#include "serverNetworkMessages/GetPlayerVendorCountMessage.h" +#include "serverNetworkMessages/SetSalesTaxMessage.h" +#include "serverNetworkMessages/GetVendorOwnerMessage.h" +#include "serverNetworkMessages/GetVendorValueMessage.h" +#include "serverNetworkMessages/QueryAuctionHeadersMessage.h" +#include "sharedNetworkMessages/DeleteCharacterMessage.h" +#include "serverNetworkMessages/SetEntranceChargeMessage.h" +#include "serverNetworkMessages/SetGameTimeMessage.h" +#include "serverNetworkMessages/QueryVendorItemCountMessage.h" +#include "serverNetworkMessages/UpdateVendorSearchOptionMessage.h" +#include "serverNetworkMessages/UpdateVendorStatusMessage.h" + +#include "Auction.h" +#include "AuctionItem.h" +#include "AuctionLocation.h" + +#include +#include +#include +#include +#include +#include "Unicode.h" + +class GameServerConnection; + +class AuctionMarket : public Singleton +{ +private: + +protected: + std::map m_locationIdMap; + std::map > m_playerVendorListMap; + + std::map m_allBazaar; + std::map > m_bazaarByPlanet; + std::map, std::map > m_bazaarByRegion; + + std::map m_allSearchableVendor; + std::map > m_searchableVendorByPlanet; + std::map, std::map > m_searchableVendorByRegion; + + std::map m_auctions; + std::map m_auctionsCountByGameObjectType; + std::set m_auctionsCountByGameObjectTypeChanged; // clear() by CommodityServerMetricsData + std::map m_auctionCountMap; + + std::map > m_resourceTreeHierarchy; + std::map > m_itemTypeMap; + int m_itemTypeMapVersionNumber; + std::map > m_resourceTypeMap; + int m_resourceTypeMapVersionNumber; + int m_gameTime; + bool m_showAllDebugInfo; + + // auctions that are completed during this frame + // and needs to be processes at the start of the next frame + // (typically buy now auctions bought during this frame) + std::vector m_completedAuctions; + + // priority queue of auctions ordered by + // the auction expiration time + std::set > m_priorityQueueAuctionTimer; + + // priority queue of auctions ordered by + // the item's expiration time + std::set > m_priorityQueueItemTimer; + + // priority queue of auction locations ordered by the time + // the auction location needs to be checked for status change + std::set > m_priorityQueueAuctionLocation; + + void AddAuction(Auction *auction); + void DestroyAuction(std::map::iterator & iter); + void UpdateLiveAuctions(int gameTime); + void DestroyExpiredItems(int gameTime); + AuctionLocation * CreateLocation(const NetworkId & ownerId, const std::string & locationString, int entranceCharge); + void InitializeFromDB(); + bool FixVendorLocation( const std::string& ); + bool GetContainerIdString( const std::string&, std::string& ); + NetworkId GetLocationId(const std::string&); + void ModifyAuctionCount (const NetworkId & playerId, int delta); + bool HasOpenAuctionSlots (const NetworkId & playerId); + void AddPlayerVendor(const NetworkId & playerId, const NetworkId & vendorId, AuctionLocation * auctionLocation); + void RemovePlayerVendor(const NetworkId & playerId, const NetworkId & vendorId); + int GetVendorCount(const NetworkId & playerId); + int GetItemCount(const NetworkId & playerId); + void AddAuctionToPriorityQueue(const Auction & auction); + + void SingletonInialize(); + +public: + AuctionMarket(); + ~AuctionMarket(); + +enum VendorStatusCode +{ + ACTIVE, + EMPTY, + UNACCESSED, + EMPTY_AND_UNACCESSED, + ENDANGERED, + REMOVED +}; + + void Update (int gameTime); + void AddAuction (const AddAuctionMessage &message); + void AddImmediateAuction (const AddImmediateAuctionMessage &message); + void AddBid (const AddBidMessage &message); + void CancelAuction (const CancelAuctionMessage &message); + void AcceptHighBid (const AcceptHighBidMessage &message); + void QueryAuctionHeaders (const QueryAuctionHeadersMessage &message); + void SetGameTime (const SetGameTimeMessage &message); + void GetItemDetails (const GetItemDetailsMessage &message); + void GetItem (const GetItemMessage &message); + void CreateVendorMarket (const CreateVendorMarketMessage &message); + void DestroyVendorMarket (const DestroyVendorMarketMessage &message); + void DeleteAuctionLocation (const DeleteAuctionLocationMessage &message); + void GetVendorOwner (const GetVendorOwnerMessage &message); + void GetVendorValue (const GetVendorValueMessage &message); + void CleanupInvalidItemRetrieval (const CleanupInvalidItemRetrievalMessage &message); + void SetSalesTax (const SetSalesTaxMessage &message); + void QueryVendorItemCount (const QueryVendorItemCountMessage &message); + void GetPlayerVendorCount (const GetPlayerVendorCountMessage &message); + void UpdateVendorSearchOption (const UpdateVendorSearchOptionMessage &message); + void SetEntranceCharge (const SetEntranceChargeMessage &message); + void DeleteCharacter (const DeleteCharacterMessage &message); + void UpdateVendorStatus (const UpdateVendorStatusMessage &message); + void UpdateVendorLocation (const NetworkId &locationId, const std::string &locationString); + + void SendItemTypeMap (GameServerConnection &gameServerConnection); + + void AddResourceType (int resourceClassCrc, const std::string & resourceName); + void SendResourceTypeMap (GameServerConnection &gameServerConnection); + + void RemoveFromAuctionTimerPriorityQueue(int timer, const NetworkId & item); + void AddAuctionToCompletedAuctionsList(const Auction & auction); + + void onReceiveAuctionLocations (const NetworkId &locationId, const std::string &locationName, const NetworkId &ownerId, const int salesTax, const NetworkId &salesTaxBankId, const int emptyDate, const int lastAccessDate, const int inactiveDate, const int status, const bool searchEnabled, const int entranceCharge); + void onReceiveMarketAuctions (const NetworkId &itemId, const NetworkId &ownerId, const NetworkId &creatorId, const NetworkId &locationId, const int minBid, const int buyNowPrice, const int auctionTimer, const std::string &oob, const Unicode::String &userDescription, const int category, const int itemTemplateId, const Unicode::String &itemName, const int itemTimer, const int active, const int itemSize); + void onReceiveMarketAuctionAttributes(const NetworkId &itemId, const std::string &attributeName, const Unicode::String &attributeValue); + void onReceiveMarketAuctionBids (const NetworkId &itemId, const NetworkId &bidderId, const int bid, const int maxProxyBid); + void printAuctionTables(); + + int getAuctionCount () const { return m_auctions.size(); } + int getLocationCount () const { return m_locationIdMap.size(); } + + void OnAddAuction (int trackId, int result, int responseId, const NetworkId & itemId, const NetworkId & ownerId, const std::string & ownerName, const NetworkId & vendorId, const std::string & location); + void OnAddBid (int trackId, int result, int responseId, const NetworkId & ownerId, const NetworkId & itemId, const NetworkId & bidderId, const NetworkId & previousBidderId, int bidAmount, int previousBidAmount, int maxProxyBid, const std::string & location, int itemNameLength, const Unicode::String & itemName, int salesTaxAmount, const NetworkId & salesTaxBankId); + void OnCancelAuction (int trackId, int result, int responseId, const NetworkId & itemId, const NetworkId & playerId, const NetworkId & highBidderId, int highBid, const std::string & location); + void OnAcceptHighBid (int trackId, int result, int responseId, const NetworkId & itemId, const NetworkId & playerId); + void OnQueryAuctionHeaders (int trackId, int result, int responseId, const NetworkId & playerId, int queryType, std::vector &auctions, unsigned int queryOffset, bool hasMorePages); + void OnGetItemDetails (int trackId, int result, int responseId, const NetworkId & itemId, const NetworkId & playerId, int userDescriptionLength, const Unicode::String & userDescription, int oobDataLength, const Unicode::String & oobData, std::vector > const & attributes); + void OnAuctionExpired (const NetworkId & ownerId, bool sold, int flags, const NetworkId & buyerId, int highBidAmount, const NetworkId & itemId, int highBidMaxProxy, const std::string & location, bool immediate, int itemNameLength, const Unicode::String & itemName, const NetworkId & itemOwnerId, int track_id, bool sendSellerMail); + void OnItemExpired (const NetworkId & ownerId, const NetworkId & itemId, int itemNameLength, const Unicode::String & itemName, const std::string & locationName, const NetworkId & locationId); + void OnGetItem (int trackId, int result, int responseId, const NetworkId & itemId, const NetworkId & playerId, const std::string & location); + void OnCreateVendorMarket (int trackId, int result, int responseId, const NetworkId & ownerId, const std::string & location); + void OnVendorRefuseItem (int trackId, int result, int responseId, const NetworkId & itemId, const NetworkId & vendorId, const NetworkId & itemOwnerId); + void OnGetVendorOwner (int trackId, int result, int responseId, const NetworkId & ownerId, const NetworkId & requesterId, const std::string & location); + void OnGetVendorValue (int trackId, int responseId, const std::string & location, int value); + void OnPermanentAuctionPurchased (int trackId, const NetworkId & ownerId, const NetworkId & buyerId, int price, const NetworkId & itemId, const std::string & location, int itemNameLength, const Unicode::String & itemName, std::vector > const & attributes); + void OnCleanupInvalidItemRetrieval (int trackId, int responseId, const NetworkId & itemId, const NetworkId & playerId, const NetworkId & creatorId, int reimburseAmt); + void OnQueryVendorItemCount (const int responseId, const int trackId, const NetworkId &vendorId, const int itemCount, const bool searchEnabled); + void OnGetPlayerVendorCount (const int responseId, const int trackId, const NetworkId &playerId, const int vendorCount, std::vector vendorList); + void OnVendorStatusChange (int trackId, const NetworkId &vendorId, int newStatus); + + AuctionLocation & GetLocation (const std::string & location); + AuctionLocation & GetLocation (const NetworkId & location); + + void VerifyExcludedGotTypes (stdmap::fwd const & excludedGotTypes); + void VerifyExcludedResourceClasses (stdset::fwd const & excludedResourceClasses); + void SetResourceTreeHierarchy (stdmap::fwd>::fwd const & resourceTreeHierarchy); + bool HasReceivedResourceTreeHierarchy() const {return !m_resourceTreeHierarchy.empty();} + + std::map const & getAuctionsCountByGameObjectType() const { return m_auctionsCountByGameObjectType; } + std::set & getAuctionsCountByGameObjectTypeChanged() { return m_auctionsCountByGameObjectTypeChanged; } + + void getItemAttributeData (int requestingGameServerId, const NetworkId & requester, const std::string & outputFileName, int gameObjectType, bool exactGameObjectTypeMatch, bool ignoreSearchableAttribute, int throttle) const; + void getItemAttributeDataValues (int requestingGameServerId, const NetworkId & requester, int gameObjectType, bool exactGameObjectTypeMatch, const std::string & attributeName, int throttle) const; + void getItemAttribute (int requestingGameServerId, const NetworkId & requester, const NetworkId & item) const; + void getVendorInfoForPlayer (int requestingGameServerId, const NetworkId & requester, const NetworkId & player, bool godMode); + void getAuctionLocationPriorityQueue(int requestingGameServerId, const NetworkId & requester, int count) const; + + void addAuctionLocationToLocationIndex(const AuctionLocation * auctionLocation); + void removeAuctionLocationFromLocationIndex(const AuctionLocation * auctionLocation); + + void sanityCheckAuctionLocationBeingDestroyed(const AuctionLocation * auctionLocation); + + void BuildAuctionsSearchableAttributeList(); + + void AddAuctionLocationToPriorityQueue(const AuctionLocation & auctionLocation); + void RemoveAuctionLocationFromPriorityQueue(const AuctionLocation & auctionLocation); + + static void getPlanetAndRegionFromLocationString(const std::string &locationName, std::string &planet, std::string ®ion); + + friend class CommodityServer; + +private: + bool IsResourceClassDerivedFrom (int resourceClassCrc, int parentResourceClassCrc); +}; + +#endif diff --git a/engine/server/application/CommoditiesServer/src/shared/CentralServerConnection.cpp b/engine/server/application/CommoditiesServer/src/shared/CentralServerConnection.cpp new file mode 100644 index 00000000..45e87326 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/CentralServerConnection.cpp @@ -0,0 +1,55 @@ +// CentralServerConnection.cpp +// copyright 2001 Verant Interactive + +//----------------------------------------------------------------------- + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "CentralServerConnection.h" +#include "sharedNetwork/NetworkSetupData.h" + +//----------------------------------------------------------------------- +CentralServerConnection::CentralServerConnection(const std::string & address, const unsigned short port) : +ServerConnection(address, port, NetworkSetupData()) +{ +} + + +//----------------------------------------------------------------------- +CentralServerConnection::CentralServerConnection(UdpConnectionMT * u, TcpClient * t) : +ServerConnection(u, t) +{ +} + +//----------------------------------------------------------------------- + +CentralServerConnection::~CentralServerConnection() +{ +} + +//----------------------------------------------------------------------- + + +void CentralServerConnection::onConnectionClosed() +{ + ServerConnection::onConnectionClosed(); + static MessageConnectionCallback m("CentralServerConnectionClosed"); + emitMessage(m); + exit(0); +} + +//----------------------------------------------------------------------- + +void CentralServerConnection::onConnectionOpened() +{ + ServerConnection::onConnectionOpened(); + static const MessageConnectionCallback m("CentralServerConnectionOpened"); + emitMessage(m); +} + +//----------------------------------------------------------------------- + +void CentralServerConnection::onReceive(const Archive::ByteStream & message) +{ + ServerConnection::onReceive(message); +} +//----------------------------------------------------------------------- diff --git a/engine/server/application/CommoditiesServer/src/shared/CentralServerConnection.h b/engine/server/application/CommoditiesServer/src/shared/CentralServerConnection.h new file mode 100644 index 00000000..a29199b5 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/CentralServerConnection.h @@ -0,0 +1,33 @@ +// CentralServerConnection.h +// copyright 2004 Verant Interactive +// Author: Justin Randall + +#ifndef _CentralServerConnection_H +#define _CentralServerConnection_H + +//----------------------------------------------------------------------- + +#include "serverUtility/ServerConnection.h" + +//----------------------------------------------------------------------- + +class CentralServerConnection : public ServerConnection +{ +public: + CentralServerConnection (const std::string & address, const unsigned short port); + CentralServerConnection(UdpConnectionMT *, TcpClient *); + ~CentralServerConnection(); + void onConnectionClosed(); + void onConnectionOpened(); + void onReceive(const Archive::ByteStream & message); + +private: + CentralServerConnection(); + CentralServerConnection(const CentralServerConnection&); + CentralServerConnection& operator=(const CentralServerConnection&); + +}; + +//----------------------------------------------------------------------- + +#endif // _CentralServerConnection_H diff --git a/engine/server/application/CommoditiesServer/src/shared/CommodityServer.cpp b/engine/server/application/CommoditiesServer/src/shared/CommodityServer.cpp new file mode 100644 index 00000000..4585adfe --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/CommodityServer.cpp @@ -0,0 +1,296 @@ +// ====================================================================== +// +// ConfigCommodityServer.cpp +// Copyright 2004, Sony Online Entertainment Inc., all rights reserved. +// Author: Doug Mellencamp +// Server Infrastructure by: Justin Randall +// +// This is the primary entry point to the commodities service. This class +// is called from main.cpp. The main server loop is encapsulated here +// in the run method +// +// ====================================================================== + +#include "FirstCommodityServer.h" + +#include "AuctionMarket.h" +#include "CommodityServer.h" +#include "CommodityServerMetricsData.h" +#include "CentralServerConnection.h" +#include "DatabaseServerConnection.h" +#include "GameServerConnection.h" +#include "ConfigCommodityServer.h" +#include "serverMetrics/MetricsManager.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/Os.h" +#include "sharedNetwork/Connection.h" +#include "sharedNetwork/Service.h" +#include "sharedNetwork/NetworkSetupData.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "sharedLog/Log.h" +#include "sharedLog/SetupSharedLog.h" + +//----------------------------------------------------------------------- + +namespace CommodityServerNamespace +{ + Service * s_gameServerService = 0; // the listening service waiting for game server connections + AuctionMarket * s_auctionMarketManager = 0; // the Auction Market singleton containg all the logic + CentralServerConnection * s_centralServerConnection = 0; // connection to central + DatabaseServerConnection * s_databaseServerConnection = 0; + CommodityServerMetricsData * s_commodityServerMetricsData = 0; +} + +using namespace CommodityServerNamespace; + +//----------------------------------------------------------------------- + +CommodityServer::CommodityServer() : +Singleton(), +MessageDispatch::Receiver(), +m_gameserverMap(), +m_commoditiesServerLoadDone(0), +m_timeCommoditiesServerStarted(time(0)), +m_commoditiesServerLoadTime(-1) +{ + connectToMessage("CommoditiesLoadDone"); + connectToMessage("DatabaseServerConnectionClosed"); +} + +//----------------------------------------------------------------------- + +CommodityServer::~CommodityServer() +{ +} + +//----------------------------------------------------------------------- + +void CommodityServer::receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message) +{ + if(message.isType("CommoditiesLoadDone")) + { + m_commoditiesServerLoadDone = 1; + + // record how long it took the commodities server to load + if (m_commoditiesServerLoadTime == -1) + m_commoditiesServerLoadTime = (time(0) - m_timeCommoditiesServerStarted) / 60; + } + else if (message.isType("DatabaseServerConnectionClosed")) + { + WARNING(true, ("[Commodities Server] : No connection to the database server. Shutting down.\n")); + exit(0); + } +} + +//----------------------------------------------------------------------- + +int CommodityServer::addGameServer (GameServerConnection & gameserver) +{ + static int nextGameServerId = 0; + int tmp = ++nextGameServerId; + m_gameserverMap[tmp] = &gameserver; + AuctionMarket::getInstance().SendItemTypeMap(gameserver); + AuctionMarket::getInstance().SendResourceTypeMap(gameserver); + return tmp; +} + +//----------------------------------------------------------------------- + +void CommodityServer::removeGameServer (int gameServerId) +{ + WARNING_STRICT_FATAL(gameServerId == 0, ("Tried to remove a gameserver with id == 0")); + std::map::iterator i = m_gameserverMap.find(gameServerId); + if (i != m_gameserverMap.end()) + { + IGNORE_RETURN(m_gameserverMap.erase(gameServerId)); + } +} + +//----------------------------------------------------------------------- + +GameServerConnection* CommodityServer::getGameServer (int gameServerId) +{ + WARNING_STRICT_FATAL(gameServerId == 0, ("Tried to get a gameserver with id == 0")); + if (gameServerId == -1) + { + // if requested game server id is -1 we don't know what game server + // to send to so use the first known good one + std::map::iterator i = m_gameserverMap.begin(); + while (i != m_gameserverMap.end()) + { + if ((*i).second) + { + return (*i).second; + } + ++i; + } + return 0; + } + else + { + std::map::iterator i = m_gameserverMap.find(gameServerId); + if (i == m_gameserverMap.end()) + return 0; + else + return i->second; + } +} + +//----------------------------------------------------------------------- + +void CommodityServer::sendToAllGameServers(const GameNetworkMessage & message) +{ + for (std::map::const_iterator i = m_gameserverMap.begin(); i != m_gameserverMap.end(); ++i) + i->second->send(message, true); +} + +//----------------------------------------------------------------------- + +DatabaseServerConnection* CommodityServer::getDatabaseServer () +{ + return s_databaseServerConnection; +} + +//----------------------------------------------------------------------- + +int CommodityServer::getCommoditiesServerLoadTime() const +{ + if (m_commoditiesServerLoadTime != -1) + return m_commoditiesServerLoadTime; + else + // return how long the commodities server has been loading + return ((time(0) - m_timeCommoditiesServerStarted) / 60); +} + +//----------------------------------------------------------------------- + +void CommodityServer::run() +{ + + // setup log for CommoditiesServer + SetupSharedLog::install("CommoditiesServer"); + + int const sleepTimePerFrameMs = ConfigCommodityServer::getSleepTimePerFrameMs(); + + NetworkSetupData setup; + setup.port = ConfigCommodityServer::getCMServerServiceBindPort(); + setup.bindInterface = ConfigCommodityServer::getCMServerServiceBindInterface(); + setup.maxConnections=500; + + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Starting Commodities Auction Market Manager.\n")); + AuctionMarket::getInstance().SingletonInialize(); + + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Initiating connection to SWG Database Server.\n")); + s_databaseServerConnection = new DatabaseServerConnection(ConfigCommodityServer::getDatabaseServerAddress(), ConfigCommodityServer::getDatabaseServerPort()); + + Auction::Initialization(); + AuctionLocation::Initialization(); + AuctionMarket::getInstance().InitializeFromDB(); + + s_commodityServerMetricsData = new CommodityServerMetricsData; + MetricsManager::install(s_commodityServerMetricsData, false, "CommoditiesServer", "", 0); + + time_t timePrevious = ::time(NULL); + time_t timeCurrent = timePrevious; + + while (true) + { + volatile int i; + i = CommodityServer::getInstance().m_commoditiesServerLoadDone; + if (i == 1) + break; + NetworkHandler::update(); + + timeCurrent = ::time(NULL); + MetricsManager::update(static_cast((timeCurrent - timePrevious) * 1000)); + timePrevious = timeCurrent; + + NetworkHandler::dispatch(); + NetworkHandler::clearBytesThisFrame(); + Os::sleep(sleepTimePerFrameMs); + } + + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Auction Market loaded and initialized.\n")); + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Starting Commodities Game Server Listening Service.\n")); + s_gameServerService = new Service(ConnectionAllocator(), setup); + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Initiating connection to central server.\n")); + s_centralServerConnection = new CentralServerConnection(ConfigCommodityServer::getCentralServerAddress(), ConfigCommodityServer::getCentralServerPort()); + + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Entering Commodities Server main message processing loop (sleep time %dms).\n", sleepTimePerFrameMs)); + + // one time operation to request from the game server + // (any game server) the list of GOT types and resource + // classes that are excluded from the vendor/bazaar + // Object Type Filter tree so that we can check to see + // if we have any item that belongs in an excluded GOT type + // or resource class so that we can remove that GOT type + // or resource class from the excluded list; + // this is not a high priority thing, so wait until + // the cluster has started and "stabilized" before + // doing this; 3 hours should be adequate + time_t timeToRequestExcludedType = ::time(NULL) + 10800; + + // one time request from the game server (any game server) + // to receive the resource tree hierarchy to support + // searching for resource container + time_t timeToRequestResourceTree = ::time(NULL); + + while(true) + { + NetworkHandler::update(); + + timeCurrent = ::time(NULL); + MetricsManager::update(static_cast((timeCurrent - timePrevious) * 1000)); + timePrevious = timeCurrent; + + NetworkHandler::dispatch(); + if (! CommodityServer::getInstance().m_gameserverMap.empty()) + { + // one time request for a game server to send us the resource + // tree hierarchy to support searching resource containers + if (!AuctionMarket::getInstance().HasReceivedResourceTreeHierarchy()) + { + // keep asking every 10 seconds until we receive the resource tree + if (timeToRequestResourceTree <= timeCurrent) + { + GameServerConnection * gsConn = CommodityServer::getInstance().getGameServer(-1); + if (gsConn) + { + GenericValueTypeMessage const msg("RequestResourceTreeHierarchy", 1); + gsConn->send(msg, true); + } + + timeToRequestResourceTree = timeCurrent + 10; + } + } + + if (timeToRequestExcludedType && (timeToRequestExcludedType <= timeCurrent)) + { + GameServerConnection * gsConn = CommodityServer::getInstance().getGameServer(-1); + if (gsConn) + { + GenericValueTypeMessage const msg("RequestCommoditiesExcludedGotTypes", 1); + gsConn->send(msg, true); + + GenericValueTypeMessage const msg2("RequestCommoditiesExcludedResourceClasses", 1); + gsConn->send(msg2, true); + + timeToRequestExcludedType = 0; + } + } + + AuctionMarket::getInstance().Update(time(0)); + } + NetworkHandler::clearBytesThisFrame(); + Os::sleep(sleepTimePerFrameMs); + } + s_centralServerConnection = 0; + s_gameServerService = 0; + s_databaseServerConnection = 0; + + MetricsManager::remove(); + delete s_commodityServerMetricsData; + s_commodityServerMetricsData = 0; +} + +//----------------------------------------------------------------------- diff --git a/engine/server/application/CommoditiesServer/src/shared/CommodityServer.h b/engine/server/application/CommoditiesServer/src/shared/CommodityServer.h new file mode 100644 index 00000000..91540a8d --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/CommodityServer.h @@ -0,0 +1,58 @@ +// ====================================================================== +// +// ConfigCommodityServer.h +// Copyright 2004, Sony Online Entertainment Inc., all rights reserved. +// Author: Doug Mellencamp +// Server Infrastructure by: Justin Randall +// +// This is the primary entry point to the commodities service. This class +// is called from main.cpp. The main server loop is encapsulated here. +// +// ====================================================================== +#ifndef _INCLUDED_CommodityServer_H +#define _INCLUDED_CommodityServer_H + +//----------------------------------------------------------------------- + +#include "Singleton/Singleton.h" +#include "Archive/ByteStream.h" +#include "sharedMessageDispatch/Receiver.h" +#include + +class GameNetworkMessage; +class GameServerConnection; +class DatabaseServerConnection; + +//----------------------------------------------------------------------- + +class CommodityServer : public Singleton, public MessageDispatch::Receiver +{ +public: + CommodityServer(); + ~CommodityServer(); + + void receiveMessage (const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message); + + int addGameServer (GameServerConnection & gameserver); + void removeGameServer (int gameServerId); + GameServerConnection* getGameServer (int gameServerId); + void sendToAllGameServers(const GameNetworkMessage & message); + DatabaseServerConnection* getDatabaseServer (); + int getCommoditiesServerLoadTime() const; + + static void run(); + +private: + + std::map m_gameserverMap; + int m_commoditiesServerLoadDone; + time_t m_timeCommoditiesServerStarted; + int m_commoditiesServerLoadTime; + + CommodityServer & operator = (const CommodityServer & rhs); + CommodityServer(const CommodityServer & source); +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_CommodityServer_H diff --git a/engine/server/application/CommoditiesServer/src/shared/CommodityServerMetricsData.cpp b/engine/server/application/CommoditiesServer/src/shared/CommodityServerMetricsData.cpp new file mode 100644 index 00000000..4b1ff37e --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/CommodityServerMetricsData.cpp @@ -0,0 +1,99 @@ +// ====================================================================== +// +// CommodityServerMetricsData.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstCommodityServer.h" +#include "CommodityServerMetricsData.h" + +#include "AuctionMarket.h" +#include "CommodityServer.h" +#include "sharedGame/GameObjectTypes.h" + +// ====================================================================== + +CommodityServerMetricsData::CommodityServerMetricsData() : + MetricsData(), + m_numItems(0), + m_numLocations(0), + m_loadTime(0), + m_mapAuctionsCountByGameObjectTypeIndex() +{ + MetricsPair p; + + ADD_METRICS_DATA(numItems, 0, true); + ADD_METRICS_DATA(numLocations, 0, true); + ADD_METRICS_DATA(loadTime, 0, true); + + m_data[m_loadTime].m_description = "minutes"; +} + +//----------------------------------------------------------------------- + +CommodityServerMetricsData::~CommodityServerMetricsData() +{ +} + +//----------------------------------------------------------------------- + +void CommodityServerMetricsData::updateData() +{ + MetricsData::updateData(); + m_data[m_numItems].m_value = AuctionMarket::getInstance().getAuctionCount(); + m_data[m_numLocations].m_value = AuctionMarket::getInstance().getLocationCount(); + m_data[m_loadTime].m_value = CommodityServer::getInstance().getCommoditiesServerLoadTime(); + + // handle auctions count by game object type statistics + std::map const & auctionsCountByGameObjectType = AuctionMarket::getInstance().getAuctionsCountByGameObjectType(); + std::set & auctionsCountByGameObjectTypeChanged = AuctionMarket::getInstance().getAuctionsCountByGameObjectTypeChanged(); + if (!auctionsCountByGameObjectTypeChanged.empty() && !auctionsCountByGameObjectType.empty()) + { + if (m_mapAuctionsCountByGameObjectTypeIndex.empty()) + { + int gameObjectType; + int baseGameObjectType; + char buffer[1024]; + for (std::map::const_iterator iterGameObjectType = auctionsCountByGameObjectType.begin(); iterGameObjectType != auctionsCountByGameObjectType.end(); ++iterGameObjectType) + { + if (!iterGameObjectType->first.empty() && (iterGameObjectType->second >= 0) && (m_mapAuctionsCountByGameObjectTypeIndex.count(iterGameObjectType->first) < 1)) + { + gameObjectType = GameObjectTypes::getGameObjectType(iterGameObjectType->first); + if (GameObjectTypes::isSubType(gameObjectType)) + { + baseGameObjectType = GameObjectTypes::getMaskedType(gameObjectType); + + snprintf(buffer, sizeof(buffer)-1, "numItems.0x%08X_%s.0x%08X_%s", baseGameObjectType, GameObjectTypes::getCanonicalName(baseGameObjectType).c_str(), gameObjectType, iterGameObjectType->first.c_str()); + buffer[sizeof(buffer)-1] = '\0'; + } + else + { + snprintf(buffer, sizeof(buffer)-1, "numItems.0x%08X_%s", gameObjectType, iterGameObjectType->first.c_str()); + buffer[sizeof(buffer)-1] = '\0'; + } + + m_mapAuctionsCountByGameObjectTypeIndex[iterGameObjectType->first] = addMetric(buffer, 0, NULL, false, false); + } + } + } + + for (std::set::const_iterator iterChanged = auctionsCountByGameObjectTypeChanged.begin(); iterChanged != auctionsCountByGameObjectTypeChanged.end(); ++iterChanged) + { + std::map::const_iterator const iterFindIndex = m_mapAuctionsCountByGameObjectTypeIndex.find(*iterChanged); + if (iterFindIndex != m_mapAuctionsCountByGameObjectTypeIndex.end()) + { + std::map::const_iterator const iterFindGameObjectType = auctionsCountByGameObjectType.find(*iterChanged); + if (iterFindGameObjectType != auctionsCountByGameObjectType.end()) + { + updateMetric(iterFindIndex->second, iterFindGameObjectType->second); + } + } + } + + auctionsCountByGameObjectTypeChanged.clear(); + } +} + +// ====================================================================== diff --git a/engine/server/application/CommoditiesServer/src/shared/CommodityServerMetricsData.h b/engine/server/application/CommoditiesServer/src/shared/CommodityServerMetricsData.h new file mode 100644 index 00000000..c578b91d --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/CommodityServerMetricsData.h @@ -0,0 +1,38 @@ +//CommodityServerMetricsData.h +//Copyright 2002 Sony Online Entertainment + + +#ifndef _CommodityServerMetricsData_H +#define _CommodityServerMetricsData_H + +//----------------------------------------------------------------------- + +#include "serverMetrics/MetricsData.h" + +//----------------------------------------------------------------------- + +class CommodityServerMetricsData : public MetricsData +{ +public: + CommodityServerMetricsData(); + ~CommodityServerMetricsData(); + + virtual void updateData(); + +private: + unsigned long m_numItems; + unsigned long m_numLocations; + unsigned long m_loadTime; + + std::map m_mapAuctionsCountByGameObjectTypeIndex; + +private: + + // Disabled. + CommodityServerMetricsData(const CommodityServerMetricsData&); + CommodityServerMetricsData &operator =(const CommodityServerMetricsData&); +}; + + +//----------------------------------------------------------------------- +#endif diff --git a/engine/server/application/CommoditiesServer/src/shared/ConfigCommodityServer.cpp b/engine/server/application/CommoditiesServer/src/shared/ConfigCommodityServer.cpp new file mode 100644 index 00000000..8e73017b --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/ConfigCommodityServer.cpp @@ -0,0 +1,72 @@ +// ====================================================================== +// +// ConfigCommodityServer.cpp +// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved. +// Author: Doug Mellencamp +// +// ====================================================================== + +//----------------------------------------------------------------------- + +#include "FirstCommodityServer.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedNetwork/SetupSharedNetwork.h" +#include "ConfigCommodityServer.h" + +//----------------------------------------------------------------------- + +ConfigCommodityServer::Data * ConfigCommodityServer::data = 0; + +#define KEY_INT(a,b) (data->a = ConfigFile::getKeyInt("CommodityServer", #a, b)) +#define KEY_BOOL(a,b) (data->a = ConfigFile::getKeyBool("CommodityServer", #a, b)) +#define KEY_FLOAT(a,b) (data->a = ConfigFile::getKeyFloat("CommodityServer", #a, b)) +#define KEY_STRING(a,b) (data->a = ConfigFile::getKeyString("CommodityServer", #a, b)) + +//----------------------------------------------------------------------- + +void ConfigCommodityServer::install(void) +{ + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + + data = new ConfigCommodityServer::Data; + + KEY_INT (cmServerServiceBindPort, 4069); + KEY_STRING (cmServerServiceBindInterface, "localhost"); + KEY_INT (databaseServerPort, 44457); //TODO: confirm port + KEY_STRING (databaseServerAddress, "localhost"); + KEY_STRING (dsn,"swodb"); + KEY_STRING (databaseUID,"dmellencamp"); + KEY_STRING (databasePWD, "compts6m"); + KEY_STRING (databaseSchema, "dmellencamp"); + KEY_INT (secondsBetweenDBReconnect, 45); + KEY_STRING (databaseProtocol, "OCI"); + KEY_BOOL (enableQueryProfile,false); + KEY_BOOL (verboseQueryMode,false); + KEY_BOOL (developmentMode, true); + KEY_INT (databaseThreads, 1); + KEY_INT (databaseCharacterNameSizeLimit, 64); + KEY_INT (databaseItemNameSizeLimit, 256); + KEY_INT (databaseUserDescriptionSizeLimit, 1024); + KEY_INT (databaseOOBDataSizeLimit, 4000); + KEY_BOOL (snapshotDBWrite, true); + KEY_BOOL (showAllDebugInfo, true); + KEY_INT (centralServerPort, 44456); + KEY_STRING (centralServerAddress, "localhost"); + KEY_INT (sleepTimePerFrameMs, 1); + KEY_INT (minutesActiveToUnaccessed, 7 * 24 * 60); + KEY_INT (minutesEmptyToEndangered, 7 * 24 * 60); + KEY_INT (minutesUnaccessedToEndangered, 7 * 24 * 60); + KEY_INT (minutesEndangeredToRemoved, 7 * 24 * 60); + KEY_INT (minutesVendorAuctionTimer, 30 * 24 * 60); + KEY_INT (minutesVendorItemTimer, 30 * 24 * 60); + KEY_INT (maxAuctionsPerPage, 100); +} + +//----------------------------------------------------------------------- + +void ConfigCommodityServer::remove(void) +{ + delete data; + data = 0; +} diff --git a/engine/server/application/CommoditiesServer/src/shared/ConfigCommodityServer.h b/engine/server/application/CommoditiesServer/src/shared/ConfigCommodityServer.h new file mode 100644 index 00000000..9bdff873 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/ConfigCommodityServer.h @@ -0,0 +1,299 @@ +// ====================================================================== +// +// ConfigCommodityServer.h +// Copyright 2004, Sony Online Entertainment Inc., all rights reserved. +// Author: Doug Mellencamp +// +// ====================================================================== + +#ifndef _ConfigCommodityServer_H +#define _ConfigCommodityServer_H + +//----------------------------------------------------------------------- + +class ConfigCommodityServer +{ + public: + struct Data + { + int cmServerServiceBindPort; + const char * cmServerServiceBindInterface; + int databaseServerPort; + const char * databaseServerAddress; + const char * dsn; + const char * databaseUID; + const char * databasePWD; + const char * databaseSchema; + int secondsBetweenDBReconnect; + const char * databaseProtocol; + bool enableQueryProfile; + bool verboseQueryMode; + bool developmentMode; + int databaseThreads; // db task q threads + int databaseCharacterNameSizeLimit; // max character name db column size + int databaseItemNameSizeLimit; // max item name db column size + int databaseUserDescriptionSizeLimit; // max user desc db column size + int databaseOOBDataSizeLimit; // max out of band data db column size + bool snapshotDBWrite; // save db writes delayed or immediate + bool showAllDebugInfo; // show detailed debugging logging info + int centralServerPort; + const char * centralServerAddress; + int sleepTimePerFrameMs; + int minutesActiveToUnaccessed; + int minutesEmptyToEndangered; + int minutesUnaccessedToEndangered; + int minutesEndangeredToRemoved; + int minutesVendorAuctionTimer; + int minutesVendorItemTimer; + int maxAuctionsPerPage; + }; + + static uint16 getCMServerServiceBindPort (); + static const char * getCMServerServiceBindInterface (); + static uint16 getDatabaseServerPort (); + static const char * getDatabaseServerAddress (); + static const char * getDSN (); + static const char * getDatabaseUID (); + static const char * getDatabasePWD (); + static const char * getDatabaseSchema (); + static uint16 getSecondsBetweenDBReconnect (); + static const char * getDatabaseProtocol (); + static bool getEnableQueryProfile (); + static bool getVerboseQueryMode (); + static bool getDevelopmentMode (); + static int getDatabaseThreads (); + static unsigned int getDatabaseCharacterNameSizeLimit (); + static unsigned int getDatabaseItemNameSizeLimit (); + static unsigned int getDatabaseUserDescriptionSizeLimit (); + static unsigned int getDatabaseOOBDataSizeLimit (); + static bool getSnapshotDBWrite (); + static bool getShowAllDebugInfo (); + static uint16 getCentralServerPort (); + static const char * getCentralServerAddress (); + static int getSleepTimePerFrameMs (); + static int getMinutesActiveToUnaccessed (); + static int getMinutesEmptyToEndangered (); + static int getMinutesUnaccessedToEndangered (); + static int getMinutesEndangeredToRemoved (); + static int getMinutesVendorAuctionTimer (); + static int getMinutesVendorItemTimer (); + static int getMaxAuctionsPerPage (); + + static void install (); + static void remove (); + + private: + static Data * data; +}; + +//----------------------------------------------------------------------- + +inline unsigned short ConfigCommodityServer::getCMServerServiceBindPort() +{ + return data->cmServerServiceBindPort; +} + +//----------------------------------------------------------------------- + +inline unsigned short ConfigCommodityServer::getDatabaseServerPort() +{ + return data->databaseServerPort; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCommodityServer::getCMServerServiceBindInterface() +{ + return data->cmServerServiceBindInterface; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCommodityServer::getDatabaseServerAddress() +{ + return data->databaseServerAddress; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCommodityServer::getDSN() +{ + return data->dsn; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCommodityServer::getDatabaseUID() +{ + return data->databaseUID; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCommodityServer::getDatabasePWD() +{ + return data->databasePWD; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCommodityServer::getDatabaseSchema() +{ + return data->databaseSchema; +} + +//----------------------------------------------------------------------- + +inline unsigned short ConfigCommodityServer::getSecondsBetweenDBReconnect() +{ + return data->secondsBetweenDBReconnect; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCommodityServer::getDatabaseProtocol() +{ + return (data->databaseProtocol); +} + +//----------------------------------------------------------------------- + +inline bool ConfigCommodityServer::getEnableQueryProfile() +{ + return (data->enableQueryProfile); +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCommodityServer::getVerboseQueryMode() +{ + return (data->verboseQueryMode); +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCommodityServer::getDevelopmentMode() +{ + return (data->developmentMode); +} + +// ---------------------------------------------------------------------- + +inline int ConfigCommodityServer::getDatabaseThreads() +{ + return (data->databaseThreads); +} + +// ---------------------------------------------------------------------- + +inline unsigned int ConfigCommodityServer::getDatabaseCharacterNameSizeLimit() +{ + return (data->databaseCharacterNameSizeLimit); +} + +// ---------------------------------------------------------------------- + +inline unsigned int ConfigCommodityServer::getDatabaseItemNameSizeLimit() +{ + return (data->databaseItemNameSizeLimit); +} + +// ---------------------------------------------------------------------- + +inline unsigned int ConfigCommodityServer::getDatabaseUserDescriptionSizeLimit() +{ + return (data->databaseUserDescriptionSizeLimit); +} + +// ---------------------------------------------------------------------- + +inline unsigned int ConfigCommodityServer::getDatabaseOOBDataSizeLimit() +{ + return (data->databaseOOBDataSizeLimit); +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCommodityServer::getSnapshotDBWrite() +{ + return (data->snapshotDBWrite); +} + +// ---------------------------------------------------------------------- + +inline bool ConfigCommodityServer::getShowAllDebugInfo() +{ + return (data->showAllDebugInfo); +} + +//----------------------------------------------------------------------- + +inline unsigned short ConfigCommodityServer::getCentralServerPort() +{ + return data->centralServerPort; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigCommodityServer::getCentralServerAddress() +{ + return data->centralServerAddress; +} + +//----------------------------------------------------------------------- + +inline int ConfigCommodityServer::getSleepTimePerFrameMs() +{ + return data->sleepTimePerFrameMs; +} + +//----------------------------------------------------------------------- + +inline int ConfigCommodityServer::getMinutesActiveToUnaccessed() +{ + return data->minutesActiveToUnaccessed; +} + +//----------------------------------------------------------------------- + +inline int ConfigCommodityServer::getMinutesEmptyToEndangered() +{ + return data->minutesEmptyToEndangered; +} + +//----------------------------------------------------------------------- + +inline int ConfigCommodityServer::getMinutesUnaccessedToEndangered() +{ + return data->minutesUnaccessedToEndangered; +} + +//----------------------------------------------------------------------- + +inline int ConfigCommodityServer::getMinutesEndangeredToRemoved() +{ + return data->minutesEndangeredToRemoved; +} + +//----------------------------------------------------------------------- + +inline int ConfigCommodityServer::getMinutesVendorAuctionTimer() +{ + return data->minutesVendorAuctionTimer; +} + +//----------------------------------------------------------------------- + +inline int ConfigCommodityServer::getMinutesVendorItemTimer() +{ + return data->minutesVendorItemTimer; +} + +//----------------------------------------------------------------------- + +inline int ConfigCommodityServer::getMaxAuctionsPerPage() +{ + return data->maxAuctionsPerPage; +} + +#endif // _ConfigCommodityServer_H diff --git a/engine/server/application/CommoditiesServer/src/shared/DatabaseServerConnection.cpp b/engine/server/application/CommoditiesServer/src/shared/DatabaseServerConnection.cpp new file mode 100644 index 00000000..25b6029e --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/DatabaseServerConnection.cpp @@ -0,0 +1,218 @@ +// DatabaseServerConnection.cpp +// copyright 2000 Verant Interactive +// Author: Justin Randall + + +//----------------------------------------------------------------------- + +#include "FirstCommodityServer.h" +#include "DatabaseServerConnection.h" +#include "ConfigCommodityServer.h" +#include "AuctionMarket.h" +#include "sharedLog/Log.h" +#include "CommodityServer.h" +#include "sharedNetwork/NetworkSetupData.h" +#include "sharedNetworkMessages/GameNetworkMessage.h" +#include "sharedNetworkMessages/DeleteCharacterMessage.h" +#include "serverNetworkMessages/CommoditiesLoadDoneMessage.h" +#include "serverNetworkMessages/GetAuctionLocationsMessage.h" +#include "serverNetworkMessages/GetMarketAuctionsMessage.h" +#include "serverNetworkMessages/GetMarketAuctionAttributesMessage.h" +#include "serverNetworkMessages/GetMarketAuctionBidsMessage.h" +#include "UnicodeUtils.h" + +//----------------------------------------------------------------------- + +DatabaseServerConnection::DatabaseServerConnection(const std::string & a, const unsigned short p) : +ServerConnection(a, p, NetworkSetupData()) +{ + LOG("DatabaseServerConnection", ("Connection with the database server created")); +} + +//----------------------------------------------------------------------- + +DatabaseServerConnection::~DatabaseServerConnection() +{ +} + +//----------------------------------------------------------------------- + +void DatabaseServerConnection::onConnectionClosed() +{ + LOG("DatabaseServerConnection", ("Connection with the database server is closed")); + static MessageConnectionCallback m("DatabaseServerConnectionClosed"); + emitMessage(m); +} + +//----------------------------------------------------------------------- + +void DatabaseServerConnection::onConnectionOpened() +{ + LOG("DatabaseServerConnection", ("Connection with the database server is open")); + static MessageConnectionCallback m("DatabaseServerConnectionOpened"); + emitMessage(m); +} + +//----------------------------------------------------------------------- + +void DatabaseServerConnection::onReceive(const Archive::ByteStream & message) +{ + static int lastLocationCount = 0, currentLocationCount = 0; + static int lastAuctionCount = 0, currentAuctionCount = 0; + static int lastAuctionAttributeCount = 0, currentAuctionAttributeCount = 0; + static int lastBidCount = 0, currentBidCount = 0; + + Archive::ReadIterator ri = message.begin(); + GameNetworkMessage msg(ri); + ri = message.begin(); + + if (msg.isType("CommoditiesLoadDone")) + { + if (currentLocationCount != lastLocationCount) + { + DEBUG_REPORT_LOG(true, (" -- %d AuctionLocations record received\n", currentLocationCount)); + LOG("CommoditiesServer", ("%d AuctionLocations record received\n", currentLocationCount)); + lastLocationCount = currentLocationCount; + } + if (currentAuctionCount != lastAuctionCount) + { + DEBUG_REPORT_LOG(true, (" -- %d MarketAuctions record received\n", currentAuctionCount)); + LOG("CommoditiesServer", ("%d MarketAuctions record received\n", currentAuctionCount)); + lastAuctionCount = currentAuctionCount; + } + if (currentAuctionAttributeCount != lastAuctionAttributeCount) + { + DEBUG_REPORT_LOG(true, (" -- %d MarketAuctionAttributes record received\n", currentAuctionAttributeCount)); + LOG("CommoditiesServer", ("%d MarketAuctionAttributes record received\n", currentAuctionAttributeCount)); + lastAuctionAttributeCount = currentAuctionAttributeCount; + } + if (currentBidCount != lastBidCount) + { + DEBUG_REPORT_LOG(true, (" -- %d MarketAuctionBids record received\n", currentBidCount)); + LOG("CommoditiesServer", ("%d MarketAuctionBids record received", currentBidCount)); + lastBidCount = currentBidCount; + } + REPORT_LOG("DatabaseServerConnection", ("CommoditiesLoadDone Message received on connection with the database server\n")); + CommoditiesLoadDoneMessage m(ri); + REPORT_LOG("DatabaseServerConnection", ("%d rows received on Auction_Locations\n", m.getAuctionLocationsCount())); + REPORT_LOG("DatabaseServerConnection", ("%d rows received on Market_Auctions\n", m.getMarketAuctionsCount())); + REPORT_LOG("DatabaseServerConnection", ("%d rows received on Market_Auction_Attributes\n", m.getMarketAuctionAttributesCount())); + REPORT_LOG("DatabaseServerConnection", ("%d rows received on Market_Auction_Bids\n", m.getMarketAuctionBidsCount())); + LOG("CommoditiesServer", ("CommoditiesLoadDone Message received, %d rows Auction_Locations, %d rows Market_Auctions, %d rows Market_Auction_Attributes, %d rows Market_Auction_Bids", m.getAuctionLocationsCount(), m.getMarketAuctionsCount(), m.getMarketAuctionAttributesCount(), m.getMarketAuctionBidsCount())); + + LOG("CommoditiesServer", ("Start build index for attribute search")); + AuctionMarket::getInstance().BuildAuctionsSearchableAttributeList(); + LOG("CommoditiesServer", ("End build index for attribute search")); + + emitMessage(m); + } + else if (msg.isType("GetAuctionLocationsMessage")) + { + GetAuctionLocationsMessage m(ri); + const std::list & auctionLocations = m.getAuctionLocations(); + for (std::list::const_iterator iter = auctionLocations.begin(); iter != auctionLocations.end(); ++iter) + { + AuctionMarket::getInstance().onReceiveAuctionLocations(iter->locationId, iter->locationName, iter->ownerId, iter->salesTax, iter->salesTaxBankId, iter->emptyDate, iter->lastAccessDate, iter->inactiveDate, iter->status, iter->searchEnabled, iter->entranceCharge); + currentLocationCount++; + if (currentLocationCount - lastLocationCount >= 1000) + { + DEBUG_REPORT_LOG(true, (" -- %d AuctionLocations record received\n", currentLocationCount)); + LOG("CommoditiesServer", ("%d AuctionLocations record received", currentLocationCount)); + lastLocationCount = currentLocationCount; + } + } + } + else if (msg.isType("GetMarketAuctionsMessage")) + { + if (currentLocationCount != lastLocationCount) + { + DEBUG_REPORT_LOG(true, (" -- %d AuctionLocations record received\n", currentLocationCount)); + LOG("CommoditiesServer", ("%d AuctionLocations record received\n", currentLocationCount)); + lastLocationCount = currentLocationCount; + } + GetMarketAuctionsMessage m(ri); + const std::list & auctions = m.getAuctions(); + for (std::list::const_iterator iter = auctions.begin(); iter != auctions.end(); ++iter) + { + AuctionMarket::getInstance().onReceiveMarketAuctions(iter->itemId, iter->ownerId, iter->creatorId, iter->locationId, iter->minBid, iter->buyNowPrice, iter->auctionTimer, iter->oob, iter->userDescription, iter->category, iter->itemTemplateId, iter->itemName, iter->itemTimer, iter->active, iter->itemSize); + currentAuctionCount++; + if (currentAuctionCount - lastAuctionCount >= 10000) + { + DEBUG_REPORT_LOG(true, (" -- %d MarketAuctions record received\n", currentAuctionCount)); + LOG("CommoditiesServer", ("%d MarketAuctions record received", currentAuctionCount)); + lastAuctionCount = currentAuctionCount; + } + } + } + else if (msg.isType("GetMarketAuctionAttributesMessage")) + { + if (currentLocationCount != lastLocationCount) + { + DEBUG_REPORT_LOG(true, (" -- %d AuctionLocations record received\n", currentLocationCount)); + LOG("CommoditiesServer", ("%d AuctionLocations record received\n", currentLocationCount)); + lastLocationCount = currentLocationCount; + } + if (currentAuctionCount != lastAuctionCount) + { + DEBUG_REPORT_LOG(true, (" -- %d MarketAuctions record received\n", currentAuctionCount)); + LOG("CommoditiesServer", ("%d MarketAuctions record received\n", currentAuctionCount)); + lastAuctionCount = currentAuctionCount; + } + GetMarketAuctionAttributesMessage m(ri); + const std::list & attributes = m.getAttributes(); + for (std::list::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) + { + AuctionMarket::getInstance().onReceiveMarketAuctionAttributes(iter->itemId, iter->attributeName, iter->attributeValue); + currentAuctionAttributeCount++; + if (currentAuctionAttributeCount - lastAuctionAttributeCount >= 10000) + { + DEBUG_REPORT_LOG(true, (" -- %d MarketAuctionAttributes record received\n", currentAuctionAttributeCount)); + LOG("CommoditiesServer", ("%d MarketAuctionAttributes record received", currentAuctionAttributeCount)); + lastAuctionAttributeCount = currentAuctionAttributeCount; + } + } + } + else if (msg.isType("GetMarketAuctionBidsMessage")) + { + if (currentLocationCount != lastLocationCount) + { + DEBUG_REPORT_LOG(true, (" -- %d AuctionLocations record received\n", currentLocationCount)); + LOG("CommoditiesServer", ("%d AuctionLocations record received\n", currentLocationCount)); + lastLocationCount = currentLocationCount; + } + if (currentAuctionCount != lastAuctionCount) + { + DEBUG_REPORT_LOG(true, (" -- %d MarketAuctions record received\n", currentAuctionCount)); + LOG("CommoditiesServer", ("%d MarketAuctions record received\n", currentAuctionCount)); + lastAuctionCount = currentAuctionCount; + } + if (currentAuctionAttributeCount != lastAuctionAttributeCount) + { + DEBUG_REPORT_LOG(true, (" -- %d MarketAuctionAttributes record received\n", currentAuctionAttributeCount)); + LOG("CommoditiesServer", ("%d MarketAuctionAttributes record received\n", currentAuctionAttributeCount)); + lastAuctionAttributeCount = currentAuctionAttributeCount; + } + GetMarketAuctionBidsMessage m(ri); + const std::list & bids = m.getMarketAuctionBids(); + for (std::list::const_iterator iter = bids.begin(); iter != bids.end(); ++iter) + { + AuctionMarket::getInstance().onReceiveMarketAuctionBids(iter->itemId, iter->bidderId, iter->bid, iter->maxProxyBid); + currentBidCount++; + if (currentBidCount - lastBidCount >= 1000) + { + DEBUG_REPORT_LOG(true, (" -- %d MarketAuctionBids record received\n", currentBidCount)); + LOG("CommoditiesServer", ("%d MarketAuctionBids record received\n", currentBidCount)); + lastBidCount = currentBidCount; + } + } + } + else if(msg.isType("DeleteCharacterMessage")) + { + DeleteCharacterMessage message(ri); + AuctionMarket::getInstance().DeleteCharacter(message); + } +} + +//----------------------------------------------------------------------- + + diff --git a/engine/server/application/CommoditiesServer/src/shared/DatabaseServerConnection.h b/engine/server/application/CommoditiesServer/src/shared/DatabaseServerConnection.h new file mode 100644 index 00000000..4359f9f9 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/DatabaseServerConnection.h @@ -0,0 +1,34 @@ +// DatabaseServerConnection.h +// copyright 2001 Verant Interactive +// Author: Justin Randall + +#ifndef _DatabaseServerConnection_H +#define _DatabaseServerConnection_H + +//----------------------------------------------------------------------- + +#include "serverUtility/ServerConnection.h" + +//----------------------------------------------------------------------- + +class DatabaseServerConnection : public ServerConnection +{ +public: + DatabaseServerConnection(const std::string & remoteAddress, const unsigned short remotePort); + ~DatabaseServerConnection(); + + void onConnectionClosed(); + void onConnectionOpened(); + void onReceive(const Archive::ByteStream & message); + +private: + DatabaseServerConnection(const DatabaseServerConnection&); + DatabaseServerConnection& operator= (const DatabaseServerConnection&); + +}; //lint !e1712 default constructor not defined + +//----------------------------------------------------------------------- + +#endif // _DatabaseServerConnection_H + + diff --git a/engine/server/application/CommoditiesServer/src/shared/FirstCommodityServer.h b/engine/server/application/CommoditiesServer/src/shared/FirstCommodityServer.h new file mode 100644 index 00000000..7886976a --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/FirstCommodityServer.h @@ -0,0 +1,19 @@ +// ====================================================================== +// +// FirstCommodityServer.h +// copyright (c) 2004 Sony Online Entertainment +// +// This is file contains the requires include to use any of the shared foundation +// libs in the Commodities server +// ====================================================================== + +#ifndef _INCLUDED_FirstCommodityServer_H +#define _INCLUDED_FirstCommodityServer_H + +//----------------------------------------------------------------------- + +#include "sharedFoundation/FirstSharedFoundation.h" + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_FirstCommodityServer_H diff --git a/engine/server/application/CommoditiesServer/src/shared/GameServerConnection.cpp b/engine/server/application/CommoditiesServer/src/shared/GameServerConnection.cpp new file mode 100644 index 00000000..21b13a20 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/GameServerConnection.cpp @@ -0,0 +1,289 @@ +// ====================================================================== +// +// ConfigCommodityServer.h +// Copyright 2004, Sony Online Entertainment Inc., all rights reserved. +// Author: Doug Mellencamp +// Server Infrastructure by: Justin Randall +// +// This is message handler for incoming gameserver messages. +// +// ====================================================================== + +#include "FirstCommodityServer.h" +#include "CommodityServer.h" +#include "GameServerConnection.h" +#include "AuctionMarket.h" +#include "ConfigCommodityServer.h" +#include "sharedNetworkMessages/GameNetworkMessage.h" +#include "serverNetworkMessages/AcceptHighBidMessage.h" +#include "serverNetworkMessages/AddAuctionMessage.h" +#include "serverNetworkMessages/AddBidMessage.h" +#include "serverNetworkMessages/AddImmediateAuctionMessage.h" +#include "serverNetworkMessages/CancelAuctionMessage.h" +#include "serverNetworkMessages/CreateVendorMarketMessage.h" +#include "serverNetworkMessages/DeleteAuctionLocationMessage.h" +#include "serverNetworkMessages/DestroyVendorMarketMessage.h" +#include "serverNetworkMessages/GetItemDetailsMessage.h" +#include "serverNetworkMessages/GetItemMessage.h" +#include "serverNetworkMessages/SetSalesTaxMessage.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "serverNetworkMessages/GetPlayerVendorCountMessage.h" +#include "serverNetworkMessages/GetVendorOwnerMessage.h" +#include "serverNetworkMessages/GetVendorValueMessage.h" +#include "serverNetworkMessages/QueryAuctionHeadersMessage.h" +#include "serverNetworkMessages/SetGameTimeMessage.h" +#include "serverNetworkMessages/CleanupInvalidItemRetrievalMessage.h" +#include "serverNetworkMessages/QueryVendorItemCountMessage.h" +#include "serverNetworkMessages/UpdateVendorStatusMessage.h" + +//----------------------------------------------------------------------- + +namespace GameServerConnectionNamespace +{ +} + +using namespace GameServerConnectionNamespace; + + +//----------------------------------------------------------------------- + +GameServerConnection::GameServerConnection(UdpConnectionMT * u, TcpClient * t) : +ServerConnection(u, t), +m_gameServerId(0), +m_showAllDebugInfo(ConfigCommodityServer::getShowAllDebugInfo()) +{ +} + +//----------------------------------------------------------------------- + +GameServerConnection::~GameServerConnection() +{ +} + +//----------------------------------------------------------------------- + +void GameServerConnection::onConnectionClosed() +{ + //REPORT_LOG("GameServerConnection", ("Connection with GameServer has closed\n")); + + CommodityServer::getInstance().removeGameServer(m_gameServerId); + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Game Server %d disconnected\n", m_gameServerId)); +} + +//----------------------------------------------------------------------- + +void GameServerConnection::onConnectionOpened() +{ + m_gameServerId = CommodityServer::getInstance().addGameServer(*this); + //setOverflowLimit(ConfigLoginServer::getClientOverflowLimit()); + + DEBUG_REPORT_LOG(true, ("[Commodities Server] : Game Server %d opened connection.\n", m_gameServerId)); +} + +//----------------------------------------------------------------------- + +void GameServerConnection::onReceive(const Archive::ByteStream & message) +{ + + Archive::ReadIterator ri = message.begin(); + GameNetworkMessage msg(ri); + ri = message.begin(); + + if(msg.isType("AcceptHighBidMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message AcceptHighBidMessage from game server id: %d.\n", m_gameServerId )); + AcceptHighBidMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().AcceptHighBid(message); + } + else if(msg.isType("AddAuctionMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message AddAuctionMessage from game server id: %d.\n", m_gameServerId )); + AddAuctionMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().AddAuction(message); + } + else if(msg.isType("AddBidMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message AddBidMessage from game server id: %d.\n", m_gameServerId )); + AddBidMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().AddBid(message); + } + else if(msg.isType("AddImmediateAuctionMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message AddImmediateAuctionMessage from game server id: %d.\n", m_gameServerId )); + AddImmediateAuctionMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().AddImmediateAuction(message); + } + else if(msg.isType("CancelAuctionMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message CancelAuctionMessage from game server id: %d.\n", m_gameServerId )); + CancelAuctionMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().CancelAuction(message); + } + else if(msg.isType("CreateVendorMarketMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message CreateVendorMarketMessage from game server id: %d.\n", m_gameServerId )); + CreateVendorMarketMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().CreateVendorMarket(message); + } + else if(msg.isType("DestroyVendorMarketMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message DestroyVendorMarketMessage from game server id: %d.\n", m_gameServerId )); + DestroyVendorMarketMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().DestroyVendorMarket(message); + } + else if(msg.isType("DeleteAuctionLocationMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message DeleteAuctionLocationMessage from game server id: %d.\n", m_gameServerId )); + DeleteAuctionLocationMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().DeleteAuctionLocation(message); + } + else if(msg.isType("GetItemDetailsMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message GetItemDetailsMessage from game server id: %d.\n", m_gameServerId )); + GetItemDetailsMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().GetItemDetails(message); + } + else if(msg.isType("GetItemMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message GetItemMessage from game server id: %d.\n", m_gameServerId )); + GetItemMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().GetItem(message); + } + else if(msg.isType("SetSalesTaxMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message SetSalesTaxMessage from game server id: %d.\n", m_gameServerId )); + SetSalesTaxMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().SetSalesTax(message); + } + else if(msg.isType("GetVendorOwnerMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message GetVendorOwnerMessage from game server id: %d.\n", m_gameServerId )); + GetVendorOwnerMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().GetVendorOwner(message); + } + else if(msg.isType("GetVendorValueMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message GetVendorValueMessage from game server id: %d.\n", m_gameServerId )); + GetVendorValueMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().GetVendorValue(message); + } + else if(msg.isType("QueryAuctionHeadersMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message QueryAuctionHeadersMessage from game server id: %d.\n", m_gameServerId )); + QueryAuctionHeadersMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().QueryAuctionHeaders(message); + } + else if(msg.isType("SetGameTimeMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message SetGameTimeMessage from game server id: %d.\n", m_gameServerId )); + SetGameTimeMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().SetGameTime(message); + } + else if(msg.isType("CleanupInvalidItemRetrievalMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message CleanupInvalidItemRetrievalMessage from game server id: %d.\n", m_gameServerId )); + CleanupInvalidItemRetrievalMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().CleanupInvalidItemRetrieval(message); + } + else if(msg.isType("QueryVendorItemCountMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message QueryVendorItemCountMessage from game server id: %d.\n", m_gameServerId )); + QueryVendorItemCountMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().QueryVendorItemCount(message); + } + else if(msg.isType("GetPlayerVendorCountMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message GetPlayerVendorCountMessage from game server id: %d.\n", m_gameServerId )); + GetPlayerVendorCountMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().GetPlayerVendorCount(message); + } + else if(msg.isType("UpdateVendorSearchOptionMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message UpdateVendorSearchOptionMessage from game server id: %d.\n", m_gameServerId )); + UpdateVendorSearchOptionMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().UpdateVendorSearchOption(message); + } + else if(msg.isType("SetEntranceChargeMessage")) + { + DEBUG_REPORT_LOG(/*m_showAllDebugInfo*/ true, ("[Commodities Server] : Received message SetEntranceChargeMessage from game server id: %d.\n", m_gameServerId )); + SetEntranceChargeMessage message(ri); + message.SetTrackId(m_gameServerId); + AuctionMarket::getInstance().SetEntranceCharge(message); + } + else if(msg.isType("ResponseCommoditiesExcludedGotTypes")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message ResponseCommoditiesExcludedGotTypes from game server id: %d.\n", m_gameServerId )); + GenericValueTypeMessage > message(ri); + AuctionMarket::getInstance().VerifyExcludedGotTypes(message.getValue()); + } + else if(msg.isType("ResponseCommoditiesExcludedResourceClasses")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message ResponseCommoditiesExcludedResourceClasses from game server id: %d.\n", m_gameServerId )); + GenericValueTypeMessage > message(ri); + AuctionMarket::getInstance().VerifyExcludedResourceClasses(message.getValue()); + } + else if(msg.isType("ResponseResourceTreeHierarchy")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message ResponseResourceTreeHierarchy from game server id: %d.\n", m_gameServerId )); + GenericValueTypeMessage > > message(ri); + AuctionMarket::getInstance().SetResourceTreeHierarchy(message.getValue()); + } + else if(msg.isType("UpdateVendorStatusMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message UpdateVendorStatusMessage from game server id: %d.\n", m_gameServerId)); + UpdateVendorStatusMessage message(ri); + AuctionMarket::getInstance().UpdateVendorStatus(message); + } + else if(msg.isType("UpdateVendorLocationMessage")) + { + DEBUG_REPORT_LOG(m_showAllDebugInfo, ("[Commodities Server] : Received message UpdateVendorLocationMessage from game server id: %d.\n", m_gameServerId)); + GenericValueTypeMessage > const message(ri); + AuctionMarket::getInstance().UpdateVendorLocation(message.getValue().first, message.getValue().second); + } + else if(msg.isType("GetItemAttributeData")) + { + GenericValueTypeMessage, std::pair, std::pair > > > const message(ri); + AuctionMarket::getInstance().getItemAttributeData(m_gameServerId, message.getValue().first.first, message.getValue().first.second, message.getValue().second.first.first, message.getValue().second.first.second, message.getValue().second.second.first, message.getValue().second.second.second); + } + else if(msg.isType("GetItemAttributeDataValues")) + { + GenericValueTypeMessage >, std::pair > > const message(ri); + AuctionMarket::getInstance().getItemAttributeDataValues(m_gameServerId, message.getValue().first.first, message.getValue().first.second.first, message.getValue().first.second.second, message.getValue().second.first, message.getValue().second.second); + } + else if(msg.isType("GetItemAttribute")) + { + GenericValueTypeMessage > const message(ri); + AuctionMarket::getInstance().getItemAttribute(m_gameServerId, message.getValue().first, message.getValue().second); + } + else if(msg.isType("GetVendorInfoForPlayer")) + { + GenericValueTypeMessage, bool> > const message(ri); + AuctionMarket::getInstance().getVendorInfoForPlayer(m_gameServerId, message.getValue().first.first, message.getValue().first.second, message.getValue().second); + } + else if(msg.isType("GetALPQ")) + { + GenericValueTypeMessage > const message(ri); + AuctionMarket::getInstance().getAuctionLocationPriorityQueue(m_gameServerId, message.getValue().first, message.getValue().second); + } +} + +//----------------------------------------------------------------------- diff --git a/engine/server/application/CommoditiesServer/src/shared/GameServerConnection.h b/engine/server/application/CommoditiesServer/src/shared/GameServerConnection.h new file mode 100644 index 00000000..37327db5 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/GameServerConnection.h @@ -0,0 +1,41 @@ +// ====================================================================== +// +// ConfigCommodityServer.h +// Copyright 2004, Sony Online Entertainment Inc., all rights reserved. +// Author: Doug Mellencamp +// Server Infrastructure by: Justin Randall +// +// This is message handler for incoming gameserver messages. +// +// ====================================================================== + +#ifndef _INCLUDED_GameServerConnection_H +#define _INCLUDED_GameServerConnection_H + + +#include "serverUtility/ServerConnection.h" + +// ====================================================================== + +class GameServerConnection : public ServerConnection +{ +public: + GameServerConnection(UdpConnectionMT *, TcpClient * t); + ~GameServerConnection(); + + virtual void onConnectionClosed (); + virtual void onConnectionOpened (); + virtual void onReceive (const Archive::ByteStream & message); + +private: + int m_gameServerId; + bool m_showAllDebugInfo; + + GameServerConnection(); + GameServerConnection & operator = (const GameServerConnection & rhs); + GameServerConnection(const GameServerConnection & source); +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_GameServerConnection_H diff --git a/engine/server/application/CommoditiesServer/src/shared/dBAuctionRecord.h b/engine/server/application/CommoditiesServer/src/shared/dBAuctionRecord.h new file mode 100644 index 00000000..57c9ca78 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/dBAuctionRecord.h @@ -0,0 +1,42 @@ +// ====================================================================== +// +// dBAuctionRecord.h +// copyright (c) 2004 Sony Online Entertainment +// Author: Doug Mellencamp +// +// ====================================================================== + + +#ifndef INCLUDED_dBAuctionRecord_H +#define INCLUDED_dBAuctionRecord_H + +// ====================================================================== + +#include "Unicode.h" +#include "sharedFoundation/NetworkId.h" + +// ====================================================================== + +/** + * Data structures for querying auctions. + */ +struct AuctionRecord +{ + NetworkId m_creatorId; + int m_minBid; + int m_auctionTimer; + int m_buyNowPrice; + Unicode::String m_userDescription; + std::string m_oob; + NetworkId m_locationId; + NetworkId m_itemId; + int m_category; + int m_itemTimer; + Unicode::String m_itemName; + NetworkId m_ownerId; + int m_active; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/CommoditiesServer/src/shared/dBBidRecord.h b/engine/server/application/CommoditiesServer/src/shared/dBBidRecord.h new file mode 100644 index 00000000..28cd5b75 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/dBBidRecord.h @@ -0,0 +1,37 @@ +// ====================================================================== +// +// dBBidRecord.h +// copyright (c) 2004 Sony Online Entertainment +// Author: Doug Mellencamp +// +// ====================================================================== + +#ifndef INCLUDED_dBBidRecord_H +#define INCLUDED_dBBidRecord_H + +// ====================================================================== + +#include "Unicode.h" +#include "sharedFoundation/NetworkId.h" + +// ====================================================================== + +/** + * Data structures for querying bids. + */ +struct BidRecord +{ + NetworkId m_bidId; + NetworkId m_itemId; + NetworkId m_bidderId; + int m_bid; + int m_maxProxyBid; +}; + +// ====================================================================== + +typedef stdvector::fwd BidList; + +// ====================================================================== + +#endif diff --git a/engine/server/application/CommoditiesServer/src/shared/database/auction_characters.tab b/engine/server/application/CommoditiesServer/src/shared/database/auction_characters.tab new file mode 100644 index 00000000..cdfa723b --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/database/auction_characters.tab @@ -0,0 +1,7 @@ +create table auction_characters +( + character_id number(20), + character_name varchar2(64), + constraint pk_auction_characters primary key (character_id) using index tablespace indexes +); +grant select on auction_characters to public; diff --git a/engine/server/application/CommoditiesServer/src/shared/database/auction_locations.tab b/engine/server/application/CommoditiesServer/src/shared/database/auction_locations.tab new file mode 100644 index 00000000..60ea5a17 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/database/auction_locations.tab @@ -0,0 +1,9 @@ +create table auction_locations +( + owner_id number(20), -- BIND_AS(DB::BindableNetworkId) + location_name varchar2(256), + constraint pk_auction_locations primary key (location_name) using index tablespace indexes, + sales_tax number(20), + sales_tax_bank_id number(20) +); +grant select on auction_locations to public; diff --git a/engine/server/application/CommoditiesServer/src/shared/database/auctions.tab b/engine/server/application/CommoditiesServer/src/shared/database/auctions.tab new file mode 100644 index 00000000..eb35a3d7 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/database/auctions.tab @@ -0,0 +1,18 @@ +create table auctions +( + creator_id number(20), + creator_name varchar2(64), + min_bid number(20), + auction_timer number(20), + buy_now_price number(20), + user_description varchar2(4000), + oob varchar2(4000), + location varchar2(256), + item_id number(20), + category number(20), + item_timer number(20), + item_name varchar2(4000), + owner_id number(20), + constraint pk_auctions primary key (item_id) using index tablespace indexes +); +grant select on auctions to public; diff --git a/engine/server/application/CommoditiesServer/src/shared/database/market_auction_bids.tab b/engine/server/application/CommoditiesServer/src/shared/database/market_auction_bids.tab new file mode 100644 index 00000000..9e80c446 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/database/market_auction_bids.tab @@ -0,0 +1,11 @@ +create table market_auction_bids +( + bid_id number(20), + item_id number(20), + bidder_id number(20), + bid number(20), + max_proxy_bid number(20), + constraint pk_market_auction_bids primary key (bid_id) using index tablespace indexes +); +grant select on market_auction_bids to public; +create index market_item_index on market_auction_bids (item_id) tablespace indexes; diff --git a/engine/server/application/CommoditiesServer/src/shared/database/market_auctions.tab b/engine/server/application/CommoditiesServer/src/shared/database/market_auctions.tab new file mode 100644 index 00000000..2c87e8e3 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/database/market_auctions.tab @@ -0,0 +1,18 @@ +create table market_auctions +( + creator_id number(20), + min_bid number(20), + auction_timer number(20), + buy_now_price number(20), + user_description varchar2(4000), + oob varchar2(4000), + location varchar2(256), + item_id number(20), + category number(20), + item_timer number(20), + item_name varchar2(4000), + owner_id number(20), + active number(20), + constraint pk_market_auctions primary key (item_id) using index tablespace indexes +); +grant select on market_auctions to public; diff --git a/engine/server/application/CommoditiesServer/src/shared/database/sp_swg_auctions.sql b/engine/server/application/CommoditiesServer/src/shared/database/sp_swg_auctions.sql new file mode 100644 index 00000000..f1cc1454 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/shared/database/sp_swg_auctions.sql @@ -0,0 +1,460 @@ +------------------------------------------------- +-- Export file for user AVALDES -- +-- Created by avaldes on 09-Jun-03, 2:15:33 PM -- +------------------------------------------------- + +spool sp_swg_auctions.log + +prompt +prompt Creating package SWG_COMMODITIES +prompt ================================ +prompt +create or replace package swg_commodities is + + -- Author : AVALDES + -- Created : 05-Jun-03 4:28:39 PM + -- Purpose : Stored Procedures for Star Wars Galaxies Commodities + + TYPE swg_cur IS REF CURSOR; + + FUNCTION create_auction + (creator_id_in IN market_auctions.creator_id%TYPE, + min_bid_in IN market_auctions.min_bid%TYPE, + auction_timer_in IN market_auctions.auction_timer%TYPE, + buy_now_price_in IN market_auctions.buy_now_price%TYPE, + location_in IN market_auctions.location%TYPE, + item_id_in IN market_auctions.item_id%TYPE, + category_in IN market_auctions.category%TYPE, + item_timer_in IN market_auctions.item_timer%TYPE, + owner_id_in IN market_auctions.owner_id%TYPE, + active_in IN market_auctions.active%TYPE, + auction_cur_out OUT swg_cur) + RETURN INTEGER; + -- + -- + -- + FUNCTION create_character + (character_id_in IN auction_characters.character_id%TYPE, + character_name_in IN auction_characters.character_name%TYPE) + RETURN INTEGER; + -- + -- + -- + FUNCTION delete_auction + (item_id_in IN market_auctions.item_id%TYPE) + RETURN INTEGER; + -- + -- + -- + FUNCTION delete_location + (location_in IN auction_locations.location_name%TYPE) + RETURN INTEGER; + -- + -- + -- + FUNCTION create_bid + (bid_id_in IN market_auction_bids.bid_id%TYPE, + item_id_in IN market_auction_bids.item_id%TYPE, + bidder_id_in IN market_auction_bids.bidder_id%TYPE, + bid_in IN market_auction_bids.bid%TYPE, + max_proxy_bid_in IN market_auction_bids.max_proxy_bid%TYPE) + RETURN INTEGER; + -- + -- + -- + FUNCTION create_location + (owner_id_in IN auction_locations.owner_id%TYPE, + location_name_in IN auction_locations.location_name%TYPE) + RETURN INTEGER; + -- + -- + -- + FUNCTION update_auction + (item_id_in IN market_auctions.item_id%TYPE, + active_in IN market_auctions.active%TYPE, + owner_id_in IN market_auctions.owner_id%TYPE) + RETURN INTEGER; + -- + -- + -- + FUNCTION update_location + (oldloc_in IN auction_locations.location_name%TYPE, + newloc_in IN auction_locations.location_name%TYPE, + sales_tax_in IN auction_locations.sales_tax%TYPE, + sales_tax_bank_id_in IN auction_locations.sales_tax_bank_id%TYPE) + RETURN INTEGER; + -- + -- + -- + FUNCTION update_item_location + (oldloc_in IN market_auctions.location%TYPE, + newloc_in IN market_auctions.location%TYPE) + RETURN INTEGER; + -- + -- + -- + FUNCTION get_auction_characters + (auction_cur_out OUT swg_cur) + RETURN INTEGER; + -- + -- + -- + FUNCTION get_auction_locations + (auction_cur_out OUT swg_cur) + RETURN INTEGER; + -- + -- + -- + FUNCTION get_auction_bids + (auction_cur_out OUT swg_cur) + RETURN INTEGER; + -- + -- + -- + FUNCTION get_market_auctions + (auction_cur_out OUT swg_cur) + RETURN INTEGER; + +end swg_commodities; +/ + +prompt +prompt Creating package body SWG_COMMODITIES +prompt ===================================== +prompt +create or replace package body swg_commodities is + + FUNCTION create_auction + (creator_id_in IN market_auctions.creator_id%TYPE, + min_bid_in IN market_auctions.min_bid%TYPE, + auction_timer_in IN market_auctions.auction_timer%TYPE, + buy_now_price_in IN market_auctions.buy_now_price%TYPE, + location_in IN market_auctions.location%TYPE, + item_id_in IN market_auctions.item_id%TYPE, + category_in IN market_auctions.category%TYPE, + item_timer_in IN market_auctions.item_timer%TYPE, + owner_id_in IN market_auctions.owner_id%TYPE, + active_in IN market_auctions.active%TYPE, + auction_cur_out OUT swg_cur) + RETURN INTEGER IS + BEGIN + INSERT INTO market_auctions + (creator_id, + min_bid, + auction_timer, + buy_now_price, + user_description, + oob, + location, + item_id, + category, + item_timer, + item_name, + owner_id, + active) + VALUES + (creator_id_in, + min_bid_in, + auction_timer_in, + buy_now_price_in, + empty_blob(), + empty_blob(), + location_in, + item_id_in, + category_in, + item_timer_in, + empty_blob(), + owner_id_in, + active_in); + + + OPEN auction_cur_out FOR + SELECT user_description, oob, item_name + FROM market_auctions + WHERE item_id = item_id_in + FOR UPDATE; + + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + RETURN SQLCODE; + END create_auction; + -- + -- + -- + FUNCTION create_character + (character_id_in IN auction_characters.character_id%TYPE, + character_name_in IN auction_characters.character_name%TYPE) + RETURN INTEGER IS + BEGIN + INSERT INTO auction_characters + (character_id, + character_name) + VALUES + (character_id_in, + character_name_in); + + COMMIT; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + RETURN SQLCODE; + + END create_character; + -- + -- + -- + FUNCTION delete_auction + (item_id_in IN market_auctions.item_id%TYPE) + RETURN INTEGER IS + BEGIN + DELETE FROM market_auctions + WHERE item_id = item_id_in; + + DELETE FROM market_auction_bids + WHERE item_id = item_id_in; + + COMMIT; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + RETURN SQLCODE; + END delete_auction; + -- + -- + -- + FUNCTION delete_location + (location_in IN auction_locations.location_name%TYPE) + RETURN INTEGER IS + BEGIN + DELETE FROM auction_locations + WHERE location_name = location_in; + + COMMIT; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + RETURN SQLCODE; + END delete_location; + -- + -- + -- + FUNCTION create_bid + (bid_id_in IN market_auction_bids.bid_id%TYPE, + item_id_in IN market_auction_bids.item_id%TYPE, + bidder_id_in IN market_auction_bids.bidder_id%TYPE, + bid_in IN market_auction_bids.bid%TYPE, + max_proxy_bid_in IN market_auction_bids.max_proxy_bid%TYPE) + RETURN INTEGER IS + BEGIN + INSERT INTO market_auction_bids + (bid_id, + item_id, + bidder_id, + bid, + max_proxy_bid) + VALUES + (bid_id_in, + item_id_in, + bidder_id_in, + bid_in, + max_proxy_bid_in); + + COMMIT; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + RETURN SQLCODE; + END create_bid; + -- + -- + -- + FUNCTION create_location + (owner_id_in IN auction_locations.owner_id%TYPE, + location_name_in IN auction_locations.location_name%TYPE) + RETURN INTEGER IS + BEGIN + INSERT INTO auction_locations + (owner_id, + location_name) + VALUES + (owner_id_in, + location_name_in); + + COMMIT; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + RETURN SQLCODE; + END create_location; + -- + -- + -- + FUNCTION update_auction + (item_id_in IN market_auctions.item_id%TYPE, + active_in IN market_auctions.active%TYPE, + owner_id_in IN market_auctions.owner_id%TYPE) + RETURN INTEGER IS + BEGIN + UPDATE market_auctions + SET active = active_in, + owner_id = owner_id_in + WHERE item_id = item_id_in; + + COMMIT; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + RETURN SQLCODE; + END update_auction; + -- + -- + -- + FUNCTION update_location + (oldloc_in IN auction_locations.location_name%TYPE, + newloc_in IN auction_locations.location_name%TYPE, + sales_tax_in IN auction_locations.sales_tax%TYPE, + sales_tax_bank_id_in IN auction_locations.sales_tax_bank_id%TYPE) + RETURN INTEGER IS + BEGIN + UPDATE auction_locations + SET location_name = newloc_in, sales_tax = sales_tax_in, sales_tax_bank_id = sales_tax_bank_id_in + WHERE location_name = oldloc_in; + + COMMIT; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + RETURN SQLCODE; + END update_location; + -- + -- + -- + FUNCTION update_item_location + (oldloc_in IN market_auctions.location%TYPE, + newloc_in IN market_auctions.location%TYPE) + RETURN INTEGER IS + BEGIN + UPDATE market_auctions + SET location = newloc_in + WHERE location = oldloc_in; + + COMMIT; + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + ROLLBACK; + RETURN SQLCODE; + END update_item_location; + -- + -- + -- + FUNCTION get_auction_characters + (auction_cur_out OUT swg_cur) + RETURN INTEGER IS + BEGIN + OPEN auction_cur_out FOR + SELECT character_id, + character_name + FROM auction_characters; + + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + RETURN SQLCODE; + END get_auction_characters; + -- + -- + -- + FUNCTION get_auction_locations + (auction_cur_out OUT swg_cur) + RETURN INTEGER IS + BEGIN + OPEN auction_cur_out FOR + SELECT owner_id, + location_name, + sales_tax, + sales_tax_bank_id + FROM auction_locations; + + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + RETURN SQLCODE; + END get_auction_locations; + -- + -- + -- + FUNCTION get_auction_bids + (auction_cur_out OUT swg_cur) + RETURN INTEGER IS + BEGIN + OPEN auction_cur_out FOR + SELECT bid_id, + item_id, + bidder_id, + bid, + max_proxy_bid + FROM market_auction_bids; + + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + RETURN SQLCODE; + END get_auction_bids; + -- + -- + -- + FUNCTION get_market_auctions + (auction_cur_out OUT swg_cur) + RETURN INTEGER IS + BEGIN + OPEN auction_cur_out FOR + SELECT creator_id, + min_bid, + auction_timer, + buy_now_price, + user_description, + oob, + location, + item_id, + category, + item_timer, + item_name, + owner_id, + active + FROM market_auctions + FOR UPDATE; + + RETURN 0; + + EXCEPTION + WHEN OTHERS THEN + RETURN SQLCODE; + END get_market_auctions; + +end swg_commodities; +/ + + +spool off diff --git a/engine/shared/library/sharedNetwork/src/CMakeLists.txt b/engine/shared/library/sharedNetwork/src/CMakeLists.txt index 5fe30176..11def0eb 100644 --- a/engine/shared/library/sharedNetwork/src/CMakeLists.txt +++ b/engine/shared/library/sharedNetwork/src/CMakeLists.txt @@ -98,3 +98,7 @@ target_link_libraries(sharedNetwork sharedMessageDispatch udplibrary ) + +if(WIN32) + target_link_libraries(sharedNetwork mswsock ws2_32) +endif()