mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-26 14:37:44 +00:00
Merge pull request #468 from NotAdam/housing
fix a few housing related inventory issues
This commit is contained in:
commit
8bf71e90d5
17 changed files with 395 additions and 73 deletions
|
@ -866,13 +866,13 @@ namespace Sapphire::Common
|
|||
Mansion
|
||||
};
|
||||
|
||||
enum HouseState : uint8_t
|
||||
enum HouseStatus : uint8_t
|
||||
{
|
||||
none,
|
||||
forSale,
|
||||
sold,
|
||||
privateHouse,
|
||||
fcHouse,
|
||||
ForSale,
|
||||
Sold,
|
||||
PrivateEstate,
|
||||
FreeCompanyEstate,
|
||||
};
|
||||
|
||||
enum HouseIconAdd : uint8_t
|
||||
|
|
|
@ -176,7 +176,7 @@ namespace Sapphire::Network::Packets
|
|||
|
||||
DirectorVars = 0x01E1, // updated 4.4
|
||||
|
||||
CFAvailableContents = 0x01FD, // updated 4.2
|
||||
CFAvailableContents = 0xF1FD, // updated 4.2
|
||||
|
||||
WeatherChange = 0x01FC, // updated 4.4
|
||||
PlayerTitleList = 0x01FD, // updated 4.4
|
||||
|
@ -264,10 +264,10 @@ namespace Sapphire::Network::Packets
|
|||
|
||||
LinkshellListHandler = 0x00F4, // updated 4.3
|
||||
|
||||
MarketBoardRequestItemInformation = 0x00FE, // updated 4.4
|
||||
MarketBoardRequestItemListingInfo = 0x00FE, // updated 4.4
|
||||
MarketBoardRequestItemListings = 0x00FF, // updated 4.4
|
||||
MarketBoardSearch = 0x0103, // updated 4.4
|
||||
|
||||
SearchMarketboard = 0x0103, // updated 4.3
|
||||
ReqExamineFcInfo = 0x010F, // updated 4.1
|
||||
|
||||
FcInfoReqHandler = 0x011A, // updated 4.2
|
||||
|
|
|
@ -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,6 +271,26 @@ struct FFXIVIpcHousingUpdateObjectPosition :
|
|||
/* 001C */ uint32_t padding;
|
||||
};
|
||||
|
||||
struct FFXIVIpcMarketBoardSearch :
|
||||
FFXIVIpcBasePacket< MarketBoardSearch >
|
||||
{
|
||||
/* 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;
|
||||
/* 0009 */ uint8_t classJobId;
|
||||
/* 000A */ char searchStr[40];
|
||||
/* 0032 */ uint16_t unk4[43];
|
||||
};
|
||||
|
||||
struct FFXIVIpcMarketBoardRequestItemListingInfo :
|
||||
FFXIVIpcBasePacket< MarketBoardRequestItemListingInfo >
|
||||
{
|
||||
/* 0000 */ uint32_t catalogId;
|
||||
/* 0000 */ uint32_t requestId;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1847,23 +1847,24 @@ 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 :
|
||||
FFXIVIpcBasePacket< MarketBoardItemListingCount >
|
||||
{
|
||||
uint32_t itemCatalogId;
|
||||
uint32_t unknown1; // does some shit if nonzero
|
||||
uint16_t unknown2;
|
||||
uint16_t quantity; // high/low u8s read separately?
|
||||
uint32_t padding3;
|
||||
uint32_t itemCatalogId;
|
||||
uint32_t unknown1; // does some shit if nonzero
|
||||
uint16_t requestId;
|
||||
uint16_t quantity; // high/low u8s read separately?
|
||||
uint32_t unknown3;
|
||||
};
|
||||
|
||||
struct FFXIVIpcMarketBoardItemListingHistory :
|
||||
|
@ -1875,14 +1876,14 @@ struct FFXIVIpcMarketBoardItemListingHistory :
|
|||
struct MarketListing
|
||||
{
|
||||
uint32_t salePrice;
|
||||
time_t purchaseTime;
|
||||
uint32_t purchaseTime;
|
||||
uint32_t quantity;
|
||||
uint16_t unknown1;
|
||||
uint8_t unknown2;
|
||||
uint8_t isHq;
|
||||
uint8_t padding;
|
||||
uint8_t onMannequin;
|
||||
|
||||
char sellerName[32];
|
||||
char buyerName[33];
|
||||
|
||||
uint8_t unknown3;
|
||||
uint32_t itemCatalogId;
|
||||
} listing[20];
|
||||
};
|
||||
|
|
|
@ -179,8 +179,8 @@ void Sapphire::World::Manager::HousingMgr::initLandCache()
|
|||
entry.m_landId = res->getUInt( "LandId" );
|
||||
|
||||
entry.m_type = static_cast< Common::LandType >( res->getUInt( "Type" ) );
|
||||
entry.m_size = res->getUInt8( "Size" );
|
||||
entry.m_status = res->getUInt8( "Status" );
|
||||
entry.m_size = static_cast< Common::HouseSize >( res->getUInt8( "Size" ) );
|
||||
entry.m_status = static_cast< Common::HouseStatus >( res->getUInt8( "Status" ) );
|
||||
entry.m_currentPrice = res->getUInt64( "LandPrice" );
|
||||
entry.m_updateTime = res->getUInt64( "UpdateTime" );
|
||||
entry.m_ownerId = res->getUInt64( "OwnerId" );
|
||||
|
@ -365,7 +365,7 @@ Sapphire::LandPurchaseResult Sapphire::World::Manager::HousingMgr::purchaseLand(
|
|||
if( !pLand )
|
||||
return LandPurchaseResult::ERR_INTERNAL;
|
||||
|
||||
if( pLand->getState() != HouseState::forSale )
|
||||
if( pLand->getStatus() != HouseStatus::ForSale )
|
||||
return LandPurchaseResult::ERR_NOT_AVAILABLE;
|
||||
|
||||
if( gilAvailable < plotPrice )
|
||||
|
@ -388,7 +388,7 @@ Sapphire::LandPurchaseResult Sapphire::World::Manager::HousingMgr::purchaseLand(
|
|||
|
||||
player.removeCurrency( CurrencyType::Gil, plotPrice );
|
||||
pLand->setOwnerId( player.getId() );
|
||||
pLand->setState( HouseState::sold );
|
||||
pLand->setStatus( HouseStatus::Sold );
|
||||
pLand->setLandType( Common::LandType::Private );
|
||||
|
||||
player.setLandFlags( LandFlagsSlot::Private, 0x00, pLand->getLandIdent() );
|
||||
|
@ -437,7 +437,7 @@ bool Sapphire::World::Manager::HousingMgr::relinquishLand( Entity::Player& playe
|
|||
|
||||
pLand->setCurrentPrice( pLand->getMaxPrice() );
|
||||
pLand->setOwnerId( 0 );
|
||||
pLand->setState( HouseState::forSale );
|
||||
pLand->setStatus( HouseStatus::ForSale );
|
||||
pLand->setLandType( Common::LandType::none );
|
||||
pLand->updateLandDb();
|
||||
|
||||
|
@ -477,11 +477,11 @@ void Sapphire::World::Manager::HousingMgr::sendWardLandInfo( Entity::Player& pla
|
|||
|
||||
auto& entry = wardInfoPacket->data().houseInfoEntry[ i ];
|
||||
|
||||
// retail always sends the house price in this packet, even after the house has been sold
|
||||
// retail always sends the house price in this packet, even after the house has been Sold
|
||||
// so I guess we do the same
|
||||
entry.housePrice = land->getCurrentPrice();
|
||||
|
||||
if( land->getState() == Common::HouseState::forSale )
|
||||
if( land->getStatus() == Common::HouseStatus::ForSale )
|
||||
continue;
|
||||
|
||||
if( auto house = land->getHouse() )
|
||||
|
@ -568,7 +568,7 @@ bool Sapphire::World::Manager::HousingMgr::initHouseModels( Entity::Player& play
|
|||
if( !player.findFirstItemWithId( presetCatalogId, foundItem ) )
|
||||
return false;
|
||||
|
||||
auto item = player.dropInventoryItem( foundItem.first, foundItem.second );
|
||||
auto item = getHousingItemFromPlayer( player, foundItem.first, foundItem.second );
|
||||
if( !item )
|
||||
return false;
|
||||
|
||||
|
@ -682,7 +682,7 @@ void Sapphire::World::Manager::HousingMgr::buildPresetEstate( Entity::Player& pl
|
|||
|
||||
createHouse( house );
|
||||
|
||||
pLand->setState( HouseState::privateHouse );
|
||||
pLand->setStatus( HouseStatus::PrivateEstate );
|
||||
pLand->setLandType( LandType::Private );
|
||||
hZone->sendLandUpdate( plotNum );
|
||||
|
||||
|
@ -1002,12 +1002,10 @@ void Sapphire::World::Manager::HousingMgr::reqPlaceHousingItem( Sapphire::Entity
|
|||
containerId == InventoryType::Bag2 ||
|
||||
containerId == InventoryType::Bag3 )
|
||||
{
|
||||
auto tmpItem = player.dropInventoryItem( static_cast< Common::InventoryType >( containerId ), slotId );
|
||||
if( !tmpItem )
|
||||
item = getHousingItemFromPlayer( player, static_cast< Common::InventoryType >( containerId ), slotId );
|
||||
if( !item )
|
||||
return;
|
||||
|
||||
item = Inventory::make_HousingItem( tmpItem->getUId(), tmpItem->getId(), framework() );
|
||||
|
||||
// set params
|
||||
item->setPos( {
|
||||
Util::floatToUInt16( pos.x ),
|
||||
|
@ -1074,7 +1072,7 @@ void Sapphire::World::Manager::HousingMgr::reqPlaceItemInStore( Sapphire::Entity
|
|||
if( freeSlot == -1 )
|
||||
return;
|
||||
|
||||
auto item = player.dropInventoryItem( static_cast< Common::InventoryType >( containerId ), slotId );
|
||||
auto item = getHousingItemFromPlayer( player, static_cast< Common::InventoryType >( containerId ), slotId );
|
||||
if( !item )
|
||||
return;
|
||||
|
||||
|
@ -1097,7 +1095,7 @@ void Sapphire::World::Manager::HousingMgr::reqPlaceItemInStore( Sapphire::Entity
|
|||
continue;
|
||||
}
|
||||
|
||||
auto item = player.dropInventoryItem( static_cast< Common::InventoryType >( containerId ), slotId );
|
||||
auto item = getHousingItemFromPlayer( player, static_cast< Common::InventoryType >( containerId ), slotId );
|
||||
if( !item )
|
||||
return;
|
||||
|
||||
|
@ -1386,24 +1384,24 @@ bool Sapphire::World::Manager::HousingMgr::removeInternalItem( Entity::Player& p
|
|||
{
|
||||
auto& containers = getEstateInventory( terri.getLandIdent() );
|
||||
|
||||
// validate the container id first
|
||||
// we also need the idx of the container so we can get the slot offset
|
||||
bool foundContainer = false;
|
||||
uint8_t containerIdx = 0;
|
||||
for( auto cId : m_internalPlacedItemContainers )
|
||||
int8_t containerIdx = 0;
|
||||
|
||||
if( isPlacedItemsInventory( static_cast< Common::InventoryType >( containerId ) ) )
|
||||
{
|
||||
if( containerId == cId )
|
||||
for( auto cId : m_internalPlacedItemContainers )
|
||||
{
|
||||
foundContainer = true;
|
||||
if( containerId == cId )
|
||||
break;
|
||||
|
||||
break;
|
||||
containerIdx++;
|
||||
}
|
||||
|
||||
containerIdx++;
|
||||
}
|
||||
else
|
||||
containerIdx = -1;
|
||||
|
||||
if( !foundContainer )
|
||||
return false;
|
||||
// its possible to remove an item from any container in basically all these remove functions
|
||||
// eg, remove a permit and reuse it elsewhere
|
||||
// I'm not going to bother fixing it for now, but worth noting for future reference
|
||||
|
||||
auto needle = containers.find( containerId );
|
||||
if( needle == containers.end() )
|
||||
|
@ -1457,8 +1455,11 @@ bool Sapphire::World::Manager::HousingMgr::removeInternalItem( Entity::Player& p
|
|||
}
|
||||
|
||||
// despawn
|
||||
auto arraySlot = ( containerIdx * 50 ) + slotId;
|
||||
terri.removeHousingObject( arraySlot );
|
||||
if( containerIdx != -1 )
|
||||
{
|
||||
auto arraySlot = ( containerIdx * 50 ) + slotId;
|
||||
terri.removeHousingObject( arraySlot );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1614,4 +1615,14 @@ bool Sapphire::World::Manager::HousingMgr::hasPermission( Sapphire::Entity::Play
|
|||
// todo: check perms here
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Sapphire::Inventory::HousingItemPtr Sapphire::World::Manager::HousingMgr::getHousingItemFromPlayer(
|
||||
Entity::Player& player, Common::InventoryType type, uint8_t slot )
|
||||
{
|
||||
auto tmpItem = player.dropInventoryItem( type, slot );
|
||||
if( !tmpItem )
|
||||
return nullptr;
|
||||
|
||||
return Inventory::make_HousingItem( tmpItem->getUId(), tmpItem->getId(), framework() );
|
||||
}
|
|
@ -31,8 +31,8 @@ namespace Sapphire::World::Manager
|
|||
uint16_t m_landId;
|
||||
|
||||
Common::LandType m_type;
|
||||
uint8_t m_size;
|
||||
uint8_t m_status;
|
||||
Common::HouseSize m_size;
|
||||
Common::HouseStatus m_status;
|
||||
|
||||
uint64_t m_currentPrice;
|
||||
|
||||
|
@ -185,6 +185,8 @@ namespace Sapphire::World::Manager
|
|||
|
||||
private:
|
||||
|
||||
Inventory::HousingItemPtr getHousingItemFromPlayer( Entity::Player& player, Common::InventoryType type, uint8_t slot );
|
||||
|
||||
ItemContainerPtr getFreeEstateInventorySlot( Common::LandIdent ident,
|
||||
Inventory::InventoryContainerPair& pair,
|
||||
Inventory::InventoryTypeList bagList );
|
||||
|
|
159
src/world/Manager/MarketMgr.cpp
Normal file
159
src/world/Manager/MarketMgr.cpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
#include "MarketMgr.h"
|
||||
|
||||
#include <Exd/ExdDataGenerated.h>
|
||||
#include <Framework.h>
|
||||
#include <Logging/Logger.h>
|
||||
|
||||
#include <Network/CommonNetwork.h>
|
||||
#include <Network/GamePacketNew.h>
|
||||
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
||||
|
||||
#include "Actor/Player.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace Sapphire::Network::Packets;
|
||||
|
||||
Sapphire::World::Manager::MarketMgr::MarketMgr( Sapphire::FrameworkPtr pFw ) :
|
||||
BaseManager( 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 )
|
||||
// {
|
||||
// if( id > 10000 )
|
||||
// break;
|
||||
//
|
||||
// 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;
|
||||
// cacheEntry.itemLevel = item->levelItem;
|
||||
//
|
||||
// m_marketItemCache.push_back( std::move( cacheEntry ) );
|
||||
// }
|
||||
//
|
||||
// std::sort( m_marketItemCache.begin(), m_marketItemCache.end(), []( const MarketableItem& a, const MarketableItem& b )
|
||||
// {
|
||||
// return a.itemLevel > b.itemLevel;
|
||||
// } );
|
||||
//
|
||||
// Logger::info( "MarketMgr: Cached " + std::to_string( m_marketItemCache.size() ) + " marketable items" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::MarketMgr::requestItemListingInfo( Sapphire::Entity::Player& player, uint32_t catalogId,
|
||||
uint32_t requestId )
|
||||
{
|
||||
auto countPkt = makeZonePacket< Server::FFFXIVIpcMarketBoardItemListingCount >( player.getId() );
|
||||
countPkt->data().quantity = 1 << 8;
|
||||
countPkt->data().itemCatalogId = catalogId;
|
||||
countPkt->data().requestId = requestId;
|
||||
|
||||
player.queuePacket( countPkt );
|
||||
|
||||
auto historyPkt = makeZonePacket< Server::FFXIVIpcMarketBoardItemListingHistory >( player.getId() );
|
||||
historyPkt->data().itemCatalogId = catalogId;
|
||||
historyPkt->data().itemCatalogId2 = catalogId;
|
||||
|
||||
std::string name = "fix game pls se :(((";
|
||||
|
||||
for( int i = 0; i < 10; i++ )
|
||||
{
|
||||
auto& listing = historyPkt->data().listing[ i ];
|
||||
|
||||
listing.itemCatalogId = catalogId;
|
||||
listing.quantity = i + 1;
|
||||
listing.purchaseTime = time( nullptr );
|
||||
listing.salePrice = 69420420;
|
||||
listing.isHq = 1;
|
||||
listing.onMannequin = 1;
|
||||
|
||||
|
||||
strcpy( listing.buyerName, name.c_str() );
|
||||
}
|
||||
|
||||
player.queuePacket( historyPkt );
|
||||
}
|
||||
|
||||
|
||||
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 < size; i++ )
|
||||
{
|
||||
auto& item = resultList.at( startIdx + i );
|
||||
auto& data = resultPkt->data().items[ i ];
|
||||
|
||||
data.itemCatalogId = item.catalogId;
|
||||
data.quantity = item.quantity;
|
||||
data.demand = 420;
|
||||
}
|
||||
|
||||
if( size < 20 )
|
||||
resultPkt->data().itemIndexEnd = 0;
|
||||
else
|
||||
resultPkt->data().itemIndexEnd = startIdx + 20;
|
||||
|
||||
player.queuePacket( resultPkt );
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::MarketMgr::requestItemListings( Sapphire::Entity::Player& player, uint16_t catalogId )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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 } );
|
||||
}
|
||||
}
|
58
src/world/Manager/MarketMgr.h
Normal file
58
src/world/Manager/MarketMgr.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
#ifndef SAPPHIRE_MARKETMGR_H
|
||||
#define SAPPHIRE_MARKETMGR_H
|
||||
|
||||
#include "ForwardsZone.h"
|
||||
#include "BaseManager.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Sapphire::World::Manager
|
||||
{
|
||||
class MarketMgr : public Manager::BaseManager
|
||||
{
|
||||
public:
|
||||
explicit MarketMgr( FrameworkPtr pFw );
|
||||
|
||||
bool init();
|
||||
|
||||
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 requestItemListingInfo( Entity::Player& player, uint32_t catalogId, uint32_t requestId );
|
||||
|
||||
void requestItemListings( Entity::Player& player, uint16_t catalogId );
|
||||
|
||||
private:
|
||||
struct ItemSearchResult
|
||||
{
|
||||
uint32_t catalogId;
|
||||
uint16_t quantity;
|
||||
};
|
||||
|
||||
struct MarketableItem
|
||||
{
|
||||
uint32_t catalogId;
|
||||
uint8_t itemSearchCategory;
|
||||
uint8_t maxEquipLevel;
|
||||
uint16_t itemLevel;
|
||||
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 );
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //SAPPHIRE_MARKETMGR_H
|
|
@ -1,3 +1,6 @@
|
|||
#ifndef SAPPHIRE_PLAYERMGR_H
|
||||
#define SAPPHIRE_PLAYERMGR_H
|
||||
|
||||
#include "ForwardsZone.h"
|
||||
#include "BaseManager.h"
|
||||
|
||||
|
@ -10,4 +13,6 @@ class PlayerMgr : public Manager::BaseManager
|
|||
|
||||
void movePlayerToLandDestination( Sapphire::Entity::Player& player, uint32_t landId, uint16_t param = 0 );
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SAPPHIRE_PLAYERMGR_H
|
|
@ -123,6 +123,12 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
|
|||
|
||||
setZoneHandler( ClientZoneIpcType::PerformNoteHandler, "PerformNoteHandler", &GameConnection::performNoteHandler );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::MarketBoardSearch, "MarketBoardSearch", &GameConnection::marketBoardSearch );
|
||||
setZoneHandler( ClientZoneIpcType::MarketBoardRequestItemListingInfo, "MarketBoardRequestItemListingInfo",
|
||||
&GameConnection::marketBoardRequestItemInfo );
|
||||
setZoneHandler( ClientZoneIpcType::MarketBoardRequestItemListings, "MarketBoardRequestItemListings",
|
||||
&GameConnection::marketBoardRequestItemListings );
|
||||
|
||||
setChatHandler( ClientChatIpcType::TellReq, "TellReq", &GameConnection::tellHandler );
|
||||
|
||||
}
|
||||
|
|
|
@ -176,6 +176,12 @@ namespace Sapphire::Network
|
|||
|
||||
DECLARE_HANDLER( reqMoveHousingItem );
|
||||
|
||||
DECLARE_HANDLER( marketBoardSearch );
|
||||
|
||||
DECLARE_HANDLER( marketBoardRequestItemInfo );
|
||||
|
||||
DECLARE_HANDLER( marketBoardRequestItemListings );
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "Manager/DebugCommandMgr.h"
|
||||
#include "Manager/EventMgr.h"
|
||||
#include "Manager/MarketMgr.h"
|
||||
|
||||
#include "Action/Action.h"
|
||||
#include "Action/ActionTeleport.h"
|
||||
|
@ -752,4 +753,41 @@ void Sapphire::Network::GameConnection::reqMoveHousingItem( FrameworkPtr pFw,
|
|||
|
||||
housingMgr->reqMoveHousingItem( player, data.ident, data.slot, data.pos, data.rotation );
|
||||
|
||||
}
|
||||
|
||||
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::FFXIVIpcMarketBoardSearch >( inPacket );
|
||||
const auto& data = packet.data();
|
||||
|
||||
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::FFXIVIpcMarketBoardRequestItemListingInfo >( inPacket );
|
||||
|
||||
auto marketMgr = pFw->get< MarketMgr >();
|
||||
|
||||
marketMgr->requestItemListingInfo( player, packet.data().catalogId, packet.data().requestId );
|
||||
}
|
||||
|
||||
void Sapphire::Network::GameConnection::marketBoardRequestItemListings( FrameworkPtr pFw,
|
||||
const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
const auto packet = ZoneChannelPacket< Client::FFXIVIpcMarketBoardRequestItemListings >( inPacket );
|
||||
|
||||
auto marketMgr = pFw->get< MarketMgr >();
|
||||
|
||||
marketMgr->requestItemListings( player, packet.data().itemCatalogId );
|
||||
}
|
|
@ -39,6 +39,7 @@
|
|||
#include "Manager/InventoryMgr.h"
|
||||
#include "Manager/EventMgr.h"
|
||||
#include "Manager/ItemMgr.h"
|
||||
#include "Manager/MarketMgr.h"
|
||||
|
||||
using namespace Sapphire::World::Manager;
|
||||
|
||||
|
@ -160,6 +161,15 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] )
|
|||
return;
|
||||
}
|
||||
|
||||
auto pMarketMgr = std::make_shared< Manager::MarketMgr >( framework() );
|
||||
framework()->set< Manager::MarketMgr >( pMarketMgr );
|
||||
|
||||
if( !pMarketMgr->init() )
|
||||
{
|
||||
Logger::fatal( "Failed to setup market manager!" );
|
||||
return;
|
||||
}
|
||||
|
||||
loadBNpcTemplates();
|
||||
|
||||
Network::HivePtr hive( new Network::Hive() );
|
||||
|
|
|
@ -76,14 +76,19 @@ void Sapphire::World::Territory::Housing::HousingInteriorTerritory::onPlayerZone
|
|||
|
||||
player.queuePacket( indoorInitPacket );
|
||||
|
||||
bool isFcHouse = pLand->getStatus() == Common::HouseStatus::PrivateEstate;
|
||||
|
||||
auto yardPacketTotal = static_cast< uint8_t >( 2 + pLand->getSize() );
|
||||
for( uint8_t yardPacketNum = 0; yardPacketNum < yardPacketTotal; yardPacketNum++ )
|
||||
{
|
||||
auto objectInitPacket = makeZonePacket< Server::FFXIVIpcHousingObjectInitialize >( player.getId() );
|
||||
memcpy( &objectInitPacket->data().landIdent, &m_landIdent, sizeof( Common::LandIdent ) );
|
||||
// todo: change this when FC houses become a thing
|
||||
objectInitPacket->data().u1 = 2; // 2 = actrl 0x400 will hide the fc door, otherwise it will stay there
|
||||
|
||||
if( isFcHouse )
|
||||
objectInitPacket->data().u1 = 2; // 2 = actrl 0x400 will hide the fc door, otherwise it will stay there
|
||||
else
|
||||
objectInitPacket->data().u1 = 0;
|
||||
|
||||
objectInitPacket->data().u2 = 100;
|
||||
objectInitPacket->data().packetNum = yardPacketNum;
|
||||
objectInitPacket->data().packetTotal = yardPacketTotal;
|
||||
|
@ -94,8 +99,8 @@ void Sapphire::World::Territory::Housing::HousingInteriorTerritory::onPlayerZone
|
|||
player.queuePacket( objectInitPacket );
|
||||
}
|
||||
|
||||
// todo: if in fc house, don't send this
|
||||
player.queuePacket( Server::makeActorControl143( player.getId(), Network::ActorControl::HideAdditionalChambersDoor ) );
|
||||
if( isFcHouse )
|
||||
player.queuePacket( Server::makeActorControl143( player.getId(), Network::ActorControl::HideAdditionalChambersDoor ) );
|
||||
}
|
||||
|
||||
void Sapphire::World::Territory::Housing::HousingInteriorTerritory::onUpdate( uint32_t currTime )
|
||||
|
|
|
@ -220,7 +220,7 @@ void Sapphire::HousingZone::sendLandSet( Entity::Player& player )
|
|||
auto& landData = landsetInitializePacket->data().land[ count ];
|
||||
|
||||
landData.plotSize = pLand->getSize();
|
||||
landData.houseState = pLand->getState();
|
||||
landData.houseState = pLand->getStatus();
|
||||
landData.iconAddIcon = pLand->getSharing();
|
||||
landData.fcId = pLand->getFcId();
|
||||
landData.fcIcon = pLand->getFcIcon();
|
||||
|
@ -256,7 +256,7 @@ void Sapphire::HousingZone::sendLandUpdate( uint8_t landId )
|
|||
auto& landData = landUpdatePacket->data().land;
|
||||
|
||||
landData.plotSize = pLand->getSize();
|
||||
landData.houseState = pLand->getState();
|
||||
landData.houseState = pLand->getStatus();
|
||||
landData.iconAddIcon = pLand->getSharing();
|
||||
landData.fcId = pLand->getFcId();
|
||||
landData.fcIcon = pLand->getFcIcon();
|
||||
|
|
|
@ -54,7 +54,7 @@ Sapphire::Land::Land( uint16_t territoryTypeId, uint8_t wardNum, uint8_t landId,
|
|||
|
||||
Sapphire::Land::~Land() = default;
|
||||
|
||||
void Sapphire::Land::init( Common::LandType type, uint8_t size, uint8_t state, uint32_t currentPrice,
|
||||
void Sapphire::Land::init( Common::LandType type, Common::HouseSize size, Common::HouseStatus state, uint32_t currentPrice,
|
||||
uint64_t ownerId, uint64_t houseId )
|
||||
{
|
||||
m_type = type;
|
||||
|
@ -84,12 +84,12 @@ uint32_t Sapphire::Land::getMaxPrice() const
|
|||
}
|
||||
|
||||
//Primary State
|
||||
void Sapphire::Land::setSize( uint8_t size )
|
||||
void Sapphire::Land::setSize( Common::HouseSize size )
|
||||
{
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void Sapphire::Land::setState( uint8_t state )
|
||||
void Sapphire::Land::setStatus( Common::HouseStatus state )
|
||||
{
|
||||
m_state = state;
|
||||
}
|
||||
|
@ -104,12 +104,12 @@ void Sapphire::Land::setLandType( Common::LandType type )
|
|||
m_type = type;
|
||||
}
|
||||
|
||||
uint8_t Sapphire::Land::getSize() const
|
||||
Sapphire::Common::HouseSize Sapphire::Land::getSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
uint8_t Sapphire::Land::getState() const
|
||||
Sapphire::Common::HouseStatus Sapphire::Land::getStatus() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ void Sapphire::Land::updateLandDb()
|
|||
|
||||
void Sapphire::Land::update( uint32_t currTime )
|
||||
{
|
||||
if( getState() == HouseState::forSale )
|
||||
if( getStatus() == HouseStatus::ForSale )
|
||||
{
|
||||
if( m_nextDrop < currTime && m_minPrice < m_currentPrice )
|
||||
{
|
||||
|
|
|
@ -18,20 +18,20 @@ namespace Sapphire
|
|||
Land( uint16_t zoneId, uint8_t wardNum, uint8_t landId, uint32_t landSetId,
|
||||
Sapphire::Data::HousingLandSetPtr info, FrameworkPtr pFw );
|
||||
virtual ~Land();
|
||||
void init( Common::LandType type, uint8_t size, uint8_t state, uint32_t currentPrice, uint64_t ownerId, uint64_t houseId );
|
||||
void init( Common::LandType type, Common::HouseSize size, Common::HouseStatus state, uint32_t currentPrice, uint64_t ownerId, uint64_t houseId );
|
||||
|
||||
using LandInventoryMap = std::unordered_map< uint16_t, ItemContainerPtr >;
|
||||
using InvMaxItemsPair = std::pair< uint16_t, uint16_t >;
|
||||
|
||||
//Primary state
|
||||
void setSize( uint8_t size );
|
||||
void setState( uint8_t state );
|
||||
void setSize( Common::HouseSize size );
|
||||
void setStatus( Common::HouseStatus state );
|
||||
void setSharing( uint8_t state );
|
||||
void setLandType( Common::LandType type );
|
||||
|
||||
//Gerneral
|
||||
uint8_t getSize() const;
|
||||
uint8_t getState() const;
|
||||
Common::HouseSize getSize() const;
|
||||
Common::HouseStatus getStatus() const;
|
||||
uint8_t getSharing() const;
|
||||
uint32_t getLandSetId() const;
|
||||
Common::LandType getLandType() const;
|
||||
|
@ -71,8 +71,8 @@ namespace Sapphire
|
|||
Common::LandIdent m_landIdent;
|
||||
|
||||
uint32_t m_landSetId;
|
||||
uint8_t m_size;
|
||||
uint8_t m_state;
|
||||
Common::HouseSize m_size;
|
||||
Common::HouseStatus m_state;
|
||||
Common::LandType m_type;
|
||||
uint8_t m_iconAddIcon;
|
||||
uint32_t m_fcId; // unclear, may be wrong
|
||||
|
|
Loading…
Add table
Reference in a new issue