mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 14:57:44 +00:00
commit
3c624f6e76
40 changed files with 6454 additions and 839 deletions
|
@ -37,7 +37,7 @@ add_subdirectory( "deps/mysqlConnector" )
|
|||
add_subdirectory( "src/common" )
|
||||
|
||||
add_subdirectory( "src/servers" )
|
||||
#add_subdirectory( "src/dbm" )
|
||||
add_subdirectory( "src/dbm" )
|
||||
|
||||
add_subdirectory( "src/tools/exd_common_gen" )
|
||||
add_subdirectory( "src/tools/exd_struct_gen" )
|
||||
|
|
106
deps/datReader/Exd.cpp
vendored
106
deps/datReader/Exd.cpp
vendored
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "bparse.h"
|
||||
#include "stream.h"
|
||||
|
||||
#include <fstream>
|
||||
#include "Exh.h"
|
||||
|
||||
using xiv::utils::bparse::extract;
|
||||
|
@ -58,7 +58,7 @@ namespace xiv
|
|||
for ( auto &file_ptr : _files )
|
||||
{
|
||||
// Get a stream
|
||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||
|
||||
// Extract the header and skip to the record indices
|
||||
|
@ -81,6 +81,105 @@ namespace xiv
|
|||
{
|
||||
}
|
||||
|
||||
const std::vector<Field> Exd::get_row( uint32_t id, uint32_t subRow )
|
||||
{
|
||||
|
||||
auto cacheEntryIt = _idCache.find( id );
|
||||
if( cacheEntryIt == _idCache.end() )
|
||||
throw std::runtime_error( "Id not found: " + std::to_string( id ) );
|
||||
|
||||
// Iterates over all the files
|
||||
const uint32_t member_count = _exh->get_members().size();
|
||||
auto& file_ptr = cacheEntryIt->second.file;
|
||||
|
||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||
|
||||
// Get the vector fields for the given record and preallocate it
|
||||
auto fields = _data[id];
|
||||
fields.reserve( member_count );
|
||||
iss.seekg( cacheEntryIt->second.offset + 6 );
|
||||
|
||||
uint8_t subRows = *reinterpret_cast< uint8_t* >( &dataCpy[ cacheEntryIt->second.offset + 5 ] );
|
||||
|
||||
if( subRow >= subRows )
|
||||
throw std::runtime_error( "Out of bounds sub-row!" );
|
||||
|
||||
int offset = cacheEntryIt->second.offset + 6 + ( subRow * _exh->get_header().data_offset + 2 * ( subRow + 1 ) );
|
||||
|
||||
for( auto& member_entry : _exh->get_exh_members() )
|
||||
{
|
||||
// Seek to the position of the member to extract.
|
||||
// 6 is because we have uint32_t/uint16_t at the start of each record
|
||||
iss.seekg( offset + member_entry.offset );
|
||||
|
||||
// Switch depending on the type to extract
|
||||
switch( member_entry.type )
|
||||
{
|
||||
case DataType::string:
|
||||
// Extract the offset to the actual string
|
||||
// Seek to it then extract the actual string
|
||||
{
|
||||
throw std::runtime_error( "String not implemented for variant 2!" );
|
||||
//auto string_offset = extract<uint32_t>( iss, "string_offset", false );
|
||||
//iss.seekg( cacheEntryIt->second.offset + 6 + _exh->get_header().data_offset + string_offset );
|
||||
//fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case DataType::boolean:
|
||||
fields.emplace_back( extract<bool>( iss, "bool" ) );
|
||||
break;
|
||||
|
||||
case DataType::int8:
|
||||
fields.emplace_back( extract<int8_t>( iss, "int8_t" ) );
|
||||
break;
|
||||
|
||||
case DataType::uint8:
|
||||
fields.emplace_back( extract<uint8_t>( iss, "uint8_t" ) );
|
||||
break;
|
||||
|
||||
case DataType::int16:
|
||||
fields.emplace_back( extract<int16_t>( iss, "int16_t", false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint16:
|
||||
fields.emplace_back( extract<uint16_t>( iss, "uint16_t", false ) );
|
||||
break;
|
||||
|
||||
case DataType::int32:
|
||||
fields.emplace_back( extract<int32_t>( iss, "int32_t", false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint32:
|
||||
fields.emplace_back( extract<uint32_t>( iss, "uint32_t", false ) );
|
||||
break;
|
||||
|
||||
case DataType::float32:
|
||||
fields.emplace_back( extract<float>( iss, "float", false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint64:
|
||||
fields.emplace_back( extract<uint64_t>( iss, "uint64_t", false ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
auto type = static_cast< uint16_t >( member_entry.type );
|
||||
if( type < 0x19 || type > 0x20 )
|
||||
throw std::runtime_error("Unknown DataType: " + std::to_string( type ));
|
||||
uint64_t val = extract< uint64_t >( iss, "bool" );
|
||||
int32_t shift = type - 0x19;
|
||||
int32_t i = 1 << shift;
|
||||
val &= i;
|
||||
fields.emplace_back( ( val & i ) == i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
|
||||
}
|
||||
|
||||
|
||||
const std::vector<Field> Exd::get_row( uint32_t id )
|
||||
{
|
||||
|
||||
|
@ -98,6 +197,9 @@ namespace xiv
|
|||
// Get the vector fields for the given record and preallocate it
|
||||
auto fields = _data[id];
|
||||
fields.reserve( member_count );
|
||||
iss.seekg( cacheEntryIt->second.offset + 6 );
|
||||
|
||||
uint8_t subRows = *reinterpret_cast< uint8_t* >( &dataCpy[ cacheEntryIt->second.offset + 5 ] );
|
||||
|
||||
for( auto& member_entry : _exh->get_exh_members() )
|
||||
{
|
||||
|
|
2
deps/datReader/Exd.h
vendored
2
deps/datReader/Exd.h
vendored
|
@ -47,6 +47,8 @@ public:
|
|||
// Get a row by its id
|
||||
const std::vector<Field> get_row(uint32_t id);
|
||||
|
||||
// Get a row by its id and sub-row
|
||||
const std::vector<Field> get_row(uint32_t id, uint32_t subRow);
|
||||
// Get all rows
|
||||
const std::map<uint32_t, std::vector<Field>>& get_rows();
|
||||
|
||||
|
|
3
deps/datReader/Exh.h
vendored
3
deps/datReader/Exh.h
vendored
|
@ -31,6 +31,9 @@ namespace xiv
|
|||
uint16_t field_count;
|
||||
uint16_t exd_count;
|
||||
uint16_t language_count;
|
||||
uint16_t unknown1;
|
||||
uint8_t u2;
|
||||
uint8_t variant;
|
||||
};
|
||||
|
||||
struct ExhMember
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
ALTER TABLE `land` ADD `Type` SMALLINT(6) NOT NULL DEFAULT '0' AFTER `LandId`;
|
||||
ALTER TABLE `house` ADD `HouseName` binary(23) DEFAULT "" AFTER `Comment`;
|
||||
ALTER TABLE `house` ADD `HouseName` binary(23) DEFAULT "" AFTER `Comment`;
|
||||
ALTER TABLE `house` ADD `HousePartModels` BINARY(32) DEFAULT "" AFTER `Endorsements`;
|
||||
ALTER TABLE `house` ADD `HousePartColours` BINARY(8) DEFAULT "" AFTER `HousePartModels`;
|
|
@ -805,8 +805,8 @@ namespace Core::Common
|
|||
none,
|
||||
forSale,
|
||||
sold,
|
||||
privateHouse,
|
||||
fcHouse,
|
||||
privateHouse
|
||||
};
|
||||
|
||||
enum HouseIconAdd : uint8_t
|
||||
|
|
|
@ -181,8 +181,8 @@ void Core::Db::ZoneDbConnection::doPrepareStatements()
|
|||
"secWeaponModel, aggressionMode, enemyType, pose, "
|
||||
"modelChara, displayFlags, Look, Models "
|
||||
"FROM bnpctemplate WHERE 1;",
|
||||
CONNECTION_BOTH);
|
||||
|
||||
CONNECTION_BOTH );
|
||||
|
||||
prepareStatement( CHARA_ITEMGLOBAL_UP,
|
||||
"UPDATE charaglobalitem SET stack = ?, durability = ?, stain = ? WHERE ItemId = ?;",
|
||||
CONNECTION_BOTH );
|
||||
|
@ -191,6 +191,15 @@ void Core::Db::ZoneDbConnection::doPrepareStatements()
|
|||
"UPDATE charaglobalitem SET IS_DELETE = 1 WHERE ItemId = ?;",
|
||||
CONNECTION_BOTH );
|
||||
|
||||
/// HOUSING
|
||||
prepareStatement( HOUSING_HOUSE_INS,
|
||||
"INSERT INTO house ( LandSetId, HouseId ) VALUES ( ?, ? );",
|
||||
CONNECTION_BOTH );
|
||||
|
||||
prepareStatement( HOUSING_HOUSE_UP,
|
||||
"UPDATE house SET BuildTime = ?, Aetheryte = ?, Comment = ?, HouseName = ?, Endorsements = ?, HousePartModels = ?, HousePartColours = ? WHERE HouseId = ?;",
|
||||
CONNECTION_BOTH );
|
||||
|
||||
/*prepareStatement( LAND_INS,
|
||||
"INSERT INTO land ( LandSetId ) VALUES ( ? );",
|
||||
CONNECTION_BOTH );
|
||||
|
|
|
@ -81,6 +81,9 @@ namespace Core::Db
|
|||
LAND_INS,
|
||||
LAND_SEL,
|
||||
LAND_UP,
|
||||
HOUSING_HOUSE_INS,
|
||||
HOUSING_HOUSE_UP,
|
||||
HOUSING_HOUSE_DEL,
|
||||
|
||||
|
||||
MAX_STATEMENTS
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -290,12 +290,18 @@ enum ActorControlType : uint16_t
|
|||
AchievementList = 0x3E9,
|
||||
|
||||
RequestHousingBuildPreset = 0x44C,
|
||||
RequestEstateHallRemoval = 0x44F,
|
||||
RequestBuildPreset = 0x450, // no idea what this is, it gets sent with BuildPresetHandler and has the plot id in param1
|
||||
RequestLandSignFree = 0x451,
|
||||
RequestLandSignOwned = 0x452,
|
||||
RequestWardLandInfo = 0x453,
|
||||
RequestLandRelinquish = 0x454,
|
||||
RequestEstateRename = 0x45A,
|
||||
RequestEstateEditGreeting = 0x45B,
|
||||
RequestEstateGreeting = 0x45C, // sends FFXIVIpcHousingEstateGreeting in return
|
||||
RequestEstateEditGuestAccessSettings = 0x45D,
|
||||
RequestEstateTagSettings = 0x45F,
|
||||
|
||||
RequestHousingItemUI = 0x463,
|
||||
RequestSharedEstateSettings = 0x46F,
|
||||
|
||||
|
|
|
@ -1607,7 +1607,7 @@ struct LandStruct
|
|||
uint32_t fcIcon;// 12
|
||||
uint32_t fcIconColor; // 16
|
||||
uint16_t housePart[ 8 ]; // 34
|
||||
uint8_t color[ 8 ]; // 36
|
||||
uint8_t houseColour[ 8 ]; // 36
|
||||
};
|
||||
|
||||
struct FFXIVIpcLandUpdate : FFXIVIpcBasePacket< LandUpdate >
|
||||
|
|
31
src/dbm/CMakeLists.txt
Normal file
31
src/dbm/CMakeLists.txt
Normal file
|
@ -0,0 +1,31 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_policy(SET CMP0015 NEW)
|
||||
project(sapphire_dbm)
|
||||
|
||||
file(GLOB SERVER_PUBLIC_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*" )
|
||||
file(GLOB SERVER_SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}*.c*")
|
||||
|
||||
add_executable(sapphire_dbm ${SERVER_PUBLIC_INCLUDE_FILES} ${SERVER_SOURCE_FILES})
|
||||
|
||||
set_target_properties(sapphire_dbm PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CXX_EXTENSIONS ON
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/"
|
||||
)
|
||||
|
||||
target_include_directories( sapphire_dbm
|
||||
PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/"
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../" )
|
||||
target_link_libraries( sapphire_dbm PRIVATE mysqlConnector common xivdat )
|
||||
if (UNIX)
|
||||
target_link_libraries( sapphire_dbm PRIVATE stdc++fs )
|
||||
else()
|
||||
target_link_libraries( sapphire_dbm PRIVATE mysql )
|
||||
endif()
|
||||
|
136
src/dbm/DbManager.cpp
Normal file
136
src/dbm/DbManager.cpp
Normal file
|
@ -0,0 +1,136 @@
|
|||
#include "DbManager.h"
|
||||
#include <MySqlConnector.h>
|
||||
DbManager::DbManager( const std::string& host, const std::string& database, const std::string& user, const std::string& pw, uint16_t port ) :
|
||||
m_host( host ),
|
||||
m_database( database ),
|
||||
m_user( user ),
|
||||
m_password( pw ),
|
||||
m_port( port )
|
||||
{
|
||||
}
|
||||
|
||||
DbManager::~DbManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool DbManager::execute( const std::string& sql )
|
||||
{
|
||||
try
|
||||
{
|
||||
auto stmt = m_pConnection->createStatement();
|
||||
bool result = stmt->execute( sql );
|
||||
return result;
|
||||
}
|
||||
catch( std::runtime_error& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DbManager::connect()
|
||||
{
|
||||
std::shared_ptr< Mysql::MySqlBase > base( new Mysql::MySqlBase() );
|
||||
Mysql::optionMap options;
|
||||
options[ Mysql::MYSQL_OPT_RECONNECT ] = "1";
|
||||
options[ Mysql::MYSQL_SET_CHARSET_NAME ] = "utf8";
|
||||
|
||||
try
|
||||
{
|
||||
m_pConnection = base->connect( m_host, m_user, m_password, options, m_port );
|
||||
}
|
||||
catch( std::runtime_error& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DbManager::selectSchema()
|
||||
{
|
||||
if( !m_pConnection )
|
||||
{
|
||||
m_lastError = "No valid db connection!";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
m_pConnection->setSchema( m_database );
|
||||
}
|
||||
catch( std::runtime_error& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string& DbManager::getLastError()
|
||||
{
|
||||
return m_lastError;
|
||||
}
|
||||
|
||||
void DbManager::setMode( Mode mode )
|
||||
{
|
||||
m_mode = mode;
|
||||
}
|
||||
|
||||
Mode DbManager::getMode() const
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
bool DbManager::performAction()
|
||||
{
|
||||
bool result = false;
|
||||
execute( " SET autocommit = 0 " );
|
||||
m_pConnection->beginTransaction();
|
||||
|
||||
switch( m_mode )
|
||||
{
|
||||
case Mode::INIT:
|
||||
result = modeInit();
|
||||
break;
|
||||
case Mode::LIQUIDATE:
|
||||
break;
|
||||
case Mode::UPDATE:
|
||||
break;
|
||||
case Mode::CHECK:
|
||||
break;
|
||||
case Mode::CLEAN_CHARS:
|
||||
break;
|
||||
}
|
||||
if( !result )
|
||||
m_pConnection->rollbackTransaction();
|
||||
else
|
||||
m_pConnection->commitTransaction();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DbManager::modeInit()
|
||||
{
|
||||
|
||||
bool result = false;
|
||||
|
||||
if( selectSchema() )
|
||||
{
|
||||
m_lastError = "Database already existing, use <liquidate> mode first to remove it.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !execute( "CREATE DATABASE " + m_database ) )
|
||||
return false;
|
||||
|
||||
if( !execute( "CREATE TABLE `dbversion` (\n"
|
||||
" `major` int(11) NOT NULL,\n"
|
||||
" `minor` int(11) NOT NULL\n"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=latin1;" ) )
|
||||
return false;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
55
src/dbm/DbManager.h
Normal file
55
src/dbm/DbManager.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#ifndef SAPPHIRE_DBMANAGER
|
||||
#define SAPPHIRE_DBMANAGER
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
|
||||
namespace Mysql
|
||||
{
|
||||
class Connection;
|
||||
}
|
||||
|
||||
enum class Mode
|
||||
{
|
||||
INIT,
|
||||
LIQUIDATE,
|
||||
UPDATE,
|
||||
CHECK,
|
||||
CLEAN_CHARS
|
||||
};
|
||||
|
||||
class DbManager
|
||||
{
|
||||
public:
|
||||
DbManager( const std::string& host, const std::string& database, const std::string& user, const std::string& pw, uint16_t port );
|
||||
|
||||
void setMode( Mode mode );
|
||||
Mode getMode() const;
|
||||
|
||||
bool connect();
|
||||
bool selectSchema();
|
||||
|
||||
bool execute( const std::string& sql );
|
||||
|
||||
bool performAction();
|
||||
|
||||
bool modeInit();
|
||||
|
||||
virtual ~DbManager();
|
||||
|
||||
const std::string& getLastError();
|
||||
|
||||
private:
|
||||
std::string m_host;
|
||||
std::string m_database;
|
||||
std::string m_user;
|
||||
std::string m_password;
|
||||
uint16_t m_port;
|
||||
std::shared_ptr< Mysql::Connection > m_pConnection;
|
||||
std::string m_lastError;
|
||||
Mode m_mode;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
190
src/dbm/main.cpp
Normal file
190
src/dbm/main.cpp
Normal file
|
@ -0,0 +1,190 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <cctype>
|
||||
#include <set>
|
||||
#include <common/Logging/Logger.h>
|
||||
#include <experimental/filesystem>
|
||||
#include <MySqlConnector.h>
|
||||
|
||||
|
||||
namespace filesys = std::experimental::filesystem;
|
||||
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
#include <regex>
|
||||
#include <map>
|
||||
|
||||
#include "DbManager.h"
|
||||
|
||||
Core::Logger g_log;
|
||||
|
||||
std::vector< std::string > getAllFilesInDir( const std::string& dirPath,
|
||||
const std::vector< std::string > dirSkipList = {} )
|
||||
{
|
||||
|
||||
// Create a vector of string
|
||||
std::vector< std::string > listOfFiles;
|
||||
try
|
||||
{
|
||||
// Check if given path exists and points to a directory
|
||||
if( filesys::exists( dirPath ) && filesys::is_directory( dirPath ) )
|
||||
{
|
||||
// Create a Recursive Directory Iterator object and points to the starting of directory
|
||||
filesys::recursive_directory_iterator iter( dirPath );
|
||||
|
||||
// Create a Recursive Directory Iterator object pointing to end.
|
||||
filesys::recursive_directory_iterator end;
|
||||
|
||||
// Iterate till end
|
||||
while( iter != end )
|
||||
{
|
||||
// Check if current entry is a directory and if exists in skip list
|
||||
if( filesys::is_directory( iter->path() ) &&
|
||||
( std::find( dirSkipList.begin(), dirSkipList.end(), iter->path().filename() ) != dirSkipList.end() ) )
|
||||
{
|
||||
// Skip the iteration of current directory pointed by iterator
|
||||
// c++17 Filesystem API to skip current directory iteration
|
||||
iter.disable_recursion_pending();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add the name in vector
|
||||
listOfFiles.push_back( iter->path().string() );
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
// Increment the iterator to point to next entry in recursive iteration
|
||||
iter.increment( ec );
|
||||
if( ec )
|
||||
{
|
||||
std::cerr << "Error While Accessing : " << iter->path().string() << " :: " << ec.message() << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( std::system_error& e )
|
||||
{
|
||||
std::cerr << "Exception :: " << e.what();
|
||||
}
|
||||
return listOfFiles;
|
||||
}
|
||||
|
||||
std::string delChar( std::string &str, char del )
|
||||
{
|
||||
str.erase( std::remove( str.begin(), str.end(), del ), str.end() );
|
||||
return str;
|
||||
}
|
||||
|
||||
void printUsage()
|
||||
{
|
||||
g_log.info( " Usage: sapphire_dbm " );
|
||||
g_log.info( "\t --mode" );
|
||||
g_log.info( "\t\t initialize -> Creates DB if not present and inserts default tables/data" );
|
||||
g_log.info( "\t\t check -> Checks if Sapphire DB-Version matches your DB-Version" );
|
||||
g_log.info( "\t\t update -> Updates your DB-Version to Sapphire DB-Version" );
|
||||
g_log.info( "\t\t clearchars -> Removes all character data from DB. Accounts will stay untouched" );
|
||||
g_log.info( "\t\t liquidate -> Removes all tables and deletes the DB" );
|
||||
g_log.info( "\t --user <mysqlUserName>" );
|
||||
g_log.info( "\t --pass <mysqlPassword> ( default empty )" );
|
||||
g_log.info( "\t --host <mysqlHost> ( default 127.0.0.1 )" );
|
||||
g_log.info( "\t --port <mysqlPort> ( default 3306 )" );
|
||||
g_log.info( "\t --database <mysqlDatabase>" );
|
||||
|
||||
}
|
||||
|
||||
int main( int32_t argc, char* argv[] )
|
||||
{
|
||||
std::string arg( "" );
|
||||
std::string val( "" );
|
||||
|
||||
std::string mode;
|
||||
std::string user;
|
||||
std::string host;
|
||||
std::string database;
|
||||
|
||||
g_log.setLogPath( "log/SapphireDbm" );
|
||||
g_log.init();
|
||||
|
||||
|
||||
std::vector< std::string > args( argv + 1, argv + argc );
|
||||
for( uint32_t i = 0; i + 1 < args.size(); i += 2 )
|
||||
{
|
||||
arg = std::string( args[ i ] );
|
||||
val = std::string( args[ i + 1 ] );
|
||||
|
||||
// trim '-' from start of arg
|
||||
arg = arg.erase( 0, arg.find_first_not_of( '-' ) );
|
||||
if( arg == "mode" )
|
||||
mode = val;
|
||||
else if( arg == "user" )
|
||||
user = val;
|
||||
else if( arg == "host" )
|
||||
host = val;
|
||||
else if( arg == "database" )
|
||||
database = val;
|
||||
}
|
||||
|
||||
if( host.empty() )
|
||||
host = "127.0.0.1";
|
||||
|
||||
if( mode.empty() || user.empty() || database.empty() )
|
||||
{
|
||||
printUsage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto dbm = DbManager( host, database, user, "", 3306 );
|
||||
|
||||
//initialize|check|update|clearchars|liquidate
|
||||
if( mode.find( "initialize" ) != std::string::npos )
|
||||
{
|
||||
dbm.setMode( Mode::INIT );
|
||||
}
|
||||
else if( mode.find( "check" ) != std::string::npos )
|
||||
{
|
||||
dbm.setMode( Mode::CHECK );
|
||||
}
|
||||
else if( mode.find( "update" ) != std::string::npos )
|
||||
{
|
||||
dbm.setMode( Mode::UPDATE );
|
||||
}
|
||||
else if( mode.find( "clearchars" ) != std::string::npos )
|
||||
{
|
||||
dbm.setMode( Mode::CLEAN_CHARS );
|
||||
}
|
||||
else if( mode.find( "liquidate" ) != std::string::npos )
|
||||
{
|
||||
dbm.setMode( Mode::LIQUIDATE );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_log.fatal( "Not a valid mode: " + mode + " !" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_log.info( "Launching in " + mode + " mode..." );
|
||||
|
||||
if( !dbm.connect() )
|
||||
{
|
||||
g_log.fatal( "Could not connect to server!" );
|
||||
g_log.fatal( dbm.getLastError() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !dbm.performAction() )
|
||||
{
|
||||
g_log.fatal( "Could not perform action!" );
|
||||
g_log.fatal( dbm.getLastError() );
|
||||
}
|
||||
|
||||
//if( !dbm.selectSchema() )
|
||||
//{
|
||||
// g_log.fatal( "Could not set schema!" );
|
||||
// g_log.fatal( dbm.getLastError() );
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Actor/Player.h>
|
||||
|
||||
#include <Framework.h>
|
||||
#include <Manager/ShopMgr.h>
|
||||
|
||||
using namespace Core;
|
||||
|
||||
class GilShop :
|
||||
|
@ -16,11 +19,11 @@ public:
|
|||
|
||||
void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override
|
||||
{
|
||||
player.playScene( eventId, 0, SCENE_FLAGS, 0, 2, shopCallback );
|
||||
player.playScene( eventId, 0, SCENE_FLAGS, 0, 2, std::bind( &GilShop::shopCallback, this, std::placeholders::_1, std::placeholders::_2 ) );
|
||||
}
|
||||
|
||||
private:
|
||||
static void shopInteractionCallback( Entity::Player& player, const Event::SceneResult& result )
|
||||
void shopInteractionCallback( Entity::Player& player, const Event::SceneResult& result )
|
||||
{
|
||||
// item purchase
|
||||
if( result.param1 == 768 )
|
||||
|
@ -28,17 +31,19 @@ private:
|
|||
// buy
|
||||
if( result.param2 == 1 )
|
||||
{
|
||||
auto shopMgr = getFramework()->get< Sapphire::World::Manager::ShopMgr >();
|
||||
|
||||
shopMgr->purchaseGilShopItem( player, result.eventId, result.param3, result.param4 );
|
||||
}
|
||||
|
||||
// sell
|
||||
else if( result.param2 == 2 )
|
||||
// sell
|
||||
// can't sell if the vendor is yourself (eg, housing permit shop)
|
||||
else if( result.param2 == 2 && result.actorId != player.getId() )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
player.sendDebug( "got tradeQuantity: " + std::to_string( result.param4 ) );
|
||||
player.playGilShop( result.eventId, SCENE_FLAGS, shopInteractionCallback );
|
||||
player.playGilShop( result.eventId, SCENE_FLAGS, std::bind( &GilShop::shopInteractionCallback, this, std::placeholders::_1, std::placeholders::_2 ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -46,8 +51,8 @@ private:
|
|||
player.playScene( result.eventId, 255, SCENE_FLAGS );
|
||||
}
|
||||
|
||||
static void shopCallback( Entity::Player& player, const Event::SceneResult& result )
|
||||
void shopCallback( Entity::Player& player, const Event::SceneResult& result )
|
||||
{
|
||||
player.playGilShop( result.eventId, SCENE_FLAGS, shopInteractionCallback );
|
||||
player.playGilShop( result.eventId, SCENE_FLAGS, std::bind( &GilShop::shopInteractionCallback, this, std::placeholders::_1, std::placeholders::_2 ) );
|
||||
}
|
||||
};
|
|
@ -61,7 +61,8 @@ public:
|
|||
if( !warp )
|
||||
return;
|
||||
|
||||
player.eventStart( actorId, warp->defaultTalk1, Event::EventHandler::Nest, 0, 0, std::bind( &WarpTaxi::inner2, this, std::placeholders::_1, std::placeholders::_2 ) );
|
||||
player.playScene( warp->defaultTalk1, 0, HIDE_HOTBAR, 0, 0, 7, nullptr );
|
||||
player.eventStart( actorId, warp->conditionSuccessEvent, Event::EventHandler::Nest, 0, 0,
|
||||
std::bind( &WarpTaxi::inner2, this, std::placeholders::_1, std::placeholders::_2 ) );
|
||||
player.playScene( warp->conditionSuccessEvent, 0, HIDE_HOTBAR, 0, 0, 7, nullptr );
|
||||
}
|
||||
};
|
|
@ -1587,7 +1587,7 @@ void Core::Entity::Player::sendZonePackets()
|
|||
auto pHousingMgr = g_fw.get< HousingMgr >();
|
||||
if( Core::LandPtr pLand = pHousingMgr->getLandByOwnerId( getId() ) )
|
||||
{
|
||||
setLandPermissions( LandPermissionSlot::Private, 0x00, pLand->getLandId(), pLand->getWardNum(), pLand->getZoneId() );
|
||||
setLandPermissions( LandPermissionSlot::Private, 0x00, pLand->getLandId(), pLand->getWardNum(), pLand->getTerritoryTypeId() );
|
||||
}
|
||||
|
||||
sendLandPermissions();
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace Core::Event
|
|||
|
||||
struct SceneResult
|
||||
{
|
||||
uint64_t actorId;
|
||||
uint32_t eventId;
|
||||
uint16_t param1;
|
||||
uint16_t param2;
|
||||
|
|
34
src/servers/sapphire_zone/Manager/ShopMgr.cpp
Normal file
34
src/servers/sapphire_zone/Manager/ShopMgr.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include "ShopMgr.h"
|
||||
|
||||
#include <Framework.h>
|
||||
#include <Exd/ExdDataGenerated.h>
|
||||
#include <Actor/Player.h>
|
||||
#include <Common.h>
|
||||
|
||||
extern Core::Framework g_fw;
|
||||
using namespace Core;
|
||||
|
||||
bool Sapphire::World::Manager::ShopMgr::purchaseGilShopItem( Entity::Player& player, uint32_t shopId, uint16_t itemId, uint32_t quantity )
|
||||
{
|
||||
auto exdData = g_fw.get< Data::ExdDataGenerated >();
|
||||
if( !exdData )
|
||||
return false;
|
||||
|
||||
auto gilShopItem = exdData->get< Data::GilShopItem >( shopId, itemId );
|
||||
if( !gilShopItem )
|
||||
return false;
|
||||
|
||||
auto item = exdData->get< Data::Item >( gilShopItem->item );
|
||||
if( !item )
|
||||
return false;
|
||||
|
||||
if( player.getCurrency( Common::CurrencyType::Gil ) < item->priceMid )
|
||||
return false;
|
||||
|
||||
if( !player.addItem( gilShopItem->item, quantity ) )
|
||||
return false;
|
||||
|
||||
player.removeCurrency( Common::CurrencyType::Gil, item->priceMid );
|
||||
|
||||
return true;
|
||||
}
|
10
src/servers/sapphire_zone/Manager/ShopMgr.h
Normal file
10
src/servers/sapphire_zone/Manager/ShopMgr.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include "ForwardsZone.h"
|
||||
|
||||
namespace Sapphire::World::Manager
|
||||
{
|
||||
class ShopMgr
|
||||
{
|
||||
public:
|
||||
bool purchaseGilShopItem( Core::Entity::Player& player, uint32_t shopId, uint16_t itemId, uint32_t quantity );
|
||||
};
|
||||
}
|
|
@ -321,6 +321,10 @@ void Core::Network::GameConnection::processOutQueue()
|
|||
|
||||
pRP.addPacket( pPacket );
|
||||
totalSize += pPacket->getSize();
|
||||
|
||||
// todo: figure out a good max set size and make it configurable
|
||||
if( totalSize > 15000 )
|
||||
break;
|
||||
}
|
||||
|
||||
if( totalSize > 0 )
|
||||
|
|
|
@ -77,7 +77,7 @@ void Core::Network::GameConnection::cfRegisterDuty( const Packets::FFXIVARR_PACK
|
|||
if( !cfCondition )
|
||||
return;
|
||||
|
||||
auto instance = pTeriMgr->createInstanceContent( cfCondition->instanceContent );
|
||||
auto instance = pTeriMgr->createInstanceContent( cfCondition->content );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
|
|
|
@ -221,6 +221,7 @@ void Core::Network::GameConnection::eventHandlerReturn( const Packets::FFXIVARR_
|
|||
if( eventCallback )
|
||||
{
|
||||
Event::SceneResult result;
|
||||
result.actorId = pEvent->getActorId();
|
||||
result.eventId = eventId;
|
||||
result.param1 = param1;
|
||||
result.param2 = param2;
|
||||
|
@ -273,7 +274,9 @@ void Core::Network::GameConnection::eventHandlerShop( const Packets::FFXIVARR_PA
|
|||
" (0x" + Util::intToHexString( static_cast< uint64_t >( eventId & 0xFFFFFFF ), 8 ) + ")" );
|
||||
|
||||
player.sendDebug( "Calling: " + objName + "." + eventName );
|
||||
player.eventStart( 0, eventId, Event::EventHandler::UI, 0, packet.data().param );
|
||||
player.eventStart( player.getId(), eventId, Event::EventHandler::UI, 0, packet.data().param );
|
||||
|
||||
pScriptMgr->onTalk( player, player.getId(), eventId );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -673,40 +673,6 @@ void Core::Network::GameConnection::buildPresetHandler( const Core::Network::Pac
|
|||
{
|
||||
const auto packet = ZoneChannelPacket< Client::FFXIVIpcBuildPresetHandler >( inPacket );
|
||||
|
||||
auto zone = player.getCurrentZone();
|
||||
auto plotNum = packet.data().plotNum;
|
||||
auto preset = packet.data().itemId;
|
||||
std::string landString = std::string( packet.data().stateString );
|
||||
auto hZone = std::dynamic_pointer_cast< HousingZone >( zone );
|
||||
|
||||
if( !hZone )
|
||||
return;
|
||||
|
||||
auto pLand = hZone->getLand( plotNum );
|
||||
/*
|
||||
if (!pLand)
|
||||
player.sendDebug( "Something went wrong..." );
|
||||
|
||||
if( stateString.find( "Private" ) )
|
||||
{
|
||||
pLand->setPreset( preset );
|
||||
pLand->setState( HouseState::privateHouse );
|
||||
pLand->UpdateLandDb();
|
||||
hZone->sendLandUpdate( plotNum );
|
||||
}
|
||||
else if( stateString.find("Free") )
|
||||
{
|
||||
pLand->setPreset( preset );
|
||||
pLand->setState( HouseState::fcHouse );
|
||||
pLand->UpdateLandDb();
|
||||
hZone->sendLandUpdate( plotNum );
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendDebug( "You tried to build a preset on not supported land." );
|
||||
}
|
||||
|
||||
auto pSuccessBuildingPacket = makeActorControl142( player.getId(), BuildPresetResponse, plotNum );
|
||||
|
||||
player.queuePacket( pSuccessBuildingPacket );*/
|
||||
auto pHousingMgr = g_fw.get< HousingMgr >();
|
||||
pHousingMgr->buildPresetEstate( player, packet.data().plotNum, packet.data().itemId );
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <Logging/Logger.h>
|
||||
#include <Exd/ExdDataGenerated.h>
|
||||
#include <Database/DatabaseDef.h>
|
||||
#include <Database/ZoneDbConnection.h>
|
||||
|
||||
#include "House.h"
|
||||
|
||||
|
@ -18,13 +20,79 @@ Core::House::House( uint32_t houseId, uint32_t landSetId, uint8_t landId, uint8_
|
|||
m_wardNum( wardNum ),
|
||||
m_territoryTypeId( territoryTypeId )
|
||||
{
|
||||
memset( &m_houseParts, 0x00, sizeof( m_houseParts ) );
|
||||
memset( &m_commentMsg, 0x00, sizeof( m_commentMsg ) );
|
||||
auto pDB = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
||||
|
||||
// todo: convert to prepared statement
|
||||
auto res = pDB->query( "SELECT * FROM house WHERE HouseId = " + std::to_string( houseId ) );
|
||||
|
||||
if( !res->next() )
|
||||
{
|
||||
g_fw.get< Core::Logger >()->info( "Creating house House#" + std::to_string( houseId ) + " in LandSet#" + std::to_string( landSetId ) );
|
||||
|
||||
auto stmt = pDB->getPreparedStatement( Db::HOUSING_HOUSE_INS );
|
||||
|
||||
stmt->setUInt( 1, m_landSetId );
|
||||
stmt->setUInt( 2, m_houseId );
|
||||
|
||||
pDB->execute( stmt );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_estateMessage = res->getString( "Comment" );
|
||||
m_houseName = res->getString( "HouseName" );
|
||||
|
||||
auto housePartModels = res->getBlobVector( "HousePartModels" );
|
||||
auto housePartColours = res->getBlobVector( "HousePartColours" );
|
||||
|
||||
auto models = reinterpret_cast< uint32_t* >( &housePartModels[ 0 ] );
|
||||
auto colours = &housePartColours[ 0 ];
|
||||
|
||||
for( auto i = 0; i < 8; i++ )
|
||||
{
|
||||
m_houseParts[ i ] = { models[ i ], colours[ i ] };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Core::House::~House()
|
||||
{
|
||||
}
|
||||
|
||||
void Core::House::updateHouseDb()
|
||||
{
|
||||
auto pDB = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
||||
|
||||
// BuildTime = 1, Aetheryte = 2, Comment = 3, HouseName = 4, Endorsements = 5,
|
||||
// HousePartModels = 6, HousePartColours = 7, HouseId = 8
|
||||
auto stmt = pDB->getPreparedStatement( Db::HOUSING_HOUSE_UP );
|
||||
stmt->setUInt( 8, m_houseId );
|
||||
|
||||
stmt->setInt64( 1, m_buildTime );
|
||||
stmt->setInt( 2, 0 );
|
||||
|
||||
stmt->setString( 3, m_estateMessage );
|
||||
stmt->setString( 4, m_houseName );
|
||||
|
||||
stmt->setUInt64( 5, 0 );
|
||||
|
||||
std::vector< uint32_t > models;
|
||||
std::vector< uint8_t > colours;
|
||||
|
||||
for( auto i = 0; i < 8; i++ )
|
||||
{
|
||||
auto& part = m_houseParts[ i ];
|
||||
models.push_back( part.first );
|
||||
colours.push_back( part.second );
|
||||
}
|
||||
|
||||
// todo: this is shit
|
||||
std::vector< uint8_t > tmpModels( models.size() * 4 );
|
||||
memcpy( tmpModels.data(), models.data(), tmpModels.size() );
|
||||
|
||||
stmt->setBinary( 6, tmpModels );
|
||||
stmt->setBinary( 7, colours );
|
||||
|
||||
pDB->execute( stmt );
|
||||
}
|
||||
|
||||
uint32_t Core::House::getLandSetId() const
|
||||
|
@ -54,20 +122,25 @@ uint32_t Core::House::getHouseId() const
|
|||
|
||||
uint8_t Core::House::getHousePartColor( Common::HousePartSlot slot ) const
|
||||
{
|
||||
return m_housePartsColor[ slot ];
|
||||
return m_houseParts[ slot ].second;
|
||||
}
|
||||
|
||||
void Core::House::setHousePart( Common::HousePartSlot slot, uint32_t id )
|
||||
{
|
||||
m_houseParts[ slot ] = id;
|
||||
m_houseParts[ slot ].first = id;
|
||||
}
|
||||
|
||||
void Core::House::setHousePartColor( Common::HousePartSlot slot, uint32_t id )
|
||||
{
|
||||
m_housePartsColor[ slot ] = id;
|
||||
m_houseParts[ slot ].second = id;
|
||||
}
|
||||
|
||||
uint32_t Core::House::getHousePart( Common::HousePartSlot slot ) const
|
||||
{
|
||||
return m_houseParts[ slot ];
|
||||
return m_houseParts[ slot ].first;
|
||||
}
|
||||
|
||||
Core::House::HousePartsArray const& Core::House::getHouseParts() const
|
||||
{
|
||||
return m_houseParts;
|
||||
}
|
|
@ -11,11 +11,13 @@ namespace Core
|
|||
|
||||
class House
|
||||
{
|
||||
|
||||
public:
|
||||
House( uint32_t houseId, uint32_t landSetId, uint8_t landId, uint8_t wardNum, uint16_t territoryTypeId );
|
||||
virtual ~House();
|
||||
|
||||
using HousePart = std::pair< uint32_t, uint8_t >;
|
||||
using HousePartsArray = std::array< HousePart, 8 >;
|
||||
|
||||
//gerneral
|
||||
uint32_t getLandSetId() const;
|
||||
uint8_t getLandId() const;
|
||||
|
@ -29,6 +31,10 @@ namespace Core
|
|||
uint32_t getHousePart( Common::HousePartSlot slot ) const;
|
||||
uint8_t getHousePartColor( Common::HousePartSlot slot ) const;
|
||||
|
||||
HousePartsArray const& getHouseParts() const;
|
||||
|
||||
void updateHouseDb();
|
||||
|
||||
private:
|
||||
uint32_t m_landSetId;
|
||||
uint8_t m_landId;
|
||||
|
@ -36,10 +42,12 @@ namespace Core
|
|||
uint16_t m_territoryTypeId;
|
||||
uint32_t m_houseId;
|
||||
|
||||
uint32_t m_houseParts[ 8 ];
|
||||
uint8_t m_housePartsColor[ 8 ];
|
||||
uint64_t m_buildTime;
|
||||
|
||||
char m_commentMsg[ 193 ];
|
||||
HousePartsArray m_houseParts;
|
||||
|
||||
std::string m_estateMessage;
|
||||
std::string m_houseName;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ void Core::HousingMgr::sendLandSignOwned( Entity::Player& player, uint8_t wardId
|
|||
memcpy( &landInfoSignPacket->data().ownerName, playerName.c_str(), playerName.size() );
|
||||
landInfoSignPacket->data().wardNum = land->getWardNum();
|
||||
landInfoSignPacket->data().worldId = 67;
|
||||
landInfoSignPacket->data().zoneId = land->getZoneId();
|
||||
landInfoSignPacket->data().zoneId = land->getTerritoryTypeId();
|
||||
player.queuePacket( landInfoSignPacket );
|
||||
}
|
||||
|
||||
|
@ -273,3 +273,41 @@ void Core::HousingMgr::sendWardLandInfo( Entity::Player& player, uint8_t wardId,
|
|||
player.queuePacket( wardInfoPacket );
|
||||
}
|
||||
|
||||
void Core::HousingMgr::buildPresetEstate( Entity::Player& player, uint8_t plotNum, uint32_t presetItem )
|
||||
{
|
||||
auto hZone = std::dynamic_pointer_cast< HousingZone >( player.getCurrentZone() );
|
||||
|
||||
if( !hZone )
|
||||
return;
|
||||
|
||||
auto pLand = hZone->getLand( plotNum );
|
||||
if( !pLand )
|
||||
return;
|
||||
|
||||
// todo: when doing FC houses, look up the type from the original purchase and check perms from FC and set state accordingly
|
||||
if( pLand->getPlayerOwner() != player.getId() )
|
||||
return;
|
||||
|
||||
// todo: check if permit is in inventory and remove one
|
||||
|
||||
if( !pLand->setPreset( presetItem ) )
|
||||
return;
|
||||
|
||||
pLand->setState( HouseState::privateHouse );
|
||||
pLand->setLandType( LandType::Private );
|
||||
hZone->sendLandUpdate( plotNum );
|
||||
|
||||
auto pSuccessBuildingPacket = makeActorControl142( player.getId(), ActorControl::BuildPresetResponse, plotNum );
|
||||
|
||||
player.queuePacket( pSuccessBuildingPacket );
|
||||
|
||||
pLand->updateLandDb();
|
||||
|
||||
// start house built event
|
||||
// CmnDefHousingBuildHouse_00149
|
||||
player.eventStart( player.getId(), 0x000B0095, Event::EventHandler::EventType::Housing, 1, 1 );
|
||||
// todo: wtf are these flags
|
||||
player.playScene( 0x000B0095, 0, 4164955899, 0, 1, plotNum, nullptr );
|
||||
|
||||
// todo: send perms/flags for house
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ namespace Core
|
|||
|
||||
bool relinquishLand( Entity::Player& player, uint8_t plot );
|
||||
|
||||
void buildPresetEstate( Entity::Player& player, uint8_t plotNum, uint32_t presetItem );
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Actor/Player.h"
|
||||
#include "Actor/Actor.h"
|
||||
#include "Land.h"
|
||||
#include "House.h"
|
||||
|
||||
#include "Forwards.h"
|
||||
#include "HousingZone.h"
|
||||
|
@ -126,13 +127,28 @@ void Core::HousingZone::sendLandSet( Entity::Player& player )
|
|||
for( uint8_t i = startIndex, count = 0; i < ( startIndex + 30 ); ++i, ++count )
|
||||
{
|
||||
auto pLand = getLand( i );
|
||||
landsetInitializePacket->data().land[ count ].plotSize = pLand->getSize();
|
||||
landsetInitializePacket->data().land[ count ].houseState = pLand->getState();
|
||||
landsetInitializePacket->data().land[ count ].type = static_cast< uint8_t >( pLand->getLandType() );
|
||||
landsetInitializePacket->data().land[ count ].iconAddIcon = pLand->getSharing();
|
||||
landsetInitializePacket->data().land[ count ].fcId = pLand->getFcId();
|
||||
landsetInitializePacket->data().land[ count ].fcIcon = pLand->getFcIcon();
|
||||
landsetInitializePacket->data().land[ count ].fcIconColor = pLand->getFcColor();
|
||||
|
||||
// todo: move this and sendLandUpdate building logic to its own function
|
||||
auto& landData = landsetInitializePacket->data().land[ count ];
|
||||
|
||||
landData.plotSize = pLand->getSize();
|
||||
landData.houseState = pLand->getState();
|
||||
landData.type = static_cast< uint8_t >( pLand->getLandType() );
|
||||
landData.iconAddIcon = pLand->getSharing();
|
||||
landData.fcId = pLand->getFcId();
|
||||
landData.fcIcon = pLand->getFcIcon();
|
||||
landData.fcIconColor = pLand->getFcColor();
|
||||
|
||||
if( auto house = pLand->getHouse() )
|
||||
{
|
||||
auto& parts = house->getHouseParts();
|
||||
|
||||
for( auto i = 0; i != parts.size(); i++ )
|
||||
{
|
||||
landData.housePart[ i ] = parts[ i ].first;
|
||||
landData.houseColour[ i ] = parts[ i ].second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player.queuePacket( landsetInitializePacket );
|
||||
|
@ -147,13 +163,28 @@ void Core::HousingZone::sendLandUpdate( uint8_t landId )
|
|||
|
||||
auto landUpdatePacket = makeZonePacket< FFXIVIpcLandUpdate >( pPlayer->getId() );
|
||||
landUpdatePacket->data().landId = landId;
|
||||
landUpdatePacket->data().land.plotSize = pLand->getSize();
|
||||
landUpdatePacket->data().land.houseState = pLand->getState();
|
||||
landUpdatePacket->data().land.type = static_cast< uint8_t >( pLand->getLandType() );
|
||||
landUpdatePacket->data().land.iconAddIcon = pLand->getSharing();
|
||||
landUpdatePacket->data().land.fcId = pLand->getFcId();
|
||||
landUpdatePacket->data().land.fcIcon = pLand->getFcIcon();
|
||||
landUpdatePacket->data().land.fcIconColor = pLand->getFcColor();
|
||||
|
||||
auto& landData = landUpdatePacket->data().land;
|
||||
|
||||
landData.plotSize = pLand->getSize();
|
||||
landData.houseState = pLand->getState();
|
||||
landData.type = static_cast< uint8_t >( pLand->getLandType() );
|
||||
landData.iconAddIcon = pLand->getSharing();
|
||||
landData.fcId = pLand->getFcId();
|
||||
landData.fcIcon = pLand->getFcIcon();
|
||||
landData.fcIconColor = pLand->getFcColor();
|
||||
|
||||
|
||||
if( auto house = pLand->getHouse() )
|
||||
{
|
||||
auto& parts = house->getHouseParts();
|
||||
|
||||
for( auto i = 0; i != parts.size(); i++ )
|
||||
{
|
||||
landData.housePart[ i ] = parts[ i ].first;
|
||||
landData.houseColour[ i ] = parts[ i ].second;
|
||||
}
|
||||
}
|
||||
|
||||
pPlayer->queuePacket( landUpdatePacket );
|
||||
}
|
||||
|
|
|
@ -20,14 +20,15 @@
|
|||
#include "Forwards.h"
|
||||
#include "Land.h"
|
||||
#include "Framework.h"
|
||||
#include "House.h"
|
||||
|
||||
extern Core::Framework g_fw;
|
||||
|
||||
using namespace Core::Common;
|
||||
|
||||
Core::Land::Land( uint16_t zoneId, uint8_t wardNum, uint8_t landId, uint32_t landSetId,
|
||||
Core::Land::Land( uint16_t territoryTypeId, uint8_t wardNum, uint8_t landId, uint32_t landSetId,
|
||||
Core::Data::HousingLandSetPtr info ) :
|
||||
m_zoneId( zoneId ),
|
||||
m_territoryTypeId( territoryTypeId ),
|
||||
m_wardNum( wardNum ),
|
||||
m_landId( landId ),
|
||||
m_currentPrice( 0 ),
|
||||
|
@ -36,7 +37,11 @@ Core::Land::Land( uint16_t zoneId, uint8_t wardNum, uint8_t landId, uint32_t lan
|
|||
m_ownerPlayerId( 0 ),
|
||||
m_landSetId( landSetId ),
|
||||
m_landInfo( info ),
|
||||
m_type( Common::LandType::Private )
|
||||
m_type( Common::LandType::none ),
|
||||
m_fcIcon( 0 ),
|
||||
m_fcIconColor( 0 ),
|
||||
m_fcId( 0 ),
|
||||
m_iconAddIcon( 0 )
|
||||
{
|
||||
memset( &m_tag, 0x00, 3 );
|
||||
|
||||
|
@ -55,15 +60,15 @@ void Core::Land::load()
|
|||
"AND LandId = " + std::to_string( m_landId ) );
|
||||
if( !res->next() )
|
||||
{
|
||||
pDb->directExecute( "INSERT INTO land ( landsetid, landid, type, size, status, landprice ) "
|
||||
pDb->directExecute( "INSERT INTO land ( landsetid, landid, type, size, status, landprice, UpdateTime, OwnerId, HouseId ) "
|
||||
"VALUES ( " + std::to_string( m_landSetId ) + "," + std::to_string( m_landId ) + ","
|
||||
+ std::to_string( static_cast< uint8_t >( m_type ) ) + ","
|
||||
+ std::to_string( m_landInfo->sizes[ m_landId ] ) + ","
|
||||
+ " 1, " + std::to_string( m_landInfo->prices[ m_landId ] ) + " );" );
|
||||
+ std::to_string( m_landInfo->plotSize[ m_landId ] ) + ","
|
||||
+ " 1, " + std::to_string( m_landInfo->initialPrice[ m_landId ] ) + ", 0, 0, 0 );" );
|
||||
|
||||
m_currentPrice = m_landInfo->prices[ m_landId ];
|
||||
m_minPrice = m_landInfo->minPrices[ m_landId ];
|
||||
m_size = m_landInfo->sizes[ m_landId ];
|
||||
m_currentPrice = m_landInfo->initialPrice[ m_landId ];
|
||||
m_minPrice = m_landInfo->minPrice[ m_landId ];
|
||||
m_size = m_landInfo->plotSize[ m_landId ];
|
||||
m_state = HouseState::forSale;
|
||||
}
|
||||
else
|
||||
|
@ -73,13 +78,20 @@ void Core::Land::load()
|
|||
m_state = res->getUInt( "Status" );
|
||||
m_currentPrice = res->getUInt( "LandPrice" );
|
||||
m_ownerPlayerId = res->getUInt( "OwnerId" );
|
||||
m_minPrice = m_landInfo->minPrices[ m_landId ];
|
||||
m_maxPrice = m_landInfo->prices[ m_landId ];
|
||||
m_minPrice = m_landInfo->minPrice[ m_landId ];
|
||||
m_maxPrice = m_landInfo->initialPrice[ m_landId ];
|
||||
|
||||
auto houseId = res->getUInt( "HouseId" );
|
||||
|
||||
// fetch the house if we have one for this land
|
||||
if( houseId > 0 )
|
||||
m_pHouse = make_House( houseId, m_landSetId, m_landId, m_wardNum, m_territoryTypeId );
|
||||
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
uint16_t Core::Land::convertItemIdToHousingItemId( uint16_t itemId )
|
||||
uint32_t Core::Land::convertItemIdToHousingItemId( uint32_t itemId )
|
||||
{
|
||||
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
|
||||
auto info = pExdData->get< Core::Data::Item >( itemId );
|
||||
|
@ -147,9 +159,9 @@ uint8_t Core::Land::getLandId() const
|
|||
return m_landId;
|
||||
}
|
||||
|
||||
uint16_t Core::Land::getZoneId() const
|
||||
uint16_t Core::Land::getTerritoryTypeId() const
|
||||
{
|
||||
return m_zoneId;
|
||||
return m_territoryTypeId;
|
||||
}
|
||||
|
||||
Core::HousePtr Core::Land::getHouse() const
|
||||
|
@ -242,15 +254,24 @@ void Core::Land::init()
|
|||
|
||||
void Core::Land::updateLandDb()
|
||||
{
|
||||
uint32_t houseId = 0;
|
||||
|
||||
if( getHouse() )
|
||||
houseId = getHouse()->getHouseId();
|
||||
|
||||
// todo: change to prepared statement
|
||||
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
||||
pDb->directExecute( "UPDATE land SET status = " + std::to_string( m_state )
|
||||
+ ", LandPrice = " + std::to_string( getCurrentPrice() )
|
||||
+ ", UpdateTime = " + std::to_string( getDevaluationTime() )
|
||||
+ ", OwnerId = " + std::to_string( getPlayerOwner() )
|
||||
+ ", HouseId = " + std::to_string( 0 ) //TODO: add house id
|
||||
+ ", OwnerId = " + std::to_string( getPlayerOwner() )
|
||||
+ ", HouseId = " + std::to_string( houseId )
|
||||
+ ", Type = " + std::to_string( static_cast< uint32_t >( m_type ) ) //TODO: add house id
|
||||
+ " WHERE LandSetId = " + std::to_string( m_landSetId )
|
||||
+ " AND LandId = " + std::to_string( m_landId ) + ";" );
|
||||
|
||||
if( auto house = getHouse() )
|
||||
house->updateHouseDb();
|
||||
}
|
||||
|
||||
void Core::Land::update( uint32_t currTime )
|
||||
|
@ -265,3 +286,41 @@ void Core::Land::update( uint32_t currTime )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Core::Land::getNextHouseId()
|
||||
{
|
||||
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
||||
auto pQR = pDb->query( "SELECT MAX( HouseId ) FROM house" );
|
||||
|
||||
if( !pQR->next() )
|
||||
return 0;
|
||||
|
||||
return pQR->getUInt( 1 ) + 1;
|
||||
}
|
||||
|
||||
bool Core::Land::setPreset( uint32_t itemId )
|
||||
{
|
||||
auto housingItemId = convertItemIdToHousingItemId( itemId );
|
||||
|
||||
auto exdData = g_fw.get< Core::Data::ExdDataGenerated >();
|
||||
if( !exdData )
|
||||
return false;
|
||||
|
||||
auto housingPreset = exdData->get< Core::Data::HousingPreset >( housingItemId );
|
||||
if( !housingPreset )
|
||||
return false;
|
||||
|
||||
if( !getHouse() )
|
||||
{
|
||||
// todo: i guess we'd create a house here?
|
||||
auto newId = getNextHouseId();
|
||||
m_pHouse = make_House( newId, getLandSetId(), getLandId(), getWardNum(), getTerritoryTypeId() );
|
||||
}
|
||||
|
||||
getHouse()->setHousePart( Common::HousePartSlot::ExteriorRoof, convertItemIdToHousingItemId( housingPreset->exteriorRoof ) );
|
||||
getHouse()->setHousePart( Common::HousePartSlot::ExteriorWall, convertItemIdToHousingItemId( housingPreset->exteriorWall ) );
|
||||
getHouse()->setHousePart( Common::HousePartSlot::ExteriorWindow, convertItemIdToHousingItemId( housingPreset->exteriorWindow ) );
|
||||
getHouse()->setHousePart( Common::HousePartSlot::ExteriorDoor, convertItemIdToHousingItemId( housingPreset->exteriorDoor ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace Core
|
|||
uint32_t getLandSetId() const;
|
||||
uint8_t getWardNum() const;
|
||||
uint8_t getLandId() const;
|
||||
uint16_t getZoneId() const;
|
||||
uint16_t getTerritoryTypeId() const;
|
||||
Common::LandType getLandType() const;
|
||||
Core::HousePtr getHouse() const;
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace Core
|
|||
uint32_t getPlayerOwner();
|
||||
//Housing Functions
|
||||
void setCurrentPrice( uint32_t currentPrice );
|
||||
void setPreset( uint32_t itemId );
|
||||
bool setPreset( uint32_t itemId );
|
||||
void updateLandDb();
|
||||
void update( uint32_t currTime );
|
||||
|
||||
|
@ -62,13 +62,14 @@ namespace Core
|
|||
uint8_t getLandTag( uint8_t slot );
|
||||
|
||||
private:
|
||||
uint16_t convertItemIdToHousingItemId( uint16_t itemId );
|
||||
uint32_t convertItemIdToHousingItemId( uint32_t itemId );
|
||||
void init();
|
||||
uint32_t getNextHouseId();
|
||||
|
||||
uint8_t m_wardNum;
|
||||
uint8_t m_landId;
|
||||
uint32_t m_landSetId;
|
||||
uint16_t m_zoneId;
|
||||
uint16_t m_territoryTypeId;
|
||||
uint8_t m_size;
|
||||
uint8_t m_state;
|
||||
Common::LandType m_type;
|
||||
|
|
|
@ -249,7 +249,7 @@ Core::ZonePtr Core::TerritoryMgr::createInstanceContent( uint32_t contentFinderC
|
|||
auto pContentFinderCondition = pExdData->get< Core::Data::ContentFinderCondition >( contentFinderConditionId );
|
||||
if( !pContentFinderCondition )
|
||||
return nullptr;
|
||||
auto instanceContentId = pContentFinderCondition->instanceContent;
|
||||
auto instanceContentId = pContentFinderCondition->content;
|
||||
|
||||
auto pInstanceContent = pExdData->get< Core::Data::InstanceContent >( instanceContentId );
|
||||
if( !pInstanceContent )
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "Zone/HousingMgr.h"
|
||||
#include "DebugCommand/DebugCommandHandler.h"
|
||||
#include "Manager/PlayerMgr.h"
|
||||
#include "Manager/ShopMgr.h"
|
||||
|
||||
#include <Config/ConfigMgr.h>
|
||||
|
||||
|
@ -32,6 +33,7 @@ bool setupFramework()
|
|||
auto pDebugCom = std::make_shared< DebugCommandHandler >();
|
||||
auto pConfig = std::make_shared< ConfigMgr >();
|
||||
auto pPlayerMgr = std::make_shared< Sapphire::World::Manager::PlayerMgr >();
|
||||
auto pShopMgr = std::make_shared< Sapphire::World::Manager::ShopMgr >();
|
||||
|
||||
pLogger->setLogPath( "log/SapphireZone" );
|
||||
pLogger->init();
|
||||
|
@ -47,6 +49,7 @@ bool setupFramework()
|
|||
g_fw.set< DebugCommandHandler >( pDebugCom );
|
||||
g_fw.set< ConfigMgr >( pConfig );
|
||||
g_fw.set< Sapphire::World::Manager::PlayerMgr >( pPlayerMgr );
|
||||
g_fw.set< Sapphire::World::Manager::ShopMgr >( pShopMgr );
|
||||
|
||||
// actuall catch errors here...
|
||||
return true;
|
||||
|
|
|
@ -36,8 +36,8 @@ bool Core::Data::ExdDataGenerated::init( const std::string& path )
|
|||
{
|
||||
try
|
||||
{
|
||||
m_data = boost::make_shared< xiv::dat::GameData >( path );
|
||||
m_exd_data = boost::make_shared< xiv::exd::ExdData >( *m_data );
|
||||
m_data = std::make_shared< xiv::dat::GameData >( path );
|
||||
m_exd_data = std::make_shared< xiv::exd::ExdData >( *m_data );
|
||||
|
||||
SETUPDATACCESS
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <ExdCat.h>
|
||||
#include <Exd.h>
|
||||
#include <set>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <variant>
|
||||
|
||||
namespace Core {
|
||||
namespace Data {
|
||||
|
@ -35,13 +35,13 @@ STRUCTS
|
|||
template< class T >
|
||||
T getField( std::vector< xiv::exd::Field >& fields, uint32_t index )
|
||||
{
|
||||
return *boost::get< T >( &fields.at( index ) );
|
||||
return std::get< T >( fields.at( index ) );
|
||||
}
|
||||
|
||||
void loadIdList( xiv::exd::Exd& data, std::set< uint32_t >& outIdList );
|
||||
|
||||
boost::shared_ptr< xiv::dat::GameData > m_data;
|
||||
boost::shared_ptr< xiv::exd::ExdData > m_exd_data;
|
||||
std::shared_ptr< xiv::dat::GameData > m_data;
|
||||
std::shared_ptr< xiv::exd::ExdData > m_exd_data;
|
||||
|
||||
DATACCESS
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -45,7 +45,7 @@ std::vector< std::string > cppKeyWords
|
|||
"class"
|
||||
};
|
||||
|
||||
//std::string datLocation( "/opt/sapphire_3_15_0/bin/sqpack" );
|
||||
//std::string datLocation( "/home/mordred/sqpack" );
|
||||
std::string datLocation( "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack" );
|
||||
std::map< uint8_t, std::string > g_typeMap;
|
||||
|
||||
|
@ -117,29 +117,57 @@ std::string generateStruct( const std::string& exd )
|
|||
std::ifstream exJson( "ex.json" );
|
||||
exJson >> json;
|
||||
|
||||
for( auto& definition : json["sheets"][exd] )
|
||||
for( auto& sheet : json[ "sheets" ] )
|
||||
{
|
||||
uint32_t index;
|
||||
std::string converterTarget = "";
|
||||
bool isRepeat = false;
|
||||
int num = 0;
|
||||
|
||||
index = definition["index"].get< uint32_t >();
|
||||
indexToNameMap[ index ] = std::string( definition["name"] );
|
||||
|
||||
converterTarget = std::string( definition["converter"]["target"] );
|
||||
if( nameTaken.find( converterTarget ) != nameTaken.end() )
|
||||
indexToTarget[ index ] = converterTarget;
|
||||
|
||||
if( auto count = definition["count"] )
|
||||
if( sheet[ "sheet" ] != exd )
|
||||
continue;
|
||||
|
||||
for( auto& definition : sheet[ "definitions" ] )
|
||||
{
|
||||
num = std::stoi( std::string( count ) );
|
||||
isRepeat = true;
|
||||
indexIsArrayMap[ index ] = true;
|
||||
indexCountMap[ index ] = num;
|
||||
uint32_t index;
|
||||
std::string converterTarget = "";
|
||||
bool isRepeat = false;
|
||||
int num = 0;
|
||||
try
|
||||
{
|
||||
index = definition.at( "index" );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::string fieldName = std::string( definition.at( "name" ) );
|
||||
indexToNameMap[ index ] = fieldName;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
|
||||
std::string fName = definition["definition"]["name"];
|
||||
indexToNameMap[ index ] = fName;
|
||||
try
|
||||
{
|
||||
converterTarget = std::string( definition.at( "converter" ).at( "target" ) );
|
||||
if( nameTaken.find( converterTarget ) != nameTaken.end() )
|
||||
indexToTarget[ index ] = converterTarget;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
num = definition.at( "count" );
|
||||
isRepeat = true;
|
||||
indexIsArrayMap[ index ] = true;
|
||||
indexCountMap[ index ] = num;
|
||||
std::string fName = definition.at( "definition" ).at( "name" );
|
||||
indexToNameMap[ index ] = fName;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -213,7 +241,15 @@ std::string generateStruct( const std::string& exd )
|
|||
count++;
|
||||
}
|
||||
|
||||
result += "\n " + exd + "( uint32_t row_id, Core::Data::ExdDataGenerated* exdData );\n";
|
||||
auto exhHead = exh.get_header();
|
||||
if( exhHead.variant == 2 )
|
||||
{
|
||||
result += "\n " + exd + "( uint32_t row_id, uint32_t subRow, Core::Data::ExdDataGenerated* exdData );\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "\n " + exd + "( uint32_t row_id, Core::Data::ExdDataGenerated* exdData );\n";
|
||||
}
|
||||
result += "};\n\n";
|
||||
|
||||
return result;
|
||||
|
@ -229,11 +265,20 @@ std::string generateConstructorsDecl( const std::string& exd )
|
|||
|
||||
int count = 0;
|
||||
|
||||
|
||||
result += "\nCore::Data::" + exd + "::" + exd + "( uint32_t row_id, Core::Data::ExdDataGenerated* exdData )\n";
|
||||
result += "{\n";
|
||||
std::string indent = " ";
|
||||
result += indent + "auto row = exdData->m_" + exd + "Dat.get_row( row_id );\n";
|
||||
auto exhHead = exh.get_header();
|
||||
if( exhHead.variant == 2 )
|
||||
{
|
||||
result += "\nCore::Data::" + exd + "::" + exd + "( uint32_t row_id, uint32_t subRow, Core::Data::ExdDataGenerated* exdData )\n";
|
||||
result += "{\n";
|
||||
result += indent + "auto row = exdData->m_" + exd + "Dat.get_row( row_id, subRow );\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "\nCore::Data::" + exd + "::" + exd + "( uint32_t row_id, Core::Data::ExdDataGenerated* exdData )\n";
|
||||
result += "{\n";
|
||||
result += indent + "auto row = exdData->m_" + exd + "Dat.get_row( row_id );\n";
|
||||
}
|
||||
for( auto member : exhMem )
|
||||
{
|
||||
if( indexToNameMap.find( count ) == indexToNameMap.end() )
|
||||
|
@ -333,22 +378,20 @@ int main( int argc, char** argv )
|
|||
|
||||
//BOOST_FOREACH( boost::property_tree::ptree::value_type &sheet, m_propTree.get_child( "sheets" ) )
|
||||
//{
|
||||
//std::string name = sheet.second.get< std::string >( "sheet" );
|
||||
//nameTaken[name] = "1";
|
||||
//}
|
||||
|
||||
for( auto& sheet : json["sheets"] )
|
||||
{
|
||||
std::string name = json["sheet"];
|
||||
|
||||
forwards += "struct " + name + ";\n";
|
||||
structDefs += generateStruct( name );
|
||||
dataDecl += generateDatAccessDecl( name );
|
||||
idListsDecl += generateIdListDecl( name );
|
||||
getterDecl += generateDirectGetters( name );
|
||||
datAccCall += generateSetDatAccessCall( name );
|
||||
constructorDecl += generateConstructorsDecl( name );
|
||||
idListGetters += generateIdListGetter( name );
|
||||
//
|
||||
for( auto& sheet : json[ "sheets" ] )
|
||||
{
|
||||
std::string name = sheet[ "sheet" ];
|
||||
forwards += "struct " + name + ";\n";
|
||||
structDefs += generateStruct( name );
|
||||
dataDecl += generateDatAccessDecl( name );
|
||||
idListsDecl += generateIdListDecl( name );
|
||||
getterDecl += generateDirectGetters( name );
|
||||
datAccCall += generateSetDatAccessCall( name );
|
||||
constructorDecl += generateConstructorsDecl( name );
|
||||
idListGetters += generateIdListGetter( name );
|
||||
}
|
||||
|
||||
getterDecl +=
|
||||
|
|
|
@ -21,8 +21,8 @@ Core::Logger g_log;
|
|||
Core::Data::ExdDataGenerated g_exdData;
|
||||
|
||||
|
||||
const std::string datLocation( "/opt/sapphire_3_15_0/bin/sqpack" );
|
||||
//const std::string datLocation( "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv" );
|
||||
//const std::string datLocation( "/opt/sapphire_3_15_0/bin/sqpack" );
|
||||
const std::string datLocation( "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack" );
|
||||
|
||||
|
||||
int main()
|
||||
|
@ -38,15 +38,20 @@ int main()
|
|||
}
|
||||
|
||||
|
||||
g_log.info( "getting id list " );
|
||||
auto idList = g_exdData.getTerritoryTypeIdList();
|
||||
//g_log.info( "getting id list " );
|
||||
//auto idList = g_exdData.getGilShopIdList();
|
||||
|
||||
g_log.info( "getting id list done" );
|
||||
for( auto id : idList )
|
||||
//g_log.info( "getting id list done" );
|
||||
//for( auto id : idList )
|
||||
{
|
||||
auto teri1 = g_exdData.get< Core::Data::TerritoryType >( id );
|
||||
auto teri1 = g_exdData.get< Core::Data::GilShopItem >( 262440, 0 );
|
||||
g_log.info( "0 -> " + std::to_string( teri1->item ) );
|
||||
|
||||
g_log.info( teri1->name );
|
||||
auto teri2 = g_exdData.get< Core::Data::GilShopItem >( 262440, 1 );
|
||||
g_log.info( "1 -> " + std::to_string( teri2->item ) );
|
||||
|
||||
auto teri3 = g_exdData.get< Core::Data::GilShopItem >( 262440, 2 );
|
||||
g_log.info( "2 -> " + std::to_string( teri3->item ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue