From dadc8184e93de63a1196e0e162e4c8fb30df90af Mon Sep 17 00:00:00 2001 From: AriAvery <41122212+AriAvery@users.noreply.github.com> Date: Sat, 10 Nov 2018 19:00:13 +0100 Subject: [PATCH] House fixes --- src/common/CommonGen.h | 8 +- src/common/Config/ConfigMgr.cpp | 18 ++- src/common/Logging/Logger.cpp | 123 ++++++++++-------- .../Scripts/common/CmnDefHousingSignboard.cpp | 26 +++- src/servers/sapphire_api/SapphireAPI.cpp | 11 +- src/servers/sapphire_api/main.cpp | 4 +- src/servers/sapphire_lobby/RestConnector.cpp | 6 +- src/servers/sapphire_zone/Actor/Player.cpp | 36 +++-- src/servers/sapphire_zone/Actor/Player.h | 10 +- .../sapphire_zone/Actor/PlayerInventory.cpp | 11 ++ .../Network/Handlers/ClientTriggerHandler.cpp | 3 + .../Network/Handlers/PacketHandlers.cpp | 9 ++ src/servers/sapphire_zone/Session.cpp | 4 + src/servers/sapphire_zone/Zone/HousingMgr.cpp | 70 ++++++++++ src/servers/sapphire_zone/Zone/HousingMgr.h | 38 ++++++ .../sapphire_zone/Zone/HousingZone.cpp | 33 ++++- src/servers/sapphire_zone/Zone/HousingZone.h | 2 + src/servers/sapphire_zone/Zone/Land.cpp | 67 +++++++--- src/servers/sapphire_zone/Zone/Land.h | 13 +- src/servers/sapphire_zone/mainGameServer.cpp | 5 +- 20 files changed, 378 insertions(+), 119 deletions(-) create mode 100644 src/servers/sapphire_zone/Zone/HousingMgr.cpp create mode 100644 src/servers/sapphire_zone/Zone/HousingMgr.h diff --git a/src/common/CommonGen.h b/src/common/CommonGen.h index dc99925d..63988bbc 100644 --- a/src/common/CommonGen.h +++ b/src/common/CommonGen.h @@ -148,10 +148,9 @@ enum class ExVersion : /////////////////////////////////////////////////////////// //GrandCompany.exd -enum class GrandCompany : - uint8_t +enum GrandCompany : uint8_t { - None = 0, + NoGc = 0, Maelstrom = 1, OrderoftheTwinAdder = 2, ImmortalFlames = 3, @@ -159,8 +158,7 @@ enum class GrandCompany : /////////////////////////////////////////////////////////// //GuardianDeity.exd -enum class GuardianDeity : - uint8_t +enum class GuardianDeity : uint8_t { HalonetheFury = 1, MenphinatheLover = 2, diff --git a/src/common/Config/ConfigMgr.cpp b/src/common/Config/ConfigMgr.cpp index 91f8ff42..1fdc9af0 100644 --- a/src/common/Config/ConfigMgr.cpp +++ b/src/common/Config/ConfigMgr.cpp @@ -3,6 +3,8 @@ #include #include +namespace fs = std::experimental::filesystem; + /** * Loads an ini file and parses it * @param configName the name of ini file relative to m_configFolderRoot to load alongside global.ini @@ -11,10 +13,14 @@ bool Core::ConfigMgr::loadConfig( const std::string& configName ) { // get global config - auto configDir = std::experimental::filesystem::path( m_configFolderRoot ); + auto configFile = fs::path( fs::path( m_configFolderRoot ) / configName ); - m_pInih = std::unique_ptr< INIReader >( new INIReader( - std::experimental::filesystem::path( configDir / configName ).string() ) ); + if( !fs::exists( configFile ) ) + { + copyDefaultConfig( configName ); + } + + m_pInih = std::unique_ptr< INIReader >( new INIReader( configFile.string() ) ); if( m_pInih->ParseError() < 0 ) return false; @@ -24,16 +30,16 @@ bool Core::ConfigMgr::loadConfig( const std::string& configName ) bool Core::ConfigMgr::copyDefaultConfig( const std::string& configName ) { - std::experimental::filesystem::path configPath( m_configFolderRoot ); + fs::path configPath( m_configFolderRoot ); configPath /= configName; - if( !std::experimental::filesystem::exists( configPath.string() + m_configDefaultSuffix ) ) + if( !fs::exists( configPath.string() + m_configDefaultSuffix ) ) { // no default file :( return false; } - std::experimental::filesystem::copy_file( configPath.string() + m_configDefaultSuffix, configPath ); + fs::copy_file( configPath.string() + m_configDefaultSuffix, configPath ); return true; } diff --git a/src/common/Logging/Logger.cpp b/src/common/Logging/Logger.cpp index 96225ebd..22534330 100644 --- a/src/common/Logging/Logger.cpp +++ b/src/common/Logging/Logger.cpp @@ -6,67 +6,76 @@ #include // #include +#include // or #include + +namespace fs = std::experimental::filesystem; namespace Core { + Logger::Logger() + { -Logger::Logger() -{ - -} - -Logger::~Logger() -{ - -} - -void Logger::setLogPath( const std::string& logPath ) -{ - m_logFile = logPath; -} - -void Logger::init() -{ - spdlog::init_thread_pool( 8192, 1 ); - - auto stdout_sink = std::make_shared< spdlog::sinks::stdout_color_sink_mt >(); - auto daily_sink = std::make_shared< spdlog::sinks::daily_file_sink_mt >( m_logFile + ".log", 0, 0 ); - - std::vector sinks { stdout_sink, daily_sink }; - - auto logger = std::make_shared< spdlog::async_logger >( "logger", sinks.begin(), sinks.end(), - spdlog::thread_pool(), spdlog::async_overflow_policy::block ); - - - spdlog::register_logger( logger ); - spdlog::set_pattern( "[%H:%M:%S.%e] [%^%l%$] %v" ); - spdlog::set_level( spdlog::level::debug ); - // always flush the log on criticial messages, otherwise it's done by libc - // see: https://github.com/gabime/spdlog/wiki/7.-Flush-policy - // nb: if the server crashes, log data can be missing from the file unless something logs critical just before it does - spdlog::flush_on( spdlog::level::critical ); -} - -void Logger::error( const std::string& text ) -{ - spdlog::get( "logger" )->error( text ); -} - -void Logger::info( const std::string& text ) -{ - spdlog::get( "logger" )->info( text ); -} - -void Logger::debug( const std::string& text ) -{ - spdlog::get( "logger" )->debug( text ); -} - -void Logger::fatal( const std::string& text ) -{ - spdlog::get( "logger" )->critical( text ); -} - + } + + Logger::~Logger() + { + + } + + void Logger::setLogPath( const std::string& logPath ) + { + auto pos = logPath.find_last_of( '/' ); + + if( pos != std::string::npos ) + { + std::string realPath = logPath.substr( 0, pos ); + fs::create_directories( realPath ); + } + + m_logFile = logPath; + } + + void Logger::init() + { + spdlog::init_thread_pool( 8192, 1 ); + + auto stdout_sink = std::make_shared< spdlog::sinks::stdout_color_sink_mt >(); + auto daily_sink = std::make_shared< spdlog::sinks::daily_file_sink_mt >( m_logFile + ".log", 0, 0 ); + + std::vector< spdlog::sink_ptr > sinks { stdout_sink, daily_sink }; + + auto logger = std::make_shared< spdlog::async_logger >( "logger", sinks.begin(), sinks.end(), + spdlog::thread_pool(), spdlog::async_overflow_policy::block ); + + + spdlog::register_logger( logger ); + spdlog::set_pattern( "[%H:%M:%S.%e] [%^%l%$] %v" ); + spdlog::set_level( spdlog::level::debug ); + // always flush the log on criticial messages, otherwise it's done by libc + // see: https://github.com/gabime/spdlog/wiki/7.-Flush-policy + // nb: if the server crashes, log data can be missing from the file unless something logs critical just before it does + spdlog::flush_on( spdlog::level::critical ); + } + + void Logger::error( const std::string& text ) + { + spdlog::get( "logger" )->error( text ); + } + + void Logger::info( const std::string& text ) + { + spdlog::get( "logger" )->info( text ); + } + + void Logger::debug( const std::string& text ) + { + spdlog::get( "logger" )->debug( text ); + } + + void Logger::fatal( const std::string& text ) + { + spdlog::get( "logger" )->critical( text ); + } } diff --git a/src/servers/Scripts/common/CmnDefHousingSignboard.cpp b/src/servers/Scripts/common/CmnDefHousingSignboard.cpp index 54cb765e..30831e8b 100644 --- a/src/servers/Scripts/common/CmnDefHousingSignboard.cpp +++ b/src/servers/Scripts/common/CmnDefHousingSignboard.cpp @@ -1,20 +1,36 @@ #include #include +#include +#include using namespace Core; -class CmnDefHousingSignboard : - public EventScript +class CmnDefHousingSignboard : public EventScript { public: - CmnDefHousingSignboard() : - EventScript( 721031 ) + CmnDefHousingSignboard() : EventScript( 721031 ) { } void Scene00000( Entity::Player& player ) { - player.playScene( getId(), 0, HIDE_HOTBAR, 0, 0 ); + auto callback = [ this ]( Entity::Player& player, const Event::SceneResult& result ) + { + // Purchase Land + if( result.param2 == 2 ) + { + auto activeLand = player.getActiveLand(); + auto territoryId = player.getTerritoryId(); + + auto pTerritory = player.getCurrentZone(); + auto pHousing = std::dynamic_pointer_cast< HousingZone >( pTerritory ); + + pHousing->playerPurchseLand( player, activeLand.plot, result.param2 ); + } + }; + + player.playScene( getId(), 0, HIDE_HOTBAR, 0, 0, callback ); + } void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override diff --git a/src/servers/sapphire_api/SapphireAPI.cpp b/src/servers/sapphire_api/SapphireAPI.cpp index 33602b13..1f981514 100644 --- a/src/servers/sapphire_api/SapphireAPI.cpp +++ b/src/servers/sapphire_api/SapphireAPI.cpp @@ -133,13 +133,16 @@ Core::Network::SapphireAPI::createCharacter( const int& accountId, const std::st for( auto& v : json["content"] ) { - for( auto& vs : v ) + if( v.is_array() ) { - tmpVector.push_back( vs.get< int >() ); + for( auto& vs : v ) + { + tmpVector.push_back( std::stoi( std::string( vs ) ) ); + } } - if( !v.empty() ) - tmpVector2.push_back( v.get< int >() ); + if( !v.empty() && !v.is_array() ) + tmpVector2.push_back( std::stoi( std::string( v ) ) ); } // leaving this in for now for reference diff --git a/src/servers/sapphire_api/main.cpp b/src/servers/sapphire_api/main.cpp index 5d627b64..90edbd05 100644 --- a/src/servers/sapphire_api/main.cpp +++ b/src/servers/sapphire_api/main.cpp @@ -488,9 +488,7 @@ void checkSession( shared_ptr< HttpServer::Response > response, shared_ptr< Http else { std::string json_string = nlohmann::json( { - { "result", result }, - { "result2", "penis" }, - { "result3", "wtf" } + { "result", result } } ).dump() ; *response << buildHttpResponse( 200, json_string, JSON ); diff --git a/src/servers/sapphire_lobby/RestConnector.cpp b/src/servers/sapphire_lobby/RestConnector.cpp index d17fe938..96ac9c6f 100644 --- a/src/servers/sapphire_lobby/RestConnector.cpp +++ b/src/servers/sapphire_lobby/RestConnector.cpp @@ -143,7 +143,7 @@ uint32_t Core::Network::RestConnector::getNextCharId() if( content.find( "invalid" ) == std::string::npos ) { - return json["result"].get< uint32_t >(); + return std::stoi( std::string( json["result"] ) ); } else { @@ -182,7 +182,7 @@ uint64_t Core::Network::RestConnector::getNextContentId() if( content.find( "invalid" ) == std::string::npos ) { - return json["result"].get< uint64_t >(); + return std::stoll( std::string( json["result"] ) ); } else { @@ -313,7 +313,7 @@ int Core::Network::RestConnector::createCharacter( char* sId, std::string name, } if( content.find( "invalid" ) == std::string::npos ) - return json["result"].get< int >(); + return std::stoi( json["result"].get< std::string >() ); return -1; } else diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index e989149f..ce7f00ed 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -15,6 +15,9 @@ #include "Zone/Zone.h" #include "Zone/ZonePosition.h" +#include "Zone//HousingMgr.h" +#include "Zone/Land.h" + #include "Network/GameConnection.h" #include "Network/PacketWrappers/ActorControlPacket142.h" #include "Network/PacketWrappers/ActorControlPacket143.h" @@ -91,8 +94,8 @@ Core::Entity::Player::Player() : for ( uint8_t i = 0; i < 5; i++ ) { - memset( &m_housePermission[i], 0xFF, 8 ); - memset( &m_housePermission[i].permissionMask, 0, 8 ); + memset( &m_landPermission[i], 0xFF, 8 ); + memset( &m_landPermission[i].permissionMask, 0, 8 ); } m_objSpawnIndexAllocator.init( MAX_DISPLAYED_EOBJS ); @@ -1574,6 +1577,12 @@ void Core::Entity::Player::sendZonePackets() sendItemLevel(); } + auto pHousingMgr = g_fw.get< HousingMgr >(); + if( Core::LandPtr pLand = pHousingMgr->getLandByOwnerId( getId() ) ) + { + setLandPermissions( LandPermissionSlot::Private, 0x0B, pLand->getLandId(), pLand->getWardNum(), pLand->getZoneId() ); + } + sendLandPermissions(); auto initZonePacket = makeZonePacket< FFXIVIpcInitZone >( getId() ); @@ -1752,24 +1761,25 @@ bool Core::Entity::Player::isOnEnterEventDone() const return m_onEnterEventDone; } -void Core::Entity::Player::setLandPermissions( uint8_t permissionSet, uint32_t permissionMask, int16_t landSetId, int16_t wardNum, int16_t zoneId ) +void Core::Entity::Player::setLandPermissions( uint8_t permissionSet, uint32_t permissionMask, int16_t landId, int16_t wardNum, int16_t zoneId ) { - m_housePermission[permissionSet].landSetId = landSetId; - m_housePermission[permissionSet].permissionMask = permissionMask; - m_housePermission[permissionSet].wardNum = wardNum; - m_housePermission[permissionSet].worldId = 67; - m_housePermission[permissionSet].unkown1 = 0; + m_landPermission[permissionSet].landId = landId; + m_landPermission[permissionSet].permissionMask = permissionMask; + m_landPermission[permissionSet].wardNum = wardNum; + m_landPermission[permissionSet].zoneId = zoneId; + m_landPermission[permissionSet].worldId = 67; + m_landPermission[permissionSet].unkown1 = 0; } void Core::Entity::Player::sendLandPermissions() { auto landPermissions = makeZonePacket< FFXIVIpcLandPermission >( getId() ); - landPermissions->data().freeCompanyHouse = m_housePermission[Common::LandPermissionSlot::FreeCompany]; - landPermissions->data().privateHouse = m_housePermission[Common::LandPermissionSlot::Private]; - landPermissions->data().apartment = m_housePermission[Common::LandPermissionSlot::Apartment]; - landPermissions->data().sharedHouse[0] = m_housePermission[Common::LandPermissionSlot::SharedHouse1]; - landPermissions->data().sharedHouse[1] = m_housePermission[Common::LandPermissionSlot::SharedHouse2]; + landPermissions->data().freeCompanyHouse = m_landPermission[Common::LandPermissionSlot::FreeCompany]; + landPermissions->data().privateHouse = m_landPermission[Common::LandPermissionSlot::Private]; + landPermissions->data().apartment = m_landPermission[Common::LandPermissionSlot::Apartment]; + landPermissions->data().sharedHouse[0] = m_landPermission[Common::LandPermissionSlot::SharedHouse1]; + landPermissions->data().sharedHouse[1] = m_landPermission[Common::LandPermissionSlot::SharedHouse2]; memset( &landPermissions->data().unkownHouse, 0xFF, 8 ); memset( &landPermissions->data().unkownHouse.permissionMask, 0, 8 ); landPermissions->data().unkownHouse.permissionMask = 2; diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index f0aefd21..d1aa1e22 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -763,7 +763,7 @@ namespace Core::Entity // Housing Handling ////////////////////////////////////////////////////////////////////////////////////////////////////// - void setLandPermissions( uint8_t permissionSet, uint32_t permissionMask, int16_t landSetId, int16_t wardNum, int16_t zoneId ); + void setLandPermissions( uint8_t permissionSet, uint32_t permissionMask, int16_t landId, int16_t wardNum, int16_t zoneId ); void sendLandPermissions(); @@ -911,6 +911,10 @@ namespace Core::Entity uint8_t getFreeSlotsInBags(); + void setActiveLand( uint8_t land, uint8_t ward ); + Common::ActiveLand getActiveLand() const; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// uint64_t m_lastMoveTime; @@ -1020,7 +1024,9 @@ namespace Core::Entity uint8_t m_searchSelectClass; // class selected to show up in profile // housing info - Common::LandPermissionSet m_housePermission[5]; + Common::LandPermissionSet m_landPermission[5]; + + Common::ActiveLand m_activeLand; // gc info uint8_t m_gc; diff --git a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp index 630dcc39..11fa3f08 100644 --- a/src/servers/sapphire_zone/Actor/PlayerInventory.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerInventory.cpp @@ -822,6 +822,17 @@ void Core::Entity::Player::discardItem( uint16_t fromInventoryId, uint8_t fromSl queuePacket( invTransFinPacket ); } +void Core::Entity::Player::setActiveLand( uint8_t land, uint8_t ward ) +{ + m_activeLand.plot = land; + m_activeLand.ward = ward; +} + +Core::Common::ActiveLand Core::Entity::Player::getActiveLand() const +{ + return m_activeLand; +} + uint16_t Core::Entity::Player::calculateEquippedGearItemLevel() { uint32_t iLvlResult = 0; diff --git a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp index cb30f491..cbd7873a 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp @@ -311,12 +311,15 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR } case ClientTriggerType::RequestHousingSign: { + auto plotPricePacket = makeZonePacket< Server::FFXIVIpcLandPriceUpdate >( player.getId() ); uint8_t ward = ( param12 & 0xFF00 ) >> 8; uint8_t plot = ( param12 & 0xFF ); pLog->debug( " Ward: " + std::to_string( ward ) + " Plot: " + std::to_string( plot ) ); + player.setActiveLand( plot, ward ); + auto zone = player.getCurrentZone(); auto hZone = std::dynamic_pointer_cast< HousingZone >( zone ); diff --git a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp index c61c7730..34293a13 100644 --- a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp @@ -434,6 +434,15 @@ void Core::Network::GameConnection::finishLoadingHandler( const Core::Network::P Entity::Player& player ) { player.sendQuestInfo(); + + // TODO: load and save this data instead of hardcoding + auto gcPacket = makeZonePacket< FFXIVGCAffiliation >( player.getId() ); + gcPacket->data().gcId = player.getGc(); + gcPacket->data().gcRank[ 0 ] = player.getGcRankArray()[ 0 ]; + gcPacket->data().gcRank[ 1 ] = player.getGcRankArray()[ 1 ]; + gcPacket->data().gcRank[ 2 ] = player.getGcRankArray()[ 2 ]; + player.queuePacket( gcPacket ); + player.getCurrentZone()->onFinishLoading( player ); // player is done zoning diff --git a/src/servers/sapphire_zone/Session.cpp b/src/servers/sapphire_zone/Session.cpp index 66e0b06b..3d5070de 100644 --- a/src/servers/sapphire_zone/Session.cpp +++ b/src/servers/sapphire_zone/Session.cpp @@ -77,8 +77,12 @@ void Core::Session::close() // remove the session from the player if( m_pPlayer ) + { + // do one last update to db + m_pPlayer->updateSql(); // reset the zone, so the zone handler knows to remove the actor m_pPlayer->setCurrentZone( nullptr ); + } } uint32_t Core::Session::getId() const diff --git a/src/servers/sapphire_zone/Zone/HousingMgr.cpp b/src/servers/sapphire_zone/Zone/HousingMgr.cpp new file mode 100644 index 00000000..700d372a --- /dev/null +++ b/src/servers/sapphire_zone/Zone/HousingMgr.cpp @@ -0,0 +1,70 @@ +#include "HousingMgr.h" +#include "HousingMgr.h" +#include +#include +#include + +#include + +#include "Actor/Player.h" + +#include "Zone.h" +#include "HousingZone.h" +#include "HousingMgr.h" +#include "Land.h" +#include "Framework.h" + +extern Core::Framework g_fw; + +Core::HousingMgr::HousingMgr() : + m_lastLandId( 0 ) +{ + +} + +Core::HousingMgr::~HousingMgr() +{ + +} + +bool Core::HousingMgr::init() +{ + + return true; +} + +uint16_t Core::HousingMgr::getNexLandId() +{ + return ++m_lastLandId; +} + +void Core::HousingMgr::insertHousingZone( Core::Data::HousingZonePtr hZone ) +{ + uint16_t id = getNexLandId(); + m_housingZonePtrMap[id] = hZone; +} + +Core::Data::HousingZonePtr Core::HousingMgr::getHousingZone( uint16_t id ) +{ + auto it = m_housingZonePtrMap.find( id ); + if( it == m_housingZonePtrMap.end() ) + return nullptr; + + return it->second; +} + +Core::LandPtr Core::HousingMgr::getLandByOwnerId( uint32_t id ) +{ + for( const auto& hZoneIt : m_housingZonePtrMap ) + { + auto pHousingZone = hZoneIt.second; + for( uint8_t landId = 0;landId < 60;landId++ ) + { + if( pHousingZone->getLand( landId )->getPlayerOwner() == id ) + { + return pHousingZone->getLand( landId ); + } + } + } + return nullptr; +} diff --git a/src/servers/sapphire_zone/Zone/HousingMgr.h b/src/servers/sapphire_zone/Zone/HousingMgr.h new file mode 100644 index 00000000..e2981ade --- /dev/null +++ b/src/servers/sapphire_zone/Zone/HousingMgr.h @@ -0,0 +1,38 @@ +#ifndef SAPPHIRE_HOUSINGMGR_H +#define SAPPHIRE_HOUSINGMGR_H + +#include "Forwards.h" +#include "HousingZone.h" +#include +#include + +namespace Core +{ + namespace Data + { + using HousingZonePtr = std::shared_ptr< HousingZone >; + } + + class HousingMgr + { + + public: + HousingMgr(); + virtual ~HousingMgr(); + + bool init(); + + uint16_t getNexLandId(); + void insertHousingZone( Core::Data::HousingZonePtr hZone ); + Core::Data::HousingZonePtr getHousingZone( uint16_t id ); + Core::LandPtr getLandByOwnerId( uint32_t id ); + + private: + using HousingZonePtrMap = std::unordered_map< uint16_t, Core::Data::HousingZonePtr >; + uint16_t m_lastLandId; + HousingZonePtrMap m_housingZonePtrMap; + }; + +} + +#endif // SAPPHIRE_HOUSINGMGR_H diff --git a/src/servers/sapphire_zone/Zone/HousingZone.cpp b/src/servers/sapphire_zone/Zone/HousingZone.cpp index 22ee225e..1a0dd152 100644 --- a/src/servers/sapphire_zone/Zone/HousingZone.cpp +++ b/src/servers/sapphire_zone/Zone/HousingZone.cpp @@ -13,6 +13,7 @@ #include "Forwards.h" #include "HousingZone.h" +#include "HousingMgr.h" #include "Framework.h" extern Core::Framework g_fw; @@ -61,10 +62,12 @@ bool Core::HousingZone::init() for( landId = 0; landId < 60; landId++ ) { auto pObject = make_Land( m_territoryTypeId, getWardNum(), landId, m_landSetId, info ); - pObject->setHouseSize( 1 ); m_landPtrMap[ landId ] = pObject; } + auto pHousingMgr = g_fw.get< HousingMgr >(); + pHousingMgr->insertHousingZone( (HousingZonePtr)this ); + return true; } @@ -100,13 +103,14 @@ void Core::HousingZone::onPlayerZoneIn( Entity::Player& player ) } auto landSetMap = makeZonePacket< FFXIVIpcLandSetMap >( player.getId() ); - landSetMap->data().subdivision = isPlayerSubInstance( player ) == false ? 1 : 2; + landSetMap->data().subdivision = isPlayerSubInstance( player ) == false ? 2 : 1; uint8_t startIndex = isPlayerSubInstance( player ) == false ? 0 : 30; for( uint8_t i = startIndex, count = 0; i < ( startIndex + 30 ); i++, count++ ) { landSetMap->data().landInfo[ count ].status = 1; //memcpy( , &getLand( i )->getLand(), sizeof( Common::LandStruct ) ); } + player.queuePacket( landSetMap ); } @@ -150,6 +154,31 @@ bool Core::HousingZone::isPlayerSubInstance( Entity::Player& player ) return player.getPos().x < -15000.0f; //ToDo: get correct pos } +void Core::HousingZone::playerPurchseLand( Entity::Player & player, uint8_t plot, uint8_t state ) +{ + uint32_t plotPrice = getLand( plot )->getCurrentPrice(); + if( plotPrice <= player.getCurrency( CurrencyType::Gil ) ) + { + auto pHousing = std::dynamic_pointer_cast< HousingZone >( player.getCurrentZone() ); + if( state == 1 ) //TODO: add Free company purchase + player.sendDebug( "Free company house purchase aren't supported at this time." ); + if( state == 2 ) //Private Purchase + { + getLand( plot )->setPlayerOwner( player.getId() ); + getLand( plot )->setState( HouseState::sold ); + + player.removeCurrency( CurrencyType::Gil, plotPrice ); + player.setLandPermissions( LandPermissionSlot::Private, 0x0B, plot, pHousing->getWardNum(), pHousing->getTerritoryTypeId() ); + player.sendLandPermissions(); + + getLand( plot )->UpdateLandDb(); + sendLandUpdate( plot ); + } + } + //else + //TOD: add error msg - insufficient gil +} + void Core::HousingZone::onUpdate( uint32_t currTime ) { for( uint8_t i = 0; i < 60; i++ ) diff --git a/src/servers/sapphire_zone/Zone/HousingZone.h b/src/servers/sapphire_zone/Zone/HousingZone.h index c2c6619f..47b3a490 100644 --- a/src/servers/sapphire_zone/Zone/HousingZone.h +++ b/src/servers/sapphire_zone/Zone/HousingZone.h @@ -26,6 +26,8 @@ namespace Core void sendLandUpdate( uint8_t landId ); bool isPlayerSubInstance( Entity::Player& player ); + void playerPurchseLand( Entity::Player& player, uint8_t plot, uint8_t state ); + /* returns current ward number for this zone */ uint8_t getWardNum() const; diff --git a/src/servers/sapphire_zone/Zone/Land.cpp b/src/servers/sapphire_zone/Zone/Land.cpp index 44828849..96b7d6eb 100644 --- a/src/servers/sapphire_zone/Zone/Land.cpp +++ b/src/servers/sapphire_zone/Zone/Land.cpp @@ -32,11 +32,13 @@ Core::Land::Land( uint16_t zoneId, uint8_t wardNum, uint8_t landId, uint32_t lan m_landId( landId ), m_currentPrice( 0 ), m_minPrice( 0 ), - m_nextDrop( 0 ), + m_nextDrop( Util::getTimeSeconds() + 21600 ), + m_ownerPlayerId( 0 ), m_landSetId( landSetId ), m_landInfo( info ) { memset( &m_land, 0x00, sizeof( LandStruct ) ); + memset( &m_tag, 0x00, 3 ); load(); } @@ -47,11 +49,9 @@ Core::Land::~Land() void Core::Land::load() { - m_land.houseState = HouseState::forSale; - auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >(); - auto res = pDb->query( "SELECT * FROM land WHERE landsetid = " + std::to_string( m_landSetId ) + " " - "AND landid = " + std::to_string( m_landId ) ); + auto res = pDb->query( "SELECT * FROM land WHERE LandSetId = " + std::to_string( m_landSetId ) + " " + "AND LandId = " + std::to_string( m_landId ) ); if( !res->next() ) { pDb->directExecute( "INSERT INTO land ( landsetid, landid, size, status, landprice ) " @@ -65,9 +65,11 @@ void Core::Land::load() } else { - m_land.houseSize = res->getUInt( "size" ); - m_land.houseState = res->getUInt( "status" ); - m_currentPrice = res->getUInt( "LandPrice" );; + m_land.houseSize = res->getUInt( "Size" ); + m_land.houseState = res->getUInt( "Status" ); + m_currentPrice = res->getUInt( "LandPrice" ); + m_ownerPlayerId = res->getUInt( "OwnerId" ); + m_minPrice = m_landInfo->minPrices[ m_landId ]; } init(); // setPreset( 262145 ); @@ -170,6 +172,26 @@ uint8_t Core::Land::getSharing() return m_land.iconAddIcon; } +uint32_t Core::Land::getLandSetId() +{ + return m_landSetId; +} + +uint8_t Core::Land::getWardNum() +{ + return m_wardNum; +} + +uint8_t Core::Land::getLandId() +{ + return m_landId; +} + +uint16_t Core::Land::getZoneId() +{ + return m_zoneId; +} + //Free Comapny void Core::Land::setFreeCompany( uint32_t id, uint32_t icon, uint32_t color ) { @@ -241,6 +263,16 @@ uint32_t Core::Land::getDevaluationTime() return m_nextDrop - Util::getTimeSeconds(); } +void Core::Land::setLandTag( uint8_t slot, uint8_t tag ) +{ + m_tag[ slot ] = tag; +} + +uint8_t Core::Land::getLandTag( uint8_t slot ) +{ + return m_tag[ slot ]; +} + void Core::Land::init() { @@ -260,15 +292,16 @@ void Core::Land::init() } } -void Core::Land::UpdateDatabase() +void Core::Land::UpdateLandDb() { - /*auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >(); - std::string exec = "UPDATE land SET landset='" + - std::string( reinterpret_cast< const char* >( &m_land ) ) + "', nextDrop=" + - std::to_string( m_nextDrop ) + ", currentPrice=" + - std::to_string( m_currentPrice ) + - " WHERE Id =" + std::to_string( m_landKey ); - pDb->execute( exec );*/ + auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >(); + pDb->directExecute( "UPDATE land SET status = " + std::to_string( m_land.houseState ) + + ", LandPrice = " + std::to_string( getCurrentPrice() ) + + ", UpdateTime = " + std::to_string( getDevaluationTime() ) + + ", OwnerId = " + std::to_string( getPlayerOwner() ) + + ", HouseId = " + std::to_string( 0 ) //TODO: add house id + + " WHERE LandSetId = " + std::to_string( m_landSetId ) + + " AND LandId = " + std::to_string( m_landId ) + ";" ); } void Core::Land::Update( uint32_t currTime ) @@ -279,7 +312,7 @@ void Core::Land::Update( uint32_t currTime ) { m_nextDrop = currTime + 21600; m_currentPrice = ( m_currentPrice / 100 ) * 99.58; + UpdateLandDb(); } - UpdateDatabase(); } } \ No newline at end of file diff --git a/src/servers/sapphire_zone/Zone/Land.h b/src/servers/sapphire_zone/Zone/Land.h index cc1b6ac5..75d44ea4 100644 --- a/src/servers/sapphire_zone/Zone/Land.h +++ b/src/servers/sapphire_zone/Zone/Land.h @@ -30,6 +30,10 @@ namespace Core uint8_t getState(); uint8_t getOwnership(); uint8_t getSharing(); + uint32_t getLandSetId(); + uint8_t getWardNum(); + uint8_t getLandId(); + uint16_t getZoneId(); //Free Comapny void setFreeCompany( uint32_t id, uint32_t icon, uint32_t color ); @@ -50,7 +54,7 @@ namespace Core uint32_t getPlayerOwner(); //Housing Functions void setPreset( uint32_t itemId ); - void UpdateDatabase(); + void UpdateLandDb(); void Update( uint32_t currTime ); const Common::LandStruct& getLand(); @@ -59,6 +63,10 @@ namespace Core uint32_t getCurrentPrice() const; uint32_t getDevaluationTime(); + //House tags + void setLandTag( uint8_t slot, uint8_t tag ); + uint8_t getLandTag( uint8_t slot ); + private: uint16_t convertItemIdToHousingItemId( uint16_t itemId ); void init(); @@ -81,6 +89,9 @@ namespace Core uint32_t m_nextDrop; uint32_t m_currentPrice; uint32_t m_minPrice; + + //Tags + uint8_t m_tag[3]; }; } diff --git a/src/servers/sapphire_zone/mainGameServer.cpp b/src/servers/sapphire_zone/mainGameServer.cpp index b45e71b0..a878b8b4 100644 --- a/src/servers/sapphire_zone/mainGameServer.cpp +++ b/src/servers/sapphire_zone/mainGameServer.cpp @@ -9,6 +9,7 @@ #include #include "Linkshell/LinkshellMgr.h" #include "Zone/TerritoryMgr.h" +#include "Zone/HousingMgr.h" #include "DebugCommand/DebugCommandHandler.h" #include @@ -25,11 +26,12 @@ bool setupFramework() auto pScript = std::make_shared< Scripting::ScriptMgr >(); auto pDb = std::make_shared< Db::DbWorkerPool< Db::ZoneDbConnection > >(); auto pLsMgr = std::make_shared< LinkshellMgr >(); + auto pHousingMgr = std::make_shared< HousingMgr >(); auto pTeriMgr = std::make_shared< TerritoryMgr >(); auto pDebugCom = std::make_shared< DebugCommandHandler >(); auto pConfig = std::make_shared< ConfigMgr >(); - pLogger->setLogPath( "log/SapphireZone_" ); + pLogger->setLogPath( "log/SapphireZone" ); pLogger->init(); g_fw.set< ServerZone >( pServer ); @@ -38,6 +40,7 @@ bool setupFramework() g_fw.set< Scripting::ScriptMgr >( pScript ); g_fw.set< Db::DbWorkerPool< Db::ZoneDbConnection > >( pDb ); g_fw.set< LinkshellMgr >( pLsMgr ); + g_fw.set< HousingMgr >( pHousingMgr ); g_fw.set< TerritoryMgr >( pTeriMgr ); g_fw.set< DebugCommandHandler >( pDebugCom ); g_fw.set< ConfigMgr >( pConfig );