mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 22:57:45 +00:00
House fixes
This commit is contained in:
parent
07750857bf
commit
dadc8184e9
20 changed files with 378 additions and 119 deletions
|
@ -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,
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <fstream>
|
||||
#include <experimental/filesystem>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -6,67 +6,76 @@
|
|||
#include <spdlog/sinks/daily_file_sink.h>
|
||||
|
||||
// #include <iostream>
|
||||
#include <experimental/filesystem> // or #include <filesystem>
|
||||
|
||||
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<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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,20 +1,36 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Actor/Player.h>
|
||||
#include <Zone/Zone.h>
|
||||
#include <Zone/HousingZone.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
70
src/servers/sapphire_zone/Zone/HousingMgr.cpp
Normal file
70
src/servers/sapphire_zone/Zone/HousingMgr.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include "HousingMgr.h"
|
||||
#include "HousingMgr.h"
|
||||
#include <Logging/Logger.h>
|
||||
#include <Database/DatabaseDef.h>
|
||||
#include <Exd/ExdDataGenerated.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#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;
|
||||
}
|
38
src/servers/sapphire_zone/Zone/HousingMgr.h
Normal file
38
src/servers/sapphire_zone/Zone/HousingMgr.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef SAPPHIRE_HOUSINGMGR_H
|
||||
#define SAPPHIRE_HOUSINGMGR_H
|
||||
|
||||
#include "Forwards.h"
|
||||
#include "HousingZone.h"
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
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
|
|
@ -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++ )
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <Database/DbWorkerPool.h>
|
||||
#include "Linkshell/LinkshellMgr.h"
|
||||
#include "Zone/TerritoryMgr.h"
|
||||
#include "Zone/HousingMgr.h"
|
||||
#include "DebugCommand/DebugCommandHandler.h"
|
||||
|
||||
#include <Config/ConfigMgr.h>
|
||||
|
@ -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 );
|
||||
|
|
Loading…
Add table
Reference in a new issue