From 50d1d9d4928de64e173f84795ad90838de477a01 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Tue, 1 Jan 2019 11:51:48 +1100 Subject: [PATCH] correctly send marketboard item list --- src/common/Network/PacketDef/Ipcs.h | 2 +- .../Network/PacketDef/Zone/ClientZoneDef.h | 20 +++- .../Network/PacketDef/Zone/ServerZoneDef.h | 5 +- src/world/Manager/MarketMgr.cpp | 106 +++++++++++++++++- src/world/Manager/MarketMgr.h | 35 +++++- src/world/Network/GameConnection.cpp | 4 + src/world/Network/GameConnection.h | 4 +- src/world/Network/Handlers/PacketHandlers.cpp | 20 +++- 8 files changed, 177 insertions(+), 19 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 40855781..c1875da3 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -266,8 +266,8 @@ namespace Sapphire::Network::Packets MarketBoardRequestItemInformation = 0x00FE, // updated 4.4 MarketBoardRequestItemListings = 0x00FF, // updated 4.4 + MarketBoardSearch = 0x0103, // updated 4.4 - SearchMarketboard = 0x0103, // updated 4.4 ReqExamineFcInfo = 0x010F, // updated 4.1 FcInfoReqHandler = 0x011A, // updated 4.2 diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index 68b856b8..e312d790 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -237,8 +237,9 @@ struct FFXIVIpcSetSharedEstateSettings : struct FFXIVIpcMarketBoardRequestItemListings : FFXIVIpcBasePacket< MarketBoardRequestItemListings > { - /* 0000 */ uint32_t itemCatalogId; - /* 0004 */ uint32_t padding; + /* 0000 */ uint16_t padding1; + /* 0002 */ uint16_t itemCatalogId; + /* 0004 */ uint32_t padding2; }; struct FFXIVIpcReqPlaceHousingItem : @@ -270,11 +271,11 @@ struct FFXIVIpcHousingUpdateObjectPosition : /* 001C */ uint32_t padding; }; -struct FFXIVIpcSearchMarketboard : - FFXIVIpcBasePacket< SearchMarketboard > +struct FFXIVIpcMarketBoardSearch : + FFXIVIpcBasePacket< MarketBoardSearch > { - /* 0000 */ uint32_t unk; - /* 0004 */ uint8_t unk2[2]; + /* 0000 */ uint32_t startIdx; + /* 0004 */ uint16_t requestId; /* 0006 */ uint8_t itemSearchCategory; /* 0007 */ uint8_t shouldCheckClassJobId; // wat? seems only 1 there at least... /* 0008 */ uint8_t maxEquipLevel; @@ -283,6 +284,13 @@ struct FFXIVIpcSearchMarketboard : /* 0032 */ uint16_t unk4[43]; }; +struct FFXIVIpcMarketBoardRequestItemInformation : + FFXIVIpcBasePacket< MarketBoardRequestItemInformation > +{ + /* 0000 */ uint32_t catalogId; + /* 0000 */ uint32_t requestId; +}; + } } } diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 63ea03ba..2c5a8d8e 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1847,13 +1847,14 @@ struct FFXIVIpcMarketBoardSearchResult : struct MarketBoardItem { uint32_t itemCatalogId; - uint32_t quantity; + uint16_t quantity; + uint16_t demand; } items[20]; uint32_t itemIndexEnd; uint32_t padding1; uint32_t itemIndexStart; - uint32_t padding2; + uint32_t requestId; }; struct FFFXIVIpcMarketBoardItemListingCount : diff --git a/src/world/Manager/MarketMgr.cpp b/src/world/Manager/MarketMgr.cpp index 1769a6e8..b850f1bc 100644 --- a/src/world/Manager/MarketMgr.cpp +++ b/src/world/Manager/MarketMgr.cpp @@ -1,5 +1,17 @@ #include "MarketMgr.h" +#include +#include +#include + +#include +#include +#include + +#include "Actor/Player.h" + +using namespace Sapphire::Network::Packets; + Sapphire::World::Manager::MarketMgr::MarketMgr( Sapphire::FrameworkPtr pFw ) : BaseManager( pFw ) { @@ -8,12 +20,98 @@ Sapphire::World::Manager::MarketMgr::MarketMgr( Sapphire::FrameworkPtr pFw ) : bool Sapphire::World::Manager::MarketMgr::init() { + Logger::info( "MarketMgr: warming up marketable item cache..." ); + + // build item cache + auto exdData = framework()->get< Sapphire::Data::ExdDataGenerated >(); + auto idList = exdData->getItemIdList(); + + for( auto id : idList ) + { + auto item = exdData->get< Sapphire::Data::Item >( id ); + if( !item ) + continue; + + if( item->isUntradable ) + continue; + + MarketableItem cacheEntry {}; + cacheEntry.catalogId = id; + cacheEntry.itemSearchCategory = item->itemSearchCategory; + cacheEntry.maxEquipLevel = item->levelEquip; + cacheEntry.name = item->name; + cacheEntry.classJob = item->classJobUse; + + m_marketItemCache.push_back( std::move( cacheEntry ) ); + } + + Logger::info( "MarketMgr: Cached " + std::to_string( m_marketItemCache.size() ) + " marketable items" ); + return true; } -void Sapphire::World::Manager::MarketMgr::searchMarketboard( Entity::Player& player, - uint8_t itemSearchCategory, uint8_t maxEquipLevel, - uint8_t classJob ) +void Sapphire::World::Manager::MarketMgr::requestItemListings( Sapphire::Entity::Player& player, uint32_t catalogId, + uint32_t requestId ) { - + auto countPkt = makeZonePacket< Server::FFFXIVIpcMarketBoardItemListingCount >( player.getId() ); + countPkt->data().quantity = 1; + countPkt->data().itemCatalogId = catalogId; +} + + +void Sapphire::World::Manager::MarketMgr::searchMarketboard( Entity::Player& player, uint8_t itemSearchCategory, + uint8_t maxEquipLevel, uint8_t classJob, + const std::string_view& searchStr, uint32_t requestId, + uint32_t startIdx ) +{ + ItemSearchResultList resultList; + findItems( searchStr, itemSearchCategory, maxEquipLevel, classJob, resultList ); + + auto numResults = resultList.size(); + + if( startIdx > numResults ) + return; + + auto endIdx = std::min< size_t >( startIdx + 20, numResults ); + auto size = endIdx - startIdx; + + auto resultPkt = makeZonePacket< Server::FFXIVIpcMarketBoardSearchResult >( player.getId() ); + resultPkt->data().itemIndexStart = startIdx; + resultPkt->data().requestId = requestId; + + for( auto i = 0; i < resultList.size(); i++ ) + { + auto& item = resultList.at( startIdx + i ); + auto& data = resultPkt->data().items[ i ]; + + data.itemCatalogId = item.catalogId; + data.quantity = item.quantity; + data.demand = 69; + } + + if( size < 20 ) + resultPkt->data().itemIndexEnd = 0; + else + resultPkt->data().itemIndexEnd = startIdx + 20; + + player.queuePacket( resultPkt ); +} + +void Sapphire::World::Manager::MarketMgr::findItems( const std::string_view& searchStr, uint8_t itemSearchCat, + uint8_t maxEquipLevel, uint8_t classJob, + Sapphire::World::Manager::MarketMgr::ItemSearchResultList& resultList ) +{ + for( const auto& item : m_marketItemCache ) + { + if( item.itemSearchCategory != itemSearchCat ) + continue; + + if( maxEquipLevel > 0 && item.maxEquipLevel > maxEquipLevel ) + continue; + + if( classJob > 0 && item.classJob != classJob ) + continue; + + resultList.push_back( { item.catalogId, 1 } ); + } } \ No newline at end of file diff --git a/src/world/Manager/MarketMgr.h b/src/world/Manager/MarketMgr.h index 9c21c8ed..311c1e28 100644 --- a/src/world/Manager/MarketMgr.h +++ b/src/world/Manager/MarketMgr.h @@ -4,6 +4,8 @@ #include "ForwardsZone.h" #include "BaseManager.h" +#include + namespace Sapphire::World::Manager { class MarketMgr : public Manager::BaseManager @@ -13,7 +15,38 @@ namespace Sapphire::World::Manager bool init(); - void searchMarketboard( Entity::Player& player, uint8_t itemSearchCategory, uint8_t maxEquipLevel, uint8_t classJob ); + void searchMarketboard( Entity::Player& player, uint8_t itemSearchCategory, + uint8_t maxEquipLevel, uint8_t classJob, + const std::string_view& searchStr, uint32_t requestId, + uint32_t startIdx ); + + void requestItemListings( Entity::Player& player, uint32_t catalogId, uint32_t requestId ); + + private: + struct ItemSearchResult + { + uint32_t catalogId; + uint16_t quantity; + }; + + struct MarketableItem + { + uint32_t catalogId; + uint8_t itemSearchCategory; + uint8_t maxEquipLevel; + uint8_t classJob; + std::string name; + }; + + using ItemSearchResultList = std::vector< ItemSearchResult >; + using MarketableItemCacheList = std::vector< MarketableItem >; + + MarketableItemCacheList m_marketItemCache; + + + + void findItems( const std::string_view& searchStr, uint8_t itemSearchCat, uint8_t maxEquipLevel, uint8_t classJob, + ItemSearchResultList& resultList ); }; } diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 8761647a..de524b87 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -123,6 +123,10 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::PerformNoteHandler, "PerformNoteHandler", &GameConnection::performNoteHandler ); + setZoneHandler( ClientZoneIpcType::MarketBoardSearch, "MarketBoardSearch", &GameConnection::marketBoardSearch ); + setZoneHandler( ClientZoneIpcType::MarketBoardRequestItemInformation, "MarketBoardRequestItemInformation", + &GameConnection::marketBoardRequestItemInfo ); + setChatHandler( ClientChatIpcType::TellReq, "TellReq", &GameConnection::tellHandler ); } diff --git a/src/world/Network/GameConnection.h b/src/world/Network/GameConnection.h index c4984267..65901843 100644 --- a/src/world/Network/GameConnection.h +++ b/src/world/Network/GameConnection.h @@ -176,7 +176,9 @@ namespace Sapphire::Network DECLARE_HANDLER( reqMoveHousingItem ); - DECLARE_HANDLER( searchMarketboard ); + DECLARE_HANDLER( marketBoardSearch ); + + DECLARE_HANDLER( marketBoardRequestItemInfo ); }; diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index 580b0629..e08a566e 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -755,14 +755,26 @@ void Sapphire::Network::GameConnection::reqMoveHousingItem( FrameworkPtr pFw, } -void Sapphire::Network::GameConnection::searchMarketboard( FrameworkPtr pFw, - const Sapphire::Network::Packets::FFXIVARR_PACKET_RAW& inPacket, +void Sapphire::Network::GameConnection::marketBoardSearch( FrameworkPtr pFw, + const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { auto marketMgr = pFw->get< MarketMgr >(); - const auto packet = ZoneChannelPacket< Client::FFXIVIpcSearchMarketboard >( inPacket ); + const auto packet = ZoneChannelPacket< Client::FFXIVIpcMarketBoardSearch >( inPacket ); const auto& data = packet.data(); - marketMgr->searchMarketboard( player, data.itemSearchCategory, data.maxEquipLevel, data.classJobId ); + std::string_view searchStr( data.searchStr ); + + marketMgr->searchMarketboard( player, data.itemSearchCategory, data.maxEquipLevel, data.classJobId, data.searchStr, + data.requestId, data.startIdx ); +} + +void Sapphire::Network::GameConnection::marketBoardRequestItemInfo( FrameworkPtr pFw, + const Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + const auto packet = ZoneChannelPacket< Client::FFXIVIpcMarketBoardRequestItemInformation >( inPacket ); + + auto marketMgr = pFw->get< MarketMgr >(); } \ No newline at end of file