1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-27 14:57:44 +00:00

Merge remote-tracking branch 'SapphireServer/develop' into develop

This commit is contained in:
Jeido 2020-11-26 19:14:12 +01:00
commit a9e6c85a5e
371 changed files with 32780 additions and 21115 deletions

View file

@ -1,5 +1,5 @@
os:
- Visual Studio 2017
- Visual Studio 2019
configuration:
- Debug
@ -20,8 +20,8 @@ before_build:
- git submodule update --init
- mkdir build
- cd build
- cmake .. -G "Visual Studio 15 2017 Win64"
- cmake --build . --target ALL_BUILD --config Release
- cmake .. -G "Visual Studio 16 2019" -A x64
- cmake --build . --target ALL_BUILD --config RelWithDebInfo
build_script:
- cd bin

3
.gitmodules vendored
View file

@ -7,3 +7,6 @@
[submodule "deps/recastnavigation"]
path = deps/recastnavigation
url = https://github.com/SapphireServer/recastnavigation
[submodule "deps/ffxiv-actions"]
path = deps/ffxiv-actions
url = https://github.com/SapphireServer/ffxiv-actions.git

View file

@ -14,9 +14,10 @@ matrix:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
- g++-8
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
- CXX=g++-8
# Setup cache
cache:

View file

@ -13,7 +13,9 @@ add_custom_target( copy_runtime_files ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/config ${CMAKE_BINARY_DIR}/bin/config
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/sql ${CMAKE_BINARY_DIR}/bin/sql
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/web ${CMAKE_BINARY_DIR}/bin/web
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/sql_import.sh ${CMAKE_BINARY_DIR}/bin/sql_import.sh )
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/sql_import.sh ${CMAKE_BINARY_DIR}/bin/sql_import.sh
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/bin/data/actions
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/deps/ffxiv-actions/actions ${CMAKE_BINARY_DIR}/bin/data/actions )
######################################
# Dependencies and compiler settings #
@ -44,7 +46,6 @@ add_subdirectory( "deps/MySQL" )
add_subdirectory( "deps/datReader" )
add_subdirectory( "deps/mysqlConnector" )
add_subdirectory( "deps/recastnavigation" )
add_subdirectory( "deps/stackwalker" )
##############################
# Main Sapphire Components #

View file

@ -1,21 +1,32 @@
{
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
"environments": [
{
"BuildDir": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build"
}
],
"configurations": [
{
"name": "x64-Debug",
"generator": "Visual Studio 15 2017 Win64",
"generator": "Visual Studio 16 2019 Win64",
"configurationType": "Debug",
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"buildRoot": "${env.BuildDir}\\${name}",
"cmakeCommandArgs": "-DCMAKE_BUILD_TYPE=\"Debug\"",
"buildCommandArgs": "-m -v:minimal"
"buildCommandArgs": "-m -v:minimal",
"inheritEnvironments": [
"msvc_x64"
]
},
{
"name": "x64-Release",
"generator": "Visual Studio 15 2017 Win64",
"generator": "Visual Studio 16 2019 Win64",
"configurationType": "Release",
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal"
"buildRoot": "${env.BuildDir}\\${name}",
"cmakeCommandArgs": "-DCMAKE_BUILD_TYPE=\"RelWithDebInfo\"",
"buildCommandArgs": "-m -v:minimal",
"inheritEnvironments": [
"msvc_x64"
]
}
]
}

View file

@ -18,7 +18,7 @@ Sapphire requires the following software:
| *Name* | *Windows* | *Linux* |
| ------ | --------- | ------- |
| CMake 3.0.2+ and C++17 capable compiler | [Visual Studio 2017](https://www.visualstudio.com/) | `gcc 7` and `g++ 7` or newer |
| CMake 3.0.2+ and C++17 capable compiler | [Visual Studio 2019](https://www.visualstudio.com/) | `gcc 8` and `g++ 8` or newer, or equivalent `clang` version. |
| MySQL Server 5.7 | [Official Site](https://dev.mysql.com/downloads/mysql/) | MySQL server from your distribution's package manager |
Please check the [wiki](https://github.com/SapphireMordred/Sapphire/wiki) for detailed installation/build instructions for your OS.

View file

@ -60,6 +60,7 @@ if( UNIX )
else( MYSQL_CONFIG )
set(MYSQL_ADD_LIBRARIES "")
list(APPEND MYSQL_ADD_LIBRARIES "mysqlclient_r")
list(APPEND MYSQL_ADD_LIBRARIES "mariadbclient")
endif( MYSQL_CONFIG )
endif( UNIX )
@ -76,6 +77,7 @@ find_path(MYSQL_INCLUDE_DIR
PATHS
${MYSQL_ADD_INCLUDE_PATH}
/usr/include
/usr/include/mariadb
/usr/include/mysql
/usr/local/include
/usr/local/include/mysql
@ -83,6 +85,8 @@ find_path(MYSQL_INCLUDE_DIR
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.7/include"
"${PROGRAM_FILES_64}/MySQL/include"
"${PROGRAM_FILES_64}/MariaDB 10.3/include/mysql"
"${PROGRAM_FILES_64}/MariaDB 10.4/include/mysql"
"${PROGRAM_FILES_64}/MariaDB 10.5/include/mysql"
"C:/MySQL/include"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/include"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.7/include"
@ -97,7 +101,7 @@ if( UNIX )
foreach(LIB ${MYSQL_ADD_LIBRARIES})
find_library( MYSQL_LIBRARY
NAMES
mysql libmysql ${LIB}
mysql libmysql libmariadb ${LIB}
PATHS
${MYSQL_ADD_LIBRARIES_PATH}
/usr/lib
@ -105,6 +109,7 @@ if( UNIX )
/usr/local/lib
/usr/local/lib/mysql
/usr/local/mysql/lib
/usr/lib/x86_64-linux-gnu
DOC "Specify the location of the mysql library here."
)
endforeach(LIB ${MYSQL_ADD_LIBRARY})
@ -121,6 +126,8 @@ if( WIN32 )
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.7/lib/opt"
"${PROGRAM_FILES_64}/MySQL/lib"
"${PROGRAM_FILES_64}/MariaDB 10.3/lib"
"${PROGRAM_FILES_64}/MariaDB 10.4/lib"
"${PROGRAM_FILES_64}/MariaDB 10.5/lib"
"C:/MySQL/lib/debug"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/lib"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/lib/opt"
@ -174,6 +181,8 @@ if( WIN32 )
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.7/bin/opt"
"${PROGRAM_FILES_64}/MySQL/bin"
"${PROGRAM_FILES_64}/MariaDB 10.3/bin"
"${PROGRAM_FILES_64}/MariaDB 10.4/bin"
"${PROGRAM_FILES_64}/MariaDB 10.5/bin"
"C:/MySQL/bin/debug"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/bin"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/bin/opt"

View file

@ -13,3 +13,4 @@ endif()
# Create log folder
file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin/log )
file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin/navi )
file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin/data )

View file

@ -4,14 +4,11 @@
#include "File.h"
namespace
{
namespace {
const uint32_t model_section_count = 0xB;
}
namespace xiv
{
namespace dat
namespace xiv::dat
{
struct DatFileHeader
{
@ -63,15 +60,9 @@ namespace dat
uint32_t block_id;
uint32_t block_count;
};
}
}
namespace xiv
{
namespace utils
{
namespace bparse
namespace xiv::utils::bparse
{
template<>
inline void reorder< xiv::dat::DatFileHeader >( xiv::dat::DatFileHeader& i_struct )
@ -79,7 +70,10 @@ namespace bparse
xiv::utils::bparse::reorder( i_struct.size );
xiv::utils::bparse::reorder( i_struct.entry_type );
xiv::utils::bparse::reorder( i_struct.total_uncompressed_size );
for (int32_t i = 0; i < 0x2; ++i) { xiv::utils::bparse::reorder(i_struct.unknown[i]); }
for( int32_t i = 0; i < 0x2; ++i )
{
xiv::utils::bparse::reorder( i_struct.unknown[ i ] );
}
}
template<>
@ -87,7 +81,10 @@ namespace bparse
{
xiv::utils::bparse::reorder( i_struct.offset );
xiv::utils::bparse::reorder( i_struct.size );
for (int32_t i = 0; i < 0x4; ++i) { xiv::utils::bparse::reorder(i_struct.unknown[i]); }
for( int32_t i = 0; i < 0x4; ++i )
{
xiv::utils::bparse::reorder( i_struct.unknown[ i ] );
}
xiv::utils::bparse::reorder( i_struct.block_hash );
}
@ -112,12 +109,30 @@ namespace bparse
inline void reorder< xiv::dat::DatMdlFileBlockInfos >( xiv::dat::DatMdlFileBlockInfos& i_struct )
{
xiv::utils::bparse::reorder( i_struct.unknown1 );
for (auto i = 0; i < ::model_section_count; ++i) { xiv::utils::bparse::reorder(i_struct.uncompressed_sizes[i]); }
for (auto i = 0; i < ::model_section_count; ++i) { xiv::utils::bparse::reorder(i_struct.compressed_sizes[i]); }
for (auto i = 0; i < ::model_section_count; ++i) { xiv::utils::bparse::reorder(i_struct.offsets[i]); }
for (auto i = 0; i < ::model_section_count; ++i) { xiv::utils::bparse::reorder(i_struct.block_ids[i]); }
for (auto i = 0; i < ::model_section_count; ++i) { xiv::utils::bparse::reorder(i_struct.block_counts[i]); }
for (auto i = 0; i < 0x2; ++i) { xiv::utils::bparse::reorder(i_struct.unknown2[i]); }
for( auto i = 0; i < ::model_section_count; ++i )
{
xiv::utils::bparse::reorder( i_struct.uncompressed_sizes[ i ] );
}
for( auto i = 0; i < ::model_section_count; ++i )
{
xiv::utils::bparse::reorder( i_struct.compressed_sizes[ i ] );
}
for( auto i = 0; i < ::model_section_count; ++i )
{
xiv::utils::bparse::reorder( i_struct.offsets[ i ] );
}
for( auto i = 0; i < ::model_section_count; ++i )
{
xiv::utils::bparse::reorder( i_struct.block_ids[ i ] );
}
for( auto i = 0; i < ::model_section_count; ++i )
{
xiv::utils::bparse::reorder( i_struct.block_counts[ i ] );
}
for( auto i = 0; i < 0x2; ++i )
{
xiv::utils::bparse::reorder( i_struct.unknown2[ i ] );
}
}
template<>
@ -130,17 +145,13 @@ namespace bparse
xiv::utils::bparse::reorder( i_struct.block_count );
}
}
}
};
using xiv::utils::bparse::extract;
namespace xiv
{
namespace dat
namespace xiv::dat
{
Dat::Dat( const std::experimental::filesystem::path& i_path, uint32_t i_nb ) :
Dat::Dat( const std::filesystem::path& i_path, uint32_t i_nb ) :
SqPack( i_path ),
m_num( i_nb )
{
@ -266,7 +277,8 @@ std::unique_ptr<File> Dat::getFile( uint32_t i_offset )
break;
default:
throw std::runtime_error("Invalid entry_type: " + std::to_string(static_cast<uint32_t>(file_header.entry_type)));
throw std::runtime_error(
"Invalid entry_type: " + std::to_string( static_cast<uint32_t>(file_header.entry_type) ) );
}
}
@ -308,4 +320,3 @@ uint32_t Dat::getNum() const
}
}
}

View file

@ -5,11 +5,9 @@
#include <mutex>
#include <experimental/filesystem>
#include <filesystem>
namespace xiv
{
namespace dat
namespace xiv::dat
{
class File;
@ -18,7 +16,7 @@ class Dat : public SqPack
{
public:
// Full path to the dat file
Dat( const std::experimental::filesystem::path& i_path, uint32_t i_nb );
Dat( const std::filesystem::path& i_path, uint32_t i_nb );
virtual ~Dat();
// Retrieves a file given the offset in the dat file
@ -39,7 +37,6 @@ protected:
uint32_t m_num;
};
}
}
#endif // XIV_DAT_DAT_H

View file

@ -10,7 +10,7 @@ namespace xiv
namespace dat
{
Cat::Cat( const std::experimental::filesystem::path& basePath, uint32_t catNum, const std::string& name ) :
Cat::Cat( const std::filesystem::path& basePath, uint32_t catNum, const std::string& name ) :
m_name( name ),
m_catNum( catNum ),
m_chunk( -1 )
@ -21,27 +21,27 @@ Cat::Cat( const std::experimental::filesystem::path& basePath, uint32_t catNum,
std::string prefix = ss.str() + "0000.win32";
// Creates the index: XX0000.win32.index
m_index = std::unique_ptr<Index>( new Index( basePath / "//ffxiv" / ( prefix + ".index" ) ) );
m_index = std::unique_ptr<Index>( new Index( basePath / "ffxiv" / ( prefix + ".index" ) ) );
// For all dat files linked to this index, create it: XX0000.win32.datX
for( uint32_t i = 0; i < getIndex().getDatCount(); ++i )
{
m_dats.emplace_back( std::unique_ptr<Dat>( new Dat( basePath / "//ffxiv" / ( prefix + ".dat" + std::to_string( i ) ), i ) ) );
m_dats.emplace_back( std::make_unique< Dat >(basePath / "ffxiv" / ( prefix + ".dat" + std::to_string( i ) ), i ) );
}
}
Cat::Cat( const std::experimental::filesystem::path& basePath, uint32_t catNum, const std::string& name, uint32_t exNum, uint32_t chunk ) :
Cat::Cat( const std::filesystem::path& basePath, uint32_t catNum, const std::string& name, uint32_t exNum, uint32_t chunk ) :
m_name( name ),
m_catNum( catNum ),
m_chunk( chunk )
{
// Creates the index: XX0000.win32.index
m_index = std::unique_ptr<Index>( new Index( basePath / GameData::buildDatStr( "ex" + std::to_string( exNum ), catNum, exNum, chunk, "win32", "index" ) ) );
m_index = std::make_unique< Index >( basePath / GameData::buildDatStr( "ex" + std::to_string( exNum ), catNum, exNum, chunk, "win32", "index" ) );
// For all dat files linked to this index, create it: XX0000.win32.datX
for( uint32_t i = 0; i < getIndex().getDatCount(); ++i )
{
m_dats.emplace_back( std::unique_ptr<Dat>( new Dat( basePath / GameData::buildDatStr( "ex" + std::to_string( exNum ), catNum, exNum, chunk, "win32", "dat" + std::to_string( i ) ), i ) ) );
m_dats.emplace_back( std::make_unique< Dat >( basePath / GameData::buildDatStr( "ex" + std::to_string( exNum ), catNum, exNum, chunk, "win32", "dat" + std::to_string( i ) ), i ) );
}
}

View file

@ -3,13 +3,15 @@
#include <memory>
#include <vector>
#include <experimental/filesystem>
#include <filesystem>
namespace xiv {
namespace dat {
namespace xiv::dat
{
class Index;
class Dat;
class File;
// A category represents an .index and its associated .datX
@ -19,14 +21,16 @@ public:
// basePath: Path to the folder containingthe datfiles
// catNum: The number of the category
// name: The name of the category, empty if not known
Cat( const std::experimental::filesystem::path& basePath, uint32_t catNum, const std::string& name );
Cat( const std::filesystem::path& basePath, uint32_t catNum, const std::string& name );
// basePath: Path to the folder containingthe datfiles
// catNum: The number of the category
// name: The name of the category, empty if not known
// exNum: The number of the expansion to load from
// chunk: The chunk to load from
Cat( const std::experimental::filesystem::path& basePath, uint32_t catNum, const std::string& name, uint32_t exNum, uint32_t chunk );
Cat( const std::filesystem::path& basePath, uint32_t catNum, const std::string& name, uint32_t exNum,
uint32_t chunk );
~Cat();
// Returns .index of the category
@ -37,6 +41,7 @@ public:
bool doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const;
bool doesDirExist( uint32_t dir_hash ) const;
@ -58,7 +63,6 @@ protected:
std::vector< std::unique_ptr< Dat>> m_dats;
};
}
}
#endif // XIV_DAT_CAT_H

View file

@ -0,0 +1,198 @@
#ifndef SAPPHIRE_LGBTYPES_H
#define SAPPHIRE_LGBTYPES_H
#include "vec3.h"
enum class LgbEntryType : uint32_t
{
BgParts = 1,
Attribute = 2,
Light = 3,
Vfx = 4,
PositionMarker = 5,
Gimmick = 6,
SharedGroup6 = 6,// secondary variable is set to 2
Sound = 7,
EventNpc = 8,
BattleNpc = 9,
RoutePath = 10,
Character = 11,
Aetheryte = 12,
EnvSpace = 13,
Gathering = 14,
SharedGroup15 = 15,// secondary variable is set to 13
Treasure = 16,
Player = 37,
Monster = 38,
Weapon = 39,
PopRange = 40,
ExitRange = 41,
LVB = 42,
MapRange = 43,
NaviMeshRange = 44,
EventObject = 45,
DemiHuman = 46,
EnvLocation = 47,
ControlPoint = 48,
EventRange = 49,
RestBonusRange = 50,
QuestMarker = 51,
TimeLine = 52,
ObjectBehaviorSet = 53,
Movie = 54,
ScenarioEXD = 55,
ScenarioText = 56,
CollisionBox = 57,
DoorRange = 58,
LineVfx = 59,
SoundEnvSet = 60,
CutActionTimeline = 61,
CharaScene = 62,
CutAction = 63,
EquipPreset = 64,
ClientPath = 65,
ServerPath = 66,
GimmickRange = 67,
TargetMarker = 68,
ChairMarker = 69,
ClickableRange = 70,
PrefetchRange = 71,
FateRange = 72,
PartyMember = 73,
KeepRange = 74,
SphereCastRange = 75,
IndoorObject = 76,
OutdoorObject = 77,
EditGroup = 78,
StableChocobo = 79
};
enum PopType : uint32_t
{
PopTypePC = 0x1,
PopTypeNPC = 0x2,
PopTypeBNPC = 0x2,
PopTypeContent = 0x3,
};
struct Transformation
{
vec3 translation;
vec3 rotation;
vec3 scale;
};
struct InstanceObject
{
LgbEntryType type;
uint32_t instanceId;
uint32_t nameOffset;
Transformation transform;
};
struct BgPartsData : public InstanceObject
{
uint32_t modelFileOffset;
uint32_t collisionFileOffset;
uint32_t unknown4;
uint32_t unknown5;
uint32_t unknown6;
uint32_t unknown7;
uint32_t unknown8;
uint32_t unknown9;
};
struct RelativePositions
{
int32_t Pos;
int32_t PosCount;
};
struct PopRangeData : public InstanceObject
{
PopType popType;
RelativePositions relativePositions;
float innerRadiusRatio;
uint8_t index;
uint8_t padding00[3];
uint32_t reserved;
};
struct GimmickData : public InstanceObject
{
uint32_t gimmickFileOffset;
char unknownBytes[100];
};
struct ENpcData : public InstanceObject
{
uint32_t enpcId;
uint8_t unknown1[0x24];
};
struct EObjData : public InstanceObject
{
uint32_t eobjId;
uint32_t levelHierachyId;
uint8_t unknown1[0xC];
};
enum TriggerBoxShape : uint32_t
{
TriggerBoxShapeBox = 0x1,
TriggerBoxShapeSphere = 0x2,
TriggerBoxShapeCylinder = 0x3,
TriggerBoxShapeBoard = 0x4,
TriggerBoxShapeMesh = 0x5,
TriggerBoxShapeBoardBothSides = 0x6,
};
struct TriggerBoxInstanceObject
{
TriggerBoxShape triggerBoxShape;
int16_t priority;
int8_t enabled;
uint8_t padding;
uint32_t reserved;
};
struct ExitRangeData : public InstanceObject
{
TriggerBoxInstanceObject triggerBoxType;
uint32_t exitType;
uint16_t zoneId;
uint16_t destTerritoryType;
int index;
uint32_t destInstanceObjectId;
uint32_t returnInstanceObjectId;
float direction;
uint32_t reserved;
};
struct MapRangeData : public InstanceObject
{
TriggerBoxInstanceObject triggerBoxType;
uint32_t mapId;
uint32_t placeNameBlock;
uint32_t placeNameSpot;
uint32_t bGM;
uint32_t weather;
uint32_t reserved;
uint32_t reserved2;
uint16_t reserved3;
uint8_t housingBlockId;
int8_t restBonusEffective;
uint8_t discoveryIndex;
int8_t mapEnabled;
int8_t placeNameEnabled;
int8_t discoveryEnabled;
int8_t bGMEnabled;
int8_t weatherEnabled;
int8_t restBonusEnabled;
int8_t bGMPlayZoneInOnly;
int8_t liftEnabled;
int8_t housingEnabled;
uint16_t padding;
};
#endif //SAPPHIRE_LGBTYPES_H

View file

@ -12,87 +12,33 @@
#include "matrix4.h"
#include "vec3.h"
#include "sgb.h"
#include "LgbTypes.h"
// garbage to skip model loading
extern bool ignoreModels;
// all credit to
// https://github.com/ufx/SaintCoinach/blob/master/SaintCoinach/Graphics/Lgb/
// this is simply their work ported to c++ since we dont c#
// based on https://github.com/ufx/SaintCoinach/blob/master/SaintCoinach/Graphics/Lgb/
struct LGB_FILE;
struct LGB_FILE_HEADER;
struct LGB_GROUP;
struct LGB_GROUP_HEADER;
enum class LgbEntryType :
uint32_t
{
BgParts = 1,
Light = 3,
Vfx = 4,
PositionMarker = 5,
Gimmick = 6,
SharedGroup6 = 6,// secondary variable is set to 2
Sound = 7,
EventNpc = 8,
BattleNpc = 9,
Aetheryte = 12,
EnvSpace = 13,
Gathering = 14,
SharedGroup15 = 15,// secondary variable is set to 13
Treasure = 16,
Weapon = 39,
PopRange = 40,
ExitRange = 41,
MapRange = 43,
NaviMeshRange = 44,
EventObject = 45,
EnvLocation = 47,
EventRange = 49,
QuestMarker = 51,
CollisionBox = 57,
DoorRange = 58,
LineVfx = 59,
ClientPath = 65,
ServerPath = 66,
GimmickRange = 67,
TargetMarker = 68,
ChairMarker = 69,
ClickableRange = 70,
PrefetchRange = 71,
FateRange = 72,
SphereCastRange = 75,
};
struct LGB_ENTRY_HEADER
{
LgbEntryType type;
uint32_t unknown;
uint32_t nameOffset;
vec3 translation;
vec3 rotation;
vec3 scale;
};
class LGB_ENTRY
class LgbEntry
{
public:
char* m_buf;
uint32_t m_offset;
LGB_ENTRY_HEADER header;
InstanceObject header;
LGB_ENTRY()
LgbEntry()
{
m_buf = nullptr;
m_offset = 0;
memset( &header, 0, sizeof( header ) );
};
LGB_ENTRY( char* buf, uint32_t offset )
LgbEntry( char* buf, uint32_t offset )
{
m_buf = buf;
m_offset = offset;
header = *reinterpret_cast< LGB_ENTRY_HEADER* >( buf + offset );
header = *reinterpret_cast< InstanceObject* >( buf + offset );
};
const LgbEntryType getType() const
@ -100,30 +46,16 @@ public:
return header.type;
};
virtual ~LGB_ENTRY()
virtual ~LgbEntry()
{
};
};
struct LGB_BGPARTS_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t modelFileOffset;
uint32_t collisionFileOffset;
uint32_t unknown4;
uint32_t unknown5;
uint32_t unknown6;
uint32_t unknown7;
uint32_t unknown8;
uint32_t unknown9;
};
class LGB_BGPARTS_ENTRY :
public LGB_ENTRY
class LGB_BGPARTS_ENTRY : public LgbEntry
{
public:
LGB_BGPARTS_HEADER header;
BgPartsData data;
std::string name;
std::string modelFileName;
std::string collisionFileName;
@ -132,124 +64,94 @@ public:
{
};
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
header = *reinterpret_cast<LGB_BGPARTS_HEADER*>( buf + offset );
data = *reinterpret_cast< BgPartsData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
modelFileName = std::string( buf + offset + header.modelFileOffset );
collisionFileName = std::string( buf + offset + header.collisionFileOffset );
modelFileName = std::string( buf + offset + data.modelFileOffset );
collisionFileName = std::string( buf + offset + data.collisionFileOffset );
};
};
struct LGB_GIMMICK_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t gimmickFileOffset;
char unknownBytes[100];
};
class LGB_GIMMICK_ENTRY :
public LGB_ENTRY
class LGB_GIMMICK_ENTRY : public LgbEntry
{
public:
LGB_GIMMICK_HEADER header;
GimmickData data;
std::string name;
std::string gimmickFileName;
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>( buf + offset );
data = *reinterpret_cast< GimmickData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
gimmickFileName = std::string( buf + offset + header.gimmickFileOffset );
//std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n";
gimmickFileName = std::string( buf + offset + data.gimmickFileOffset );
};
};
struct LGB_ENPC_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t enpcId;
uint8_t unknown1[0x24];
};
class LGB_ENPC_ENTRY :
public LGB_ENTRY
class LGB_ENPC_ENTRY : public LgbEntry
{
public:
LGB_ENPC_HEADER header;
ENpcData data;
std::string name;
LGB_ENPC_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset );
data = *reinterpret_cast< ENpcData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
//std::cout << "\t ENpc " << header.enpcId << " " << name << "\n";
};
};
struct LGB_EOBJ_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t eobjId;
uint32_t levelHierachyId;
uint8_t unknown1[0xC];
};
class LGB_EOBJ_ENTRY :
public LGB_ENTRY
class LGB_EOBJ_ENTRY : public LgbEntry
{
public:
LGB_EOBJ_HEADER header;
EObjData data;
std::string name;
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset );
//std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n";
data = *reinterpret_cast< EObjData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_MAPRANGE_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t type;
uint8_t unknown2;
uint8_t unknown2_1;
uint16_t unknown3;
uint32_t unknown5;
uint32_t mapId;
uint32_t offsetX;
uint32_t offsetY;
uint32_t unkInts[4];
uint16_t unkShort;
uint8_t unkFlag;
uint8_t unkFlag2;
uint8_t discoveryIndex;
uint8_t unkFlag3;
uint8_t unkFlag4;
uint8_t unknown4[0x09];
};
struct LGB_MAPRANGE_ENTRY :
public LGB_ENTRY
struct LGB_MAP_RANGE_ENTRY : public LgbEntry
{
public:
LGB_MAPRANGE_HEADER header;
MapRangeData data;
std::string name;
LGB_MAPRANGE_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LGB_MAP_RANGE_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_MAPRANGE_HEADER* >( buf + offset );
data = *reinterpret_cast< MapRangeData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_EXIT_RANGE_ENTRY : public LgbEntry
{
public:
ExitRangeData data;
std::string name;
LGB_EXIT_RANGE_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
data = *reinterpret_cast< ExitRangeData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_POP_RANGE_ENTRY : public LgbEntry
{
public:
PopRangeData data;
LGB_POP_RANGE_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
data = *reinterpret_cast< PopRangeData* >( buf + offset );
};
};
struct LGB_GROUP_HEADER
{
uint32_t id;
@ -272,15 +174,13 @@ struct LGB_GROUP
LGB_FILE* parent;
LGB_GROUP_HEADER header;
std::string name;
std::vector< std::shared_ptr< LGB_ENTRY > > entries;
std::vector< std::shared_ptr< LgbEntry > > entries;
LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset )
{
parent = parentStruct;
header = *reinterpret_cast< LGB_GROUP_HEADER* >( buf + offset );
name = std::string( buf + offset + header.groupNameOffset );
//entries.resize( header.entryCount );
//std::cout << name << "\n\t unknown: " << header.unknown << "\n";
const auto entriesOffset = offset + header.entriesOffset;
for( auto i = 0; i < header.entryCount; ++i )
{
@ -289,7 +189,6 @@ struct LGB_GROUP
try
{
const auto type = *reinterpret_cast< LgbEntryType* >( buf + entryOffset );
// garbage to skip model loading
if( type == LgbEntryType::BgParts )
{
entries.push_back( std::make_shared< LGB_BGPARTS_ENTRY >( buf, entryOffset ) );
@ -306,16 +205,18 @@ struct LGB_GROUP
{
entries.push_back( std::make_shared< LGB_EOBJ_ENTRY >( buf, entryOffset ) );
}
else if( type == LgbEntryType::ExitRange )
{
entries.push_back( std::make_shared< LGB_EXIT_RANGE_ENTRY >( buf, entryOffset ) );
}
else if( type == LgbEntryType::MapRange )
{
entries.push_back( std::make_shared< LGB_MAPRANGE_ENTRY >( buf, entryOffset ) );
entries.push_back( std::make_shared< LGB_MAP_RANGE_ENTRY >( buf, entryOffset ) );
}
else
{
entries.push_back( std::make_shared< LGB_ENTRY >( buf, entryOffset ) );
entries.push_back( std::make_shared< LgbEntry >( buf, entryOffset ) );
}
}
catch( std::exception& e )
{
@ -344,8 +245,7 @@ struct LGB_FILE
std::vector< LGB_GROUP > groups;
std::string m_name;
LGB_FILE( char* buf, const std::string& name ) :
LGB_FILE( buf )
LGB_FILE( char* buf, const std::string& name ) : LGB_FILE( buf )
{
m_name = name;
}
@ -356,8 +256,6 @@ struct LGB_FILE
if( strncmp( &header.magic[ 0 ], "LGB1", 4 ) != 0 || strncmp( &header.magic2[ 0 ], "LGP1", 4 ) != 0 )
throw std::runtime_error( "Invalid LGB file!" );
//groups.resize(header.groupCount);
constexpr auto baseOffset = sizeof( header );
for( auto i = 0; i < header.groupCount; ++i )
{

View file

@ -22,15 +22,13 @@ struct SGB_GROUP;
struct SGB_GROUP_HEADER;
enum SgbDataType :
uint32_t
enum SgbDataType : uint32_t
{
Unknown0008 = 0x0008,
Group = 0x0100,
};
enum SgbGroupEntryType :
uint32_t
enum SgbGroupEntryType : uint32_t
{
Model = 0x01,
Gimmick = 0x06,
@ -124,15 +122,13 @@ struct SGB_ENTRY_HEADER
vec3 scale;
};
struct SGB_MODEL_HEADER :
public SGB_ENTRY_HEADER
struct SGB_MODEL_HEADER : public SGB_ENTRY_HEADER
{
int32_t modelFileOffset;
int32_t collisionFileOffset;
};
struct SGB_MODEL_ENTRY :
public SGB_GROUP_ENTRY
struct SGB_MODEL_ENTRY : public SGB_GROUP_ENTRY
{
SGB_MODEL_HEADER header;
SgbGroupEntryType type;

View file

@ -8,11 +8,8 @@
using xiv::utils::bparse::extract;
namespace xiv
namespace xiv::exd
{
namespace exd
{
struct ExdHeader
{
char magic[0x4];
@ -26,27 +23,36 @@ namespace xiv
uint32_t id;
uint32_t offset;
};
}
}
namespace xiv
namespace xiv::utils::bparse {
template<>
inline void reorder< xiv::exd::ExdHeader >( xiv::exd::ExdHeader& i_struct )
{
namespace utils
for( int32_t i = 0; i < 0x4; ++i )
{
namespace bparse
{
template <> inline void reorder<xiv::exd::ExdHeader>( xiv::exd::ExdHeader& i_struct ) { for( int32_t i = 0; i < 0x4; ++i ) { xiv::utils::bparse::reorder( i_struct.magic[i] ); } i_struct.unknown = xiv::utils::bparse::byteswap( i_struct.unknown ); xiv::utils::bparse::reorder( i_struct.unknown ); i_struct.unknown2 = xiv::utils::bparse::byteswap( i_struct.unknown2 ); xiv::utils::bparse::reorder( i_struct.unknown2 ); i_struct.index_size = xiv::utils::bparse::byteswap( i_struct.index_size ); xiv::utils::bparse::reorder( i_struct.index_size ); }
template <> inline void reorder<xiv::exd::ExdRecordIndex>( xiv::exd::ExdRecordIndex& i_struct ) { i_struct.id = xiv::utils::bparse::byteswap( i_struct.id ); xiv::utils::bparse::reorder( i_struct.id ); i_struct.offset = xiv::utils::bparse::byteswap( i_struct.offset ); xiv::utils::bparse::reorder( i_struct.offset ); }
xiv::utils::bparse::reorder( i_struct.magic[ i ] );
}
i_struct.unknown = xiv::utils::bparse::byteswap( i_struct.unknown );
xiv::utils::bparse::reorder( i_struct.unknown );
i_struct.unknown2 = xiv::utils::bparse::byteswap( i_struct.unknown2 );
xiv::utils::bparse::reorder( i_struct.unknown2 );
i_struct.index_size = xiv::utils::bparse::byteswap( i_struct.index_size );
xiv::utils::bparse::reorder( i_struct.index_size );
}
template<>
inline void reorder< xiv::exd::ExdRecordIndex >( xiv::exd::ExdRecordIndex& i_struct )
{
i_struct.id = xiv::utils::bparse::byteswap( i_struct.id );
xiv::utils::bparse::reorder( i_struct.id );
i_struct.offset = xiv::utils::bparse::byteswap( i_struct.offset );
xiv::utils::bparse::reorder( i_struct.offset );
}
};
namespace xiv
namespace xiv::exd
{
namespace exd
{
Exd::Exd( std::shared_ptr< Exh > i_exh, const std::vector< std::shared_ptr< dat::File>>& i_files )
{
_exh = i_exh;
@ -376,5 +382,4 @@ namespace xiv
}
}
}

12
deps/datReader/Exd.h vendored
View file

@ -8,9 +8,7 @@
#include "File.h"
namespace xiv
{
namespace exd
namespace xiv::exd
{
class Exh;
@ -40,8 +38,12 @@ class Exd
public:
// i_exh: the header
// i_files: the multiple exd files
Exd() {}
Exd()
{
}
Exd( std::shared_ptr< Exh > i_exh, const std::vector< std::shared_ptr< dat::File>>& i_files );
~Exd();
// Get a row by its id
@ -49,6 +51,7 @@ public:
// 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();
@ -60,7 +63,6 @@ protected:
std::map< uint32_t, ExdCacheEntry > _idCache;
};
}
}
#endif // XIV_EXD_EXD_H

View file

@ -11,19 +11,18 @@ namespace
{
// Suffix of the filenames given a language
std::map<xiv::exd::Language, std::string> language_map =
{{xiv::exd::Language::none, ""},
{
{xiv::exd::Language::none, ""},
{xiv::exd::Language::ja, "_ja"},
{xiv::exd::Language::en, "_en"},
{xiv::exd::Language::de, "_de"},
{xiv::exd::Language::fr, "_fr"},
{xiv::exd::Language::chs, "_chs"}};
{xiv::exd::Language::chs, "_chs"}
};
}
namespace xiv
namespace xiv::exd
{
namespace exd
{
Cat::Cat( dat::GameData& i_game_data, const std::string& i_name ) :
_name( i_name )
{
@ -44,10 +43,11 @@ namespace xiv
std::vector< std::shared_ptr< dat::File>> files;
for( auto& exd_def: _header->get_exd_defs() )
{
files.emplace_back( i_game_data.getFile("exd/" + i_name + "_" + std::to_string(exd_def.start_id) + language_map.at(language) + ".exd") );
files.emplace_back( i_game_data.getFile(
"exd/" + i_name + "_" + std::to_string( exd_def.start_id ) + language_map.at( language ) + ".exd" ) );
}
// Instantiate the data for this language
_data[language] = std::unique_ptr<Exd>(new Exd(_header, files));
_data[ language ] = std::make_unique< Exd >( _header, files );
}
}
}
@ -79,4 +79,3 @@ namespace xiv
}
}
}

View file

@ -4,7 +4,7 @@
#include <memory>
#include <map>
#include <experimental/filesystem>
#include <filesystem>
#include "bparse.h"
#include "Exd.h"

View file

@ -7,10 +7,7 @@
#include "ExdCat.h"
namespace xiv
{
namespace exd
{
namespace xiv::exd {
ExdData::ExdData( dat::GameData& i_game_data ) try :
_game_data( i_game_data )
@ -42,7 +39,7 @@ ExdData::ExdData(dat::GameData& i_game_data) try :
// instantiate the creation mutex for this category
_cat_names.push_back( category );
_cats[ category ] = std::unique_ptr< Cat >();
_cat_creation_mutexes[category] = std::unique_ptr<std::mutex>(new std::mutex());
_cat_creation_mutexes[ category ] = std::make_unique< std::mutex >();
std::getline( stream, line );
}
@ -92,9 +89,8 @@ void ExdData::create_category(const std::string& i_cat_name)
// Maybe after unlocking it has already been created, so check (most likely if it blocked)
if( !_cats[ i_cat_name ] )
{
_cats[i_cat_name] = std::unique_ptr<Cat>(new Cat(_game_data, i_cat_name));
_cats[ i_cat_name ] = std::make_unique< Cat >( _game_data, i_cat_name );
}
}
}
}

View file

@ -5,7 +5,7 @@
#include <memory>
#include <mutex>
#include <experimental/filesystem>
#include <filesystem>
namespace xiv
{
@ -34,7 +34,7 @@ namespace xiv
const Cat& get_category(const std::string& i_cat_name);
// Export in csv in base flder i_ouput_path
void export_as_csvs(const std::experimental::filesystem::path& i_output_path);
void export_as_csvs(const std::filesystem::path& i_output_path);
protected:
// Lazy instantiation of category

View file

@ -7,10 +7,9 @@
using xiv::utils::bparse::extract;
namespace xiv
{
namespace exd
namespace xiv::exd
{
Exh::Exh( const dat::File& i_file )
{
// Get a stream from the file
@ -74,4 +73,3 @@ const std::vector<ExhMember>& Exh::get_exh_members() const
}
}
}

66
deps/datReader/Exh.h vendored
View file

@ -5,11 +5,10 @@
#include "bparse.h"
namespace xiv
namespace xiv::exd
{
namespace exd
{
enum class DataType : uint16_t
enum class DataType :
uint16_t
{
string = 0,
boolean = 1,
@ -47,32 +46,60 @@ namespace xiv
uint32_t start_id;
uint32_t count_id;
};
};
namespace xiv::utils::bparse {
template<>
inline void reorder< xiv::exd::ExhHeader >( xiv::exd::ExhHeader& i_struct )
{
for( int32_t i = 0; i < 0x4; ++i )
{
xiv::utils::bparse::reorder( i_struct.magic[ i ] );
}
i_struct.unknown = xiv::utils::bparse::byteswap( i_struct.unknown );
xiv::utils::bparse::reorder( i_struct.unknown );
i_struct.data_offset = xiv::utils::bparse::byteswap( i_struct.data_offset );
xiv::utils::bparse::reorder( i_struct.data_offset );
i_struct.field_count = xiv::utils::bparse::byteswap( i_struct.field_count );
xiv::utils::bparse::reorder( i_struct.field_count );
i_struct.exd_count = xiv::utils::bparse::byteswap( i_struct.exd_count );
xiv::utils::bparse::reorder( i_struct.exd_count );
i_struct.language_count = xiv::utils::bparse::byteswap( i_struct.language_count );
xiv::utils::bparse::reorder( i_struct.language_count );
}
template<>
inline void reorder< xiv::exd::ExhMember >( xiv::exd::ExhMember& i_struct )
{
i_struct.type = xiv::utils::bparse::byteswap( i_struct.type );
xiv::utils::bparse::reorder( i_struct.type );
i_struct.offset = xiv::utils::bparse::byteswap( i_struct.offset );
xiv::utils::bparse::reorder( i_struct.offset );
}
template<>
inline void reorder< xiv::exd::ExhExdDef >( xiv::exd::ExhExdDef& i_struct )
{
i_struct.start_id = xiv::utils::bparse::byteswap( i_struct.start_id );
xiv::utils::bparse::reorder( i_struct.start_id );
i_struct.count_id = xiv::utils::bparse::byteswap( i_struct.count_id );
xiv::utils::bparse::reorder( i_struct.count_id );
}
};
namespace xiv
{
namespace utils
{
namespace bparse
{
template <> inline void reorder<xiv::exd::ExhHeader>( xiv::exd::ExhHeader& i_struct ) { for( int32_t i = 0; i < 0x4; ++i ) { xiv::utils::bparse::reorder( i_struct.magic[i] ); } i_struct.unknown = xiv::utils::bparse::byteswap( i_struct.unknown ); xiv::utils::bparse::reorder( i_struct.unknown ); i_struct.data_offset = xiv::utils::bparse::byteswap( i_struct.data_offset ); xiv::utils::bparse::reorder( i_struct.data_offset ); i_struct.field_count = xiv::utils::bparse::byteswap( i_struct.field_count ); xiv::utils::bparse::reorder( i_struct.field_count ); i_struct.exd_count = xiv::utils::bparse::byteswap( i_struct.exd_count ); xiv::utils::bparse::reorder( i_struct.exd_count ); i_struct.language_count = xiv::utils::bparse::byteswap( i_struct.language_count ); xiv::utils::bparse::reorder( i_struct.language_count ); }
template <> inline void reorder<xiv::exd::ExhMember>( xiv::exd::ExhMember& i_struct ) { i_struct.type = xiv::utils::bparse::byteswap( i_struct.type ); xiv::utils::bparse::reorder( i_struct.type ); i_struct.offset = xiv::utils::bparse::byteswap( i_struct.offset ); xiv::utils::bparse::reorder( i_struct.offset ); }
template <> inline void reorder<xiv::exd::ExhExdDef>( xiv::exd::ExhExdDef& i_struct ) { i_struct.start_id = xiv::utils::bparse::byteswap( i_struct.start_id ); xiv::utils::bparse::reorder( i_struct.start_id ); i_struct.count_id = xiv::utils::bparse::byteswap( i_struct.count_id ); xiv::utils::bparse::reorder( i_struct.count_id ); }
}
}
};
namespace xiv
{
namespace dat
{
class File;
}
namespace exd
{
enum Language : uint16_t;
enum Language :
uint16_t;
// Header file for exd data
class Exh
@ -80,12 +107,17 @@ namespace xiv
public:
// The header file
Exh( const dat::File& i_file );
~Exh();
const ExhHeader& get_header() const;
const std::vector< ExhExdDef >& get_exd_defs() const;
const std::vector< Language >& get_languages() const;
const std::map< uint32_t, ExhMember >& get_members() const;
const std::vector< ExhMember >& get_exh_members() const;
protected:

View file

@ -2,9 +2,7 @@
#include <fstream>
namespace xiv
{
namespace dat
namespace xiv::dat
{
File::File() :
@ -31,7 +29,7 @@ std::vector<std::vector<char>>& File::access_data_sections()
return _data_sections;
}
void File::exportToFile(const std::experimental::filesystem::path& i_path) const
void File::exportToFile( const std::filesystem::path& i_path ) const
{
std::ofstream ofs( i_path.string(), std::ios_base::binary | std::ios_base::out );
for( auto& data_section : _data_sections )
@ -42,4 +40,3 @@ void File::exportToFile(const std::experimental::filesystem::path& i_path) const
}
}
}

24
deps/datReader/File.h vendored
View file

@ -3,29 +3,20 @@
#include <vector>
#include <experimental/filesystem>
#include <filesystem>
#include <stdint.h>
#include "bparse.h"
namespace xiv
namespace xiv::dat
{
namespace dat
{
enum class FileType : uint32_t
enum class FileType :
uint32_t
{
empty = 1,
standard = 2,
model = 3,
texture = 4,
};
}
};
namespace xiv
{
namespace dat
{
class Dat;
@ -33,24 +24,25 @@ namespace xiv
class File
{
friend class Dat;
public:
File();
~File();
FileType get_type() const;
// Getters functions for the data in the file
const std::vector< std::vector< char>>& get_data_sections() const;
std::vector< std::vector< char>>& access_data_sections();
void exportToFile( const std::experimental::filesystem::path& i_path ) const;
void exportToFile( const std::filesystem::path& i_path ) const;
protected:
FileType _type;
std::vector< std::vector< char>> _data_sections;
};
}
}
#endif // XIV_DAT_FILE_H

View file

@ -11,8 +11,7 @@
#include "DatCat.h"
#include "File.h"
namespace
{
namespace {
// Relation between category number and category name
// These names are taken straight from the exe, it helps resolve dispatching when getting files by path
@ -48,12 +47,9 @@ namespace
{ 0x0C, "music" } };
}
namespace xiv
namespace xiv::dat
{
namespace dat
{
GameData::GameData(const std::experimental::filesystem::path& path) try :
GameData::GameData( const std::filesystem::path& path ) try :
m_path( path )
{
int maxExLevel = 0;
@ -62,18 +58,21 @@ GameData::GameData(const std::experimental::filesystem::path& path) try :
#ifdef _WIN32
static constexpr auto sep = "\\";
#else
static constexpr auto sep = std::experimental::filesystem::path::preferred_separator;
static constexpr auto sep = std::filesystem::path::preferred_separator;
#endif
// Determine which expansions are available
while( std::experimental::filesystem::exists( std::experimental::filesystem::path( m_path.string() + sep + "ex" + std::to_string( maxExLevel + 1 ) + sep + "ex" + std::to_string( maxExLevel + 1 ) + ".ver" ) ) )
while( std::filesystem::exists( std::filesystem::path(
m_path.string() + sep + "ex" + std::to_string( maxExLevel + 1 ) + sep + "ex" + std::to_string( maxExLevel + 1 ) +
".ver" ) ) )
{
maxExLevel++;
}
// Iterate over the files in path
for( auto it = std::experimental::filesystem::directory_iterator( m_path.string() + "//ffxiv" ); it != std::experimental::filesystem::directory_iterator(); ++it )
for( auto it = std::filesystem::directory_iterator( m_path.string() + "//ffxiv" );
it != std::filesystem::directory_iterator(); ++it )
{
// Get the filename of the current element
auto filename = it->path().filename().string();
@ -92,21 +91,24 @@ GameData::GameData(const std::experimental::filesystem::path& path) try :
// instantiate the creation mutex for this category
m_catNums.push_back( cat_nb );
m_cats[ cat_nb ] = std::unique_ptr< Cat >();
m_catCreationMutexes[cat_nb] = std::unique_ptr<std::mutex>( new std::mutex() );
m_catCreationMutexes[ cat_nb ] = std::make_unique< std::mutex >();
// Check for expansion
for( int exNum = 1; exNum <= maxExLevel; exNum++ )
{
const std::string path = m_path.string() + sep + buildDatStr( "ex" + std::to_string( exNum ), cat_nb, exNum, 0, "win32", "index" );
const std::string path =
m_path.string() + sep + buildDatStr( "ex" + std::to_string( exNum ), cat_nb, exNum, 0, "win32", "index" );
if( std::experimental::filesystem::exists( std::experimental::filesystem::path( path ) ) )
if( std::filesystem::exists( std::filesystem::path( path ) ) )
{
int chunkCount = 0;
for( int chunkTest = 0; chunkTest < 256; chunkTest++ )
{
if( std::experimental::filesystem::exists( m_path.string() + sep + buildDatStr( "ex" + std::to_string( exNum ), cat_nb, exNum, chunkTest, "win32", "index" ) ) )
if( std::filesystem::exists( m_path.string() + sep +
buildDatStr( "ex" + std::to_string( exNum ), cat_nb, exNum, chunkTest, "win32",
"index" ) ) )
{
m_exCats[ cat_nb ].exNumToChunkMap[ exNum ].chunkToCatMap[ chunkTest ] = std::unique_ptr< Cat >();
chunkCount++;
@ -130,7 +132,8 @@ GameData::~GameData()
}
const std::string GameData::buildDatStr( const std::string folder, const int cat, const int exNum, const int chunk, const std::string platform, const std::string type )
const std::string GameData::buildDatStr( const std::string folder, const int cat, const int exNum, const int chunk,
const std::string platform, const std::string type )
{
char dat[1024];
sprintf( dat, "%s/%02x%02x%02x.%s.%s", folder.c_str(), cat, exNum, chunk, platform.c_str(), type.c_str() );
@ -290,7 +293,7 @@ void GameData::createCategory(uint32_t catNum)
}
// Actually creates the category
m_cats[catNum] = std::unique_ptr<Cat>( new Cat( m_path, catNum, catName ) );
m_cats[ catNum ] = std::make_unique< Cat >( m_path, catNum, catName );
}
}
@ -312,11 +315,11 @@ void GameData::createExCategory( uint32_t catNum )
for( auto const& chunk : m_exCats[ catNum ].exNumToChunkMap[ ex.first ].chunkToCatMap )
{
// Actually creates the category
m_exCats[catNum].exNumToChunkMap[ex.first].chunkToCatMap[chunk.first] = std::unique_ptr<Cat>( new Cat( m_path, catNum, catName, ex.first, chunk.first ) );
m_exCats[ catNum ].exNumToChunkMap[ ex.first ].chunkToCatMap[ chunk.first ] = std::unique_ptr< Cat >(
new Cat( m_path, catNum, catName, ex.first, chunk.first ) );
}
}
}
}
}
}

View file

@ -5,14 +5,13 @@
#include <unordered_map>
#include <mutex>
#include <experimental/filesystem>
#include <filesystem>
namespace xiv
{
namespace dat
namespace xiv::dat
{
class Cat;
class File;
// Interface to all the datfiles - Main entry point
@ -21,16 +20,20 @@ class GameData
{
public:
// This should be the path in which the .index/.datX files are located
GameData( const std::experimental::filesystem::path& path );
GameData( const std::filesystem::path& path );
~GameData();
static const std::string buildDatStr( const std::string folder, const int cat, const int exNum, const int chunk, const std::string platform, const std::string type );
static const std::string
buildDatStr( const std::string folder, const int cat, const int exNum, const int chunk, const std::string platform,
const std::string type );
// Returns all the scanned category number available in the path
const std::vector< uint32_t >& getCatNumbers() const;
// Return a specific category by its number (see getCatNumbers() for loops)
const Cat& getCategory( uint32_t catNum );
// Return a specific category by it's name (e.g.: "exd"/"game_script"/ etc...)
const Cat& getCategory( const std::string& catName );
@ -61,7 +64,7 @@ protected:
void createExCategory( uint32_t catNum );
// Path given to constructor, pointing to the folder with the .index/.datX files
const std::experimental::filesystem::path m_path;
const std::filesystem::path m_path;
// Stored categories, indexed by their number, categories are instantiated and parsed individually when they are needed
std::unordered_map< uint32_t, std::unique_ptr< Cat>> m_cats;
@ -71,14 +74,19 @@ protected:
// Map of all EX categories and their chunks, "CatNum - (ExNum - (ChunkNum - Cat))"
// Map of all EX categories and their chunks, "CatNum - (ExNum - (ChunkNum - Cat))"
using ChunkToCatMap = struct { std::unordered_map< uint32_t, std::unique_ptr< Cat > > chunkToCatMap; };
using ExNumToChunkMap = struct { std::unordered_map< uint32_t, ChunkToCatMap > exNumToChunkMap; };
using ChunkToCatMap = struct
{
std::unordered_map< uint32_t, std::unique_ptr< Cat > > chunkToCatMap;
};
using ExNumToChunkMap = struct
{
std::unordered_map< uint32_t, ChunkToCatMap > exNumToChunkMap;
};
using CatNumToExNumMap = std::unordered_map< uint32_t, ExNumToChunkMap >;
CatNumToExNumMap m_exCats;
std::unordered_map< uint32_t, std::unique_ptr< std::mutex>> m_catCreationMutexes;
};
}
}
#endif // XIV_DAT_GAMEDATA_H

View file

@ -2,9 +2,7 @@
#include "bparse.h"
namespace xiv
{
namespace dat
namespace xiv::dat
{
struct IndexBlockRecord
{
@ -21,13 +19,8 @@ namespace dat
uint32_t padding;
};
}
}
namespace xiv
{
namespace utils
{
namespace bparse
namespace xiv::utils::bparse
{
template<>
inline void reorder< xiv::dat::IndexBlockRecord >( xiv::dat::IndexBlockRecord& i_struct )
@ -46,17 +39,13 @@ namespace bparse
xiv::utils::bparse::reorder( i_struct.padding );
}
}
}
};
using xiv::utils::bparse::extract;
namespace xiv
{
namespace dat
namespace xiv::dat
{
Index::Index(const std::experimental::filesystem::path& path) :
Index::Index( const std::filesystem::path& path ) :
SqPack( path )
{
if( !m_handle )
@ -84,7 +73,7 @@ Index::Index(const std::experimental::filesystem::path& path) :
// The dat number is found in the offset, last four bits
hashTableEntry.datNum = ( indexHashTableEntry.datOffset & 0xF ) / 0x2;
// The offset in the dat file, needs to strip the dat number indicator
hashTableEntry.datOffset = ( indexHashTableEntry.datOffset & 0xFFFFFFF0 ) * 0x08;
hashTableEntry.datOffset = ( indexHashTableEntry.datOffset - ( indexHashTableEntry.datOffset & 0x000F ) ) * 0x08;
hashTableEntry.dirHash = indexHashTableEntry.dirHash;
hashTableEntry.filenameHash = indexHashTableEntry.filenameHash;
}
@ -164,4 +153,3 @@ void Index::isIndexBlockValid( const IndexBlockRecord& i_index_block_record )
}
}
}

View file

@ -5,18 +5,20 @@
#include <unordered_map>
#include <experimental/filesystem>
#include <filesystem>
namespace xiv {
namespace dat {
namespace xiv::dat
{
struct IndexBlockRecord;
class Index : public SqPack
class Index :
public SqPack
{
public:
// Full path to the index file
Index( const std::experimental::filesystem::path& i_path );
Index( const std::filesystem::path& i_path );
virtual ~Index();
// An entry in the hash table, representing a file in a given dat
@ -36,12 +38,15 @@ public:
uint32_t getDatCount() const;
bool doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const;
bool doesDirExist( uint32_t dir_hash ) const;
// Returns the whole HashTable
const HashTable& getHashTable() const;
// Returns the hash table for a specific dir
const DirHashTable& getDirHashTable( uint32_t dir_hash ) const;
// Returns the HashTableEntry for a given file given its hashes
const HashTableEntry& getHashTableEntry( uint32_t dir_hash, uint32_t filename_hash ) const;
@ -53,7 +58,6 @@ protected:
HashTable m_hashTable;
};
}
}
#endif // XIV_DAT_INDEX_H

View file

@ -1,11 +1,19 @@
#include "SqPack.h"
namespace xiv {
namespace dat {
namespace xiv::dat {
enum PlatformId :
uint8_t
{
Win32,
PS3,
PS4
};
struct SqPackHeader
{
char magic[0x8];
uint32_t zero;
PlatformId platformId;
uint8_t padding0[3];
uint32_t size;
uint32_t version;
uint32_t type;
@ -17,10 +25,9 @@ namespace dat {
uint32_t type;
};
}
}
namespace xiv {
namespace utils {
namespace bparse {
namespace xiv::utils:: bparse
{
template<>
inline void reorder< xiv::dat::SqPackHeader >( xiv::dat::SqPackHeader& i_struct )
{
@ -28,7 +35,7 @@ namespace bparse {
{
xiv::utils::bparse::reorder( i_struct.magic[ i ] );
}
xiv::utils::bparse::reorder(i_struct.zero);
xiv::utils::bparse::reorder( i_struct.platformId );
xiv::utils::bparse::reorder( i_struct.size );
xiv::utils::bparse::reorder( i_struct.version );
xiv::utils::bparse::reorder( i_struct.type );
@ -41,18 +48,14 @@ namespace bparse {
xiv::utils::bparse::reorder( i_struct.type );
}
}
}
};
using xiv::utils::bparse::extract;
namespace xiv
{
namespace dat
namespace xiv::dat
{
SqPack::SqPack( const std::experimental::filesystem::path& path ) :
// Open the file
SqPack::SqPack( const std::filesystem::path& path ) :
m_handle( path.string(), std::ios_base::in | std::ios_base::binary )
{
// Extract the header
@ -73,4 +76,3 @@ namespace dat
}
}
}

View file

@ -3,28 +3,24 @@
#include <fstream>
#include <experimental/filesystem>
#include <filesystem>
#include "bparse.h"
namespace xiv
namespace xiv::dat
{
namespace dat
{
struct SqPackBlockHash
{
uint8_t hash[0x14];
uint32_t padding[0xB];
};
}
}
}
namespace xiv {
namespace utils {
namespace bparse {
template <> inline void reorder<xiv::dat::SqPackBlockHash>( xiv::dat::SqPackBlockHash& i_struct )
namespace xiv::utils::bparse
{
template<>
inline void reorder< xiv::dat::SqPackBlockHash >( xiv::dat::SqPackBlockHash& i_struct )
{
for( auto i = 0; i < 0x14; ++i )
{
@ -35,13 +31,9 @@ namespace xiv {
xiv::utils::bparse::reorder( i_struct.padding[ i ] );
}
}
}
}
};
namespace xiv
{
namespace dat
namespace xiv::dat
{
class SqPack
@ -49,7 +41,8 @@ class SqPack
public:
// Full path to the sqpack file
SqPack( const std::experimental::filesystem::path& i_path );
SqPack( const std::filesystem::path& i_path );
virtual ~SqPack();
protected:
@ -61,6 +54,5 @@ protected:
};
}
}
#endif // XIV_DAT_SQPACK_H

View file

@ -6,11 +6,7 @@
#include <sstream>
#include <vector>
namespace xiv
{
namespace utils
{
namespace bparse
namespace xiv::utils::bparse
{
// Internal macro for byteswapping
@ -40,7 +36,10 @@ void read(std::istream& i_stream, StructType& i_struct)
}
// By default a type does not need reordering
template <typename StructType> void reorder(StructType& i_struct) {}
template< typename StructType >
void reorder( StructType& i_struct )
{
}
// "Overload" for passed struct as arg
template< typename StructType >
@ -84,7 +83,8 @@ StructType extract(std::istream& i_stream, const std::string& i_name, bool i_is_
}
template< typename StructType >
void extract(std::istream& i_stream, const std::string& i_name, uint32_t i_size, std::vector<StructType>& o_structs, bool i_is_le = true)
void extract( std::istream& i_stream, const std::string& i_name, uint32_t i_size, std::vector< StructType >& o_structs,
bool i_is_le = true )
{
o_structs.reserve( i_size );
for( uint32_t i = 0; i < i_size; ++i )
@ -96,8 +96,6 @@ void extract(std::istream& i_stream, const std::string& i_name, uint32_t i_size,
// For cstrings
std::string extract_cstring( std::istream& i_stream, const std::string& i_name );
}
}
}
#endif // XIV_UTILS_BPARSE_H

View file

@ -1,8 +1,8 @@
#include "conv.h"
namespace xiv {
namespace utils {
namespace conv {
namespace xiv::utils::conv
{
float half2float( const uint16_t i_value )
{
uint32_t t1;
@ -30,6 +30,4 @@ namespace conv {
}
}
}
}

View file

@ -5,13 +5,11 @@
#include <vector>
#include <ostream>
namespace xiv {
namespace utils {
namespace conv {
namespace xiv::utils::conv
{
float half2float( const uint16_t i_value );
float ubyte2float( const uint8_t i_value );
}
}
}
#endif // XIV_UTILS_CONV_H

View file

@ -65,11 +65,7 @@ namespace internal
}
}
namespace xiv
{
namespace utils
{
namespace crc32
namespace xiv::utils::crc32
{
uint32_t compute( const std::string& i_input, uint32_t init_crc )
@ -130,7 +126,8 @@ void generate_hashes_1(std::string& i_format, const uint32_t i_first_index, std:
}
}
void generate_hashes_2(std::string& i_format, const uint32_t i_first_index, const uint32_t i_second_index, std::vector<uint32_t>& o_hashes)
void generate_hashes_2( std::string& i_format, const uint32_t i_first_index, const uint32_t i_second_index,
std::vector< uint32_t >& o_hashes )
{
char* str = const_cast<char*>(i_format.data());
const uint32_t str_size = i_format.size();
@ -176,5 +173,3 @@ void generate_hashes_2(std::string& i_format, const uint32_t i_first_index, cons
}
}
}

View file

@ -5,9 +5,8 @@
#include <vector>
#include <string>
namespace xiv {
namespace utils {
namespace crc32 {
namespace xiv::utils::crc32
{
// Normal crc32 computation from a given intial crc value, use zlib.crc32 instead, the final XOR 0xFFFFFFFF is not done
uint32_t compute( const std::string& i_input, uint32_t init_crc = 0xFFFFFFFF );
@ -17,10 +16,10 @@ namespace crc32 {
uint32_t rev_compute( const std::string& i_input, uint32_t init_crc = 0 );
void generate_hashes_1( std::string& i_format, const uint32_t i_first_index, std::vector< uint32_t >& o_hashes );
void generate_hashes_2( std::string& i_format, const uint32_t i_first_index, const uint32_t i_second_index, std::vector< uint32_t >& o_hashes );
}
}
void generate_hashes_2( std::string& i_format, const uint32_t i_first_index, const uint32_t i_second_index,
std::vector< uint32_t >& o_hashes );
}
#endif // XIV_UTILS_CRC32_H

View file

@ -4,13 +4,7 @@
#include <sstream>
#include <streambuf>
namespace xiv
{
namespace utils
{
namespace stream
namespace xiv::utils::stream
{
}
}
}

View file

@ -5,14 +5,11 @@
#include <iostream>
#include <vector>
namespace xiv
{
namespace utils
{
namespace stream
namespace xiv::utils::stream
{
template< typename CharT, typename TraitsT = std::char_traits< CharT > >
class vectorwrapbuf : public std::basic_streambuf<CharT, TraitsT>
class vectorwrapbuf :
public std::basic_streambuf< CharT, TraitsT >
{
public:
vectorwrapbuf( std::vector< CharT >& vec )
@ -21,7 +18,4 @@ public:
}
};
}
}
}
#endif // XIV_UTILS_STREAM_H

View file

@ -4,11 +4,7 @@
#include <zlib/zlib.h>
#include <vector>
namespace xiv
{
namespace utils
{
namespace zlib
namespace xiv::utils::zlib
{
void compress( const std::vector< char >& in, std::vector< char >& out )
@ -61,5 +57,3 @@ void no_header_decompress(uint8_t* in, uint32_t in_size, uint8_t* out, uint32_t
}
}
}
}

View file

@ -4,18 +4,13 @@
#include <cstdint>
#include <vector>
namespace xiv
{
namespace utils
{
namespace zlib
namespace xiv::utils::zlib
{
void compress( const std::vector< char >& in, std::vector< char >& out );
void no_header_decompress( uint8_t* in, uint32_t in_size, uint8_t* out, uint32_t out_size );
}
}
}
#endif // XIV_UTILS_ZLIB_H

1
deps/ffxiv-actions vendored Submodule

@ -0,0 +1 @@
Subproject commit dde9b5bbfc7c0197de0b0b49b982a0ee9fe761ab

View file

@ -4,6 +4,10 @@
#include "PreparedStatement.h"
#include <mysql.h>
#ifdef _MSC_VER
// fixes compile error when compiling with vs2019
#include <stdexcept>
#endif
#include <vector>
Mysql::Connection::Connection( std::shared_ptr< MySqlBase > pBase,

View file

@ -3,6 +3,8 @@
#include <memory>
#include <map>
#include <string>
#include "MysqlCommon.h"
typedef struct st_mysql MYSQL;

View file

@ -1,11 +0,0 @@
cmake_minimum_required(VERSION 3.0.2)
project(Sapphire)
if( WIN32 )
file( GLOB STACKWALKER_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.h*" )
file( GLOB STACKWALKER_SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.c*" )
add_library( stackwalker ${STACKWALKER_INCLUDE_FILES} ${STACKWALKER_SOURCE_FILES} )
endif()

File diff suppressed because it is too large Load diff

View file

@ -1,255 +0,0 @@
#ifndef __STACKWALKER_H__
#define __STACKWALKER_H__
#if defined(_MSC_VER)
/**********************************************************************
*
* StackWalker.h
*
*
*
* LICENSE (http://www.opensource.org/licenses/bsd-license.php)
*
* Copyright (c) 2005-2009, Jochen Kalmbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of Jochen Kalmbach nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* **********************************************************************/
// #pragma once is supported starting with _MSC_VER 1000,
// so we need not to check the version (because we only support _MSC_VER >= 1100)!
#pragma once
#include <windows.h>
#if _MSC_VER >= 1900
#pragma warning(disable : 4091)
#endif
// special defines for VC5/6 (if no actual PSDK is installed):
#if _MSC_VER < 1300
typedef unsigned __int64 DWORD64, *PDWORD64;
#if defined(_WIN64)
typedef unsigned __int64 SIZE_T, *PSIZE_T;
#else
typedef unsigned long SIZE_T, *PSIZE_T;
#endif
#endif // _MSC_VER < 1300
class StackWalkerInternal; // forward
class StackWalker
{
public:
typedef enum StackWalkOptions
{
// No addition info will be retrieved
// (only the address is available)
RetrieveNone = 0,
// Try to get the symbol-name
RetrieveSymbol = 1,
// Try to get the line for this symbol
RetrieveLine = 2,
// Try to retrieve the module-infos
RetrieveModuleInfo = 4,
// Also retrieve the version for the DLL/EXE
RetrieveFileVersion = 8,
// Contains all the above
RetrieveVerbose = 0xF,
// Generate a "good" symbol-search-path
SymBuildPath = 0x10,
// Also use the public Microsoft-Symbol-Server
SymUseSymSrv = 0x20,
// Contains all the above "Sym"-options
SymAll = 0x30,
// Contains all options (default)
OptionsAll = 0x3F
} StackWalkOptions;
StackWalker(int options = OptionsAll, // 'int' is by design, to combine the enum-flags
LPCSTR szSymPath = NULL,
DWORD dwProcessId = GetCurrentProcessId(),
HANDLE hProcess = GetCurrentProcess());
StackWalker(DWORD dwProcessId, HANDLE hProcess);
virtual ~StackWalker();
typedef BOOL(__stdcall* PReadProcessMemoryRoutine)(
HANDLE hProcess,
DWORD64 qwBaseAddress,
PVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesRead,
LPVOID pUserData // optional data, which was passed in "ShowCallstack"
);
BOOL LoadModules();
BOOL ShowCallstack(
HANDLE hThread = GetCurrentThread(),
const CONTEXT* context = NULL,
PReadProcessMemoryRoutine readMemoryFunction = NULL,
LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback
);
BOOL ShowObject(LPVOID pObject);
#if _MSC_VER >= 1300
// due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
// in older compilers in order to use it... starting with VC7 we can declare it as "protected"
protected:
#endif
enum
{
STACKWALK_MAX_NAMELEN = 1024
}; // max name length for found symbols
protected:
// Entry for each Callstack-Entry
typedef struct CallstackEntry
{
DWORD64 offset; // if 0, we have no valid entry
CHAR name[STACKWALK_MAX_NAMELEN];
CHAR undName[STACKWALK_MAX_NAMELEN];
CHAR undFullName[STACKWALK_MAX_NAMELEN];
DWORD64 offsetFromSmybol;
DWORD offsetFromLine;
DWORD lineNumber;
CHAR lineFileName[STACKWALK_MAX_NAMELEN];
DWORD symType;
LPCSTR symTypeString;
CHAR moduleName[STACKWALK_MAX_NAMELEN];
DWORD64 baseOfImage;
CHAR loadedImageName[STACKWALK_MAX_NAMELEN];
} CallstackEntry;
typedef enum CallstackEntryType
{
firstEntry,
nextEntry,
lastEntry
} CallstackEntryType;
virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);
virtual void OnLoadModule(LPCSTR img,
LPCSTR mod,
DWORD64 baseAddr,
DWORD size,
DWORD result,
LPCSTR symType,
LPCSTR pdbName,
ULONGLONG fileVersion);
virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry& entry);
virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);
virtual void OnOutput(LPCSTR szText);
StackWalkerInternal* m_sw;
HANDLE m_hProcess;
DWORD m_dwProcessId;
BOOL m_modulesLoaded;
LPSTR m_szSymPath;
int m_options;
int m_MaxRecursionCount;
static BOOL __stdcall myReadProcMem(HANDLE hProcess,
DWORD64 qwBaseAddress,
PVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesRead);
friend StackWalkerInternal;
}; // class StackWalker
// The "ugly" assembler-implementation is needed for systems before XP
// If you have a new PSDK and you only compile for XP and later, then you can use
// the "RtlCaptureContext"
// Currently there is no define which determines the PSDK-Version...
// So we just use the compiler-version (and assumes that the PSDK is
// the one which was installed by the VS-IDE)
// INFO: If you want, you can use the RtlCaptureContext if you only target XP and later...
// But I currently use it in x64/IA64 environments...
//#if defined(_M_IX86) && (_WIN32_WINNT <= 0x0500) && (_MSC_VER < 1400)
#if defined(_M_IX86)
#ifdef CURRENT_THREAD_VIA_EXCEPTION
// TODO: The following is not a "good" implementation,
// because the callstack is only valid in the "__except" block...
#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
do \
{ \
memset(&c, 0, sizeof(CONTEXT)); \
EXCEPTION_POINTERS* pExp = NULL; \
__try \
{ \
throw 0; \
} \
__except (((pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER \
: EXCEPTION_EXECUTE_HANDLER)) \
{ \
} \
if (pExp != NULL) \
memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \
c.ContextFlags = contextFlags; \
} while (0);
#else
// clang-format off
// The following should be enough for walking the callstack...
#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
do \
{ \
memset(&c, 0, sizeof(CONTEXT)); \
c.ContextFlags = contextFlags; \
__asm call x \
__asm x: pop eax \
__asm mov c.Eip, eax \
__asm mov c.Ebp, ebp \
__asm mov c.Esp, esp \
} while (0)
// clang-format on
#endif
#else
// The following is defined for x86 (XP and higher), x64 and IA64:
#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
do \
{ \
memset(&c, 0, sizeof(CONTEXT)); \
c.ContextFlags = contextFlags; \
RtlCaptureContext(&c); \
} while (0);
#endif
#endif //defined(_MSC_VER)
#endif // __STACKWALKER_H__

View file

@ -31,8 +31,8 @@
#include <mutex>
#include <functional>
#include <experimental/filesystem>
namespace ci { namespace fs = std::experimental::filesystem; }
#include <filesystem>
namespace ci { namespace fs = std::filesystem; }
//! Exception for when Watchdog can't locate a file or parse the wildcard
class WatchedFileSystemExc : public std::exception {
@ -319,7 +319,7 @@ protected:
std::string mFilter;
std::function<void(const ci::fs::path&)> mCallback;
std::function<void(const std::vector<ci::fs::path>&)> mListCallback;
std::map< std::string, std::experimental::filesystem::file_time_type > mModificationTimes;
std::map< std::string, std::filesystem::file_time_type > mModificationTimes;
};
std::mutex mMutex;

View file

@ -0,0 +1,15 @@
-- Migration generated at 2019/07/06 03:52:54
-- 20190706035254_ConvertFixedSizeDataToBlobs.sql
ALTER TABLE `charainfo`
CHANGE COLUMN `TitleList` `TitleList` BLOB NULL DEFAULT NULL AFTER `ActiveTitle`,
CHANGE COLUMN `Achievement` `Achievement` BLOB NULL DEFAULT NULL AFTER `TitleList`,
CHANGE COLUMN `Aetheryte` `Aetheryte` BLOB NULL DEFAULT NULL AFTER `Achievement`,
CHANGE COLUMN `HowTo` `HowTo` BLOB NULL DEFAULT NULL AFTER `Aetheryte`,
CHANGE COLUMN `Minions` `Minions` BLOB NULL DEFAULT NULL AFTER `HowTo`,
CHANGE COLUMN `Mounts` `Mounts` BLOB NULL DEFAULT NULL AFTER `Minions`,
CHANGE COLUMN `Orchestrion` `Orchestrion` BLOB NULL DEFAULT NULL AFTER `Mounts`,
CHANGE COLUMN `QuestCompleteFlags` `QuestCompleteFlags` BLOB NULL DEFAULT NULL AFTER `ConfigFlags`,
CHANGE COLUMN `QuestTracking` `QuestTracking` BLOB NULL DEFAULT NULL AFTER `OpeningSequence`,
CHANGE COLUMN `Discovery` `Discovery` BLOB NULL DEFAULT NULL AFTER `GrandCompanyRank`,
CHANGE COLUMN `Unlocks` `Unlocks` BLOB NULL DEFAULT NULL AFTER `Pose`;

File diff suppressed because it is too large Load diff

View file

@ -400,13 +400,6 @@ CREATE TABLE `dbupdate` (
PRIMARY KEY(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `discoveryinfo` (
`id` int(10) NOT NULL,
`map_id` int(3) NOT NULL,
`discover_id` int(3) NOT NULL,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `house` (
`HouseId` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`LandSetId` int(10) UNSIGNED DEFAULT NULL,
@ -602,3 +595,8 @@ CREATE TABLE `charamonsternote` (
`UPDATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(`CharacterId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `__Migration` (
`MigrationName` VARCHAR(250) NOT NULL,
PRIMARY KEY (`MigrationName`)
) ENGINE=InnoDB;

View file

@ -1,89 +0,0 @@
#ifndef _FORWARDS_H
#define _FORWARDS_H
#include <memory>
namespace Sapphire
{
class Cell;
class Zone;
class Item;
class ItemContainer;
class Inventory;
class Session;
class ZonePosition;
using ZonePtr = std::shared_ptr< Zone >;
using ItemPtr = std::shared_ptr< Item >;
using ItemContainerPtr = std::shared_ptr< ItemContainer >;
using InventoryPtr = std::shared_ptr< Inventory >;
using SessionPtr = std::shared_ptr< Session >;
using ZonePositionPtr = std::shared_ptr< ZonePosition >;
namespace StatusEffect
{
class StatusEffect;
class StatusEffectContainer;
using StatusEffectPtr = std::shared_ptr< StatusEffect >;
using StatusEffectContainerPtr = std::shared_ptr< StatusEffectContainer >;
}
namespace Entity
{
class Chara;
class Player;
class BattleNpc;
using ActorPtr = std::shared_ptr< Chara >;
using PlayerPtr = std::shared_ptr< Player >;
using BattleNpcPtr = std::shared_ptr< BattleNpc >;
}
namespace Event
{
class EventHandler;
using EventPtr = std::shared_ptr< EventHandler >;
}
namespace Action
{
class Action;
class ActionTeleport;
class EventAction;
using ActionPtr = std::shared_ptr< Action >;
using ActionTeleportPtr = std::shared_ptr< ActionTeleport >;
using EventActionPtr = std::shared_ptr< EventAction >;
}
namespace Network
{
class Hive;
class Acceptor;
class Connection;
class WorldConnection;
class SessionConnection;
class ZoneConnection;
using HivePtr = std::shared_ptr< Hive >;
using AcceptorPtr = std::shared_ptr< Acceptor >;
using ConnectionPtr = std::shared_ptr< Connection >;
using WorldConnectionPtr = std::shared_ptr< WorldConnection >;
using ZoneConnectionPtr = std::shared_ptr< ZoneConnection >;
using SessionConnectionPtr = std::shared_ptr< SessionConnection >;
namespace Packets
{
class GamePacket;
using GamePacketPtr = std::shared_ptr< GamePacket >;
}
}
namespace Scripting
{
using EventReturnCallback = std::function< void( Entity::Player&, uint32_t, uint16_t, uint16_t, uint16_t,
uint16_t ) >;
}
using ActionCallback = std::function< void( Entity::Player&, uint32_t, uint64_t ) >;
}
#endif

View file

@ -1,14 +0,0 @@
#include "LoginSession.h"
namespace Sapphire {
LoginSession::LoginSession( void )
{
//setSocket(NULL);
}
LoginSession::~LoginSession( void )
{
}
}

View file

@ -1,57 +0,0 @@
#pragma once
#ifndef _CLoginSession_H_
#define _CLoginSession_H_
#include <stdint.h>
#include <string>
#include <string.h>
namespace Sapphire
{
class LoginSession
{
private:
uint32_t m_ip;
uint32_t m_accountId;
uint8_t m_sessionId[56];
public:
std::string newCharName;
LoginSession( void );
~LoginSession( void );
uint32_t getIp()
{
return m_ip;
}
void setSessionId( uint8_t* sessionId )
{
memcpy( m_sessionId, sessionId, 56 );
}
void setIp( uint32_t ip )
{
m_ip = ip;
}
uint32_t getAccountId()
{
return m_accountId;
}
void setAccountId( uint32_t id )
{
m_accountId = id;
}
};
}
#endif

View file

@ -1,29 +1,24 @@
#include "PlayerMinimal.h"
#include <Util/Util.h>
#include <Common.h>
#include <Exd/ExdDataGenerated.h>
#include <Database/DatabaseDef.h>
#include <nlohmann/json.hpp>
extern Sapphire::Data::ExdDataGenerated g_exdDataGen;
namespace Sapphire {
namespace Sapphire::Api {
using namespace Common;
// player constructor
PlayerMinimal::PlayerMinimal( void ) :
PlayerMinimal::PlayerMinimal() :
m_id( 0 )
{
}
// deconstructor
PlayerMinimal::~PlayerMinimal( void )
{
}
// load player from the db
@ -84,64 +79,101 @@ void PlayerMinimal::load( uint32_t charId )
}
}
std::string PlayerMinimal::getLookString()
{
auto it = m_lookMap.begin();
std::string lookString;
for( ; it != m_lookMap.end(); ++it )
{
std::string s = std::to_string( it->second );
lookString += "\"" + s + "\"";
if( it != m_lookMap.end() )
{
lookString += ",";
}
}
return lookString.substr( 0, lookString.size() - 1 );
}
std::string PlayerMinimal::getModelString()
{
std::string modelString = "\""
+ std::to_string( m_modelEquip[ 0 ] ) + "\",\""
+ std::to_string( m_modelEquip[ 1 ] ) + "\",\""
+ std::to_string( m_modelEquip[ 2 ] ) + "\",\""
+ std::to_string( m_modelEquip[ 3 ] ) + "\",\""
+ std::to_string( m_modelEquip[ 4 ] ) + "\",\""
+ std::to_string( m_modelEquip[ 5 ] ) + "\",\""
+ std::to_string( m_modelEquip[ 6 ] ) + "\",\""
+ std::to_string( m_modelEquip[ 7 ] ) + "\",\""
+ std::to_string( m_modelEquip[ 8 ] ) + "\",\""
+ std::to_string( m_modelEquip[ 9 ] ) + "\"";
return modelString;
}
std::string PlayerMinimal::getInfoJson()
{
std::string charDetails = "{\"content\":[\"" + std::string( getName() ) + "\"," +
"[\"0\",\"0\",\"0\",\"0\",\"" + std::to_string( m_classLevel ) +
"\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\"],"
"\"0\",\"0\",\"0\",\"" +
std::to_string( getBirthMonth() ) +
"\",\"" + std::to_string( getBirthDay() ) +
"\",\"" + std::to_string( getGuardianDeity() ) +
"\",\"" + std::to_string( m_class ) +
"\",\"0\",\"" + std::to_string( getZoneId() ) +
"\",\"0\"," +
"[" + getLookString() + "]," +
"\"" + std::to_string( m_modelMainWeapon ) + "\",\"" + std::to_string( m_modelSubWeapon ) + "\"," +
"[" + getModelString() + "]," +
"\"1\",\"0\",\"0\",\"0\",\"" + std::to_string( m_equipDisplayFlags ) +
"\",\"0\",\"\",\"0\",\"0\"]," +
"\"classname\":\"ClientSelectData\",\"classid\":116}";
return charDetails;
auto payload = nlohmann::json();
auto& c = payload["content"];
// DisplayName
c.push_back( getName() );
// class levels
auto levelsArray = nlohmann::json();
for( int i = 0; i < Common::CLASSJOB_SLOTS; ++i )
{
// these must be strings
levelsArray.push_back( std::to_string( m_classMap[ i ] ) );
}
// ClassLv
c.push_back( levelsArray );
// Race
c.push_back( "0" );
// Tribe
c.push_back( "0" );
// Sex
c.push_back( "0" );
// BirthMonth
c.push_back( std::to_string( getBirthMonth() ) );
// Birthday
c.push_back( std::to_string( getBirthDay() ) );
// GuardianDeity
c.push_back( std::to_string( getGuardianDeity() ) );
// Class
c.push_back( std::to_string( m_class ) );
// ZoneId
c.push_back( "0" );
// TerritoryType
c.push_back( std::to_string( getZoneId() ) );
// ContentFinderCondition
c.push_back( "0" );
// look map
auto lookArray = nlohmann::json();
for( auto& it : m_lookMap )
{
lookArray.push_back( std::to_string( it.second ) );
}
// Customize
c.push_back( lookArray );
// ModelMainWeapon
c.push_back( std::to_string( m_modelMainWeapon ) );
// ModelSubWeapon
c.push_back( std::to_string( m_modelSubWeapon ) );
// model
auto modelArray = nlohmann::json();
for( auto i : m_modelEquip )
{
modelArray.push_back( std::to_string( i ) );
}
// ModelEquip
c.push_back( modelArray );
// MainWeapon
c.push_back( "1" );
// SubWeapon
c.push_back( "0" );
// JobStone
c.push_back( "0" );
// RemakeFlag
c.push_back( "0" );
// ConfigFlags
c.push_back( std::to_string( m_equipDisplayFlags ) );
// Voice
c.push_back( "0" );
// WorldName
c.push_back( "" );
// LoginStatus
c.push_back( "0" );
// IsOutTerritory
c.push_back( "0" );
payload["classname"] = "ClientSelectData";
payload["classid"] = 116;
return payload.dump();
}
uint8_t PlayerMinimal::getClassLevel()
@ -150,30 +182,6 @@ uint8_t PlayerMinimal::getClassLevel()
return static_cast< uint8_t >( m_classMap[ classJobIndex ] );
}
std::string PlayerMinimal::getClassString()
{
std::map< uint8_t, uint16_t >::iterator it;
it = m_classMap.begin();
std::string classString;
for( ; it != m_classMap.end(); ++it )
{
std::string s = std::to_string( it->second );
classString += "\"" + s + "\"";
if( it != m_classMap.end() )
{
classString += ",";
}
}
return classString.substr( 0, classString.size() - 1 );
}
void PlayerMinimal::saveAsNew()
{

View file

@ -2,18 +2,19 @@
#define _PLAYERMINIMAL_H
#include <map>
#include <stdint.h>
#include <string.h>
#include <cstdint>
#include <string>
#include <cstring>
namespace Sapphire
namespace Sapphire::Api
{
class PlayerMinimal
{
public:
PlayerMinimal( void );
PlayerMinimal();
~PlayerMinimal( void );
~PlayerMinimal() = default;
// write player to the database
void write();
@ -23,14 +24,8 @@ namespace Sapphire
void saveAsNew();
std::string getLookString();
std::string getInfoJson();
std::string getModelString();
std::string getClassString();
uint8_t getClassLevel();
// return the id of the actor

View file

@ -1,4 +1,4 @@
#include "SapphireAPI.h"
#include "SapphireApi.h"
#include <Crypt/base64.h>
#include "Session.h"
#include "PlayerMinimal.h"
@ -10,7 +10,9 @@
#include <Database/DatabaseDef.h>
bool Sapphire::Network::SapphireAPI::login( const std::string& username, const std::string& pass, std::string& sId )
using namespace Sapphire::Api;
bool SapphireApi::login( const std::string& username, const std::string& pass, std::string& sId )
{
std::string query =
"SELECT account_id FROM accounts WHERE account_name = '" + username + "' AND account_pass = '" + pass + "';";
@ -53,7 +55,7 @@ bool Sapphire::Network::SapphireAPI::login( const std::string& username, const s
}
bool Sapphire::Network::SapphireAPI::insertSession( const uint32_t accountId, std::string& sId )
bool SapphireApi::insertSession( const uint32_t accountId, std::string& sId )
{
// create session for the new sessionid and store to sessionlist
auto pSession = std::make_shared< Session >();
@ -66,7 +68,7 @@ bool Sapphire::Network::SapphireAPI::insertSession( const uint32_t accountId, st
}
bool Sapphire::Network::SapphireAPI::createAccount( const std::string& username, const std::string& pass, std::string& sId )
bool SapphireApi::createAccount( const std::string& username, const std::string& pass, std::string& sId )
{
// get account from login name
auto pQR = g_charaDb.query( "SELECT account_id FROM accounts WHERE account_name = '" + username + "';" );
@ -96,11 +98,11 @@ bool Sapphire::Network::SapphireAPI::createAccount( const std::string& username,
}
int Sapphire::Network::SapphireAPI::createCharacter( const uint32_t accountId, const std::string& name,
int SapphireApi::createCharacter( const uint32_t accountId, const std::string& name,
const std::string& infoJson,
const uint32_t gmRank )
{
Sapphire::PlayerMinimal newPlayer;
Api::PlayerMinimal newPlayer;
newPlayer.setAccountId( accountId );
newPlayer.setId( getNextCharId() );
@ -169,7 +171,7 @@ int Sapphire::Network::SapphireAPI::createCharacter( const uint32_t accountId, c
return newPlayer.getAccountId();
}
void Sapphire::Network::SapphireAPI::deleteCharacter( std::string name, const uint32_t accountId )
void SapphireApi::deleteCharacter( std::string name, const uint32_t accountId )
{
PlayerMinimal deletePlayer;
auto charList = getCharList( accountId );
@ -190,26 +192,28 @@ void Sapphire::Network::SapphireAPI::deleteCharacter( std::string name, const ui
g_charaDb.execute( "DELETE FROM characlass WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charaglobalitem WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charainfoblacklist WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charainfofriendlist WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charainfolinkshell WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charainfosearch WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charaitemcrystal WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charaitemcurrency WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charaiteminventory WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charaitemgearset WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charamonsternote WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charaquest WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charastatus WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
}
std::vector< Sapphire::PlayerMinimal > Sapphire::Network::SapphireAPI::getCharList( uint32_t accountId )
std::vector< PlayerMinimal > SapphireApi::getCharList( uint32_t accountId )
{
std::vector< Sapphire::PlayerMinimal > charList;
std::vector< Api::PlayerMinimal > charList;
auto pQR = g_charaDb.query(
"SELECT CharacterId, ContentId FROM charainfo WHERE AccountId = " + std::to_string( accountId ) + ";" );
while( pQR->next() )
{
Sapphire::PlayerMinimal player;
Api::PlayerMinimal player;
uint32_t charId = pQR->getUInt( 1 );
@ -220,7 +224,7 @@ std::vector< Sapphire::PlayerMinimal > Sapphire::Network::SapphireAPI::getCharLi
return charList;
}
bool Sapphire::Network::SapphireAPI::checkNameTaken( std::string name )
bool SapphireApi::checkNameTaken( std::string name )
{
g_charaDb.escapeString( name );
@ -234,7 +238,7 @@ bool Sapphire::Network::SapphireAPI::checkNameTaken( std::string name )
return true;
}
uint32_t Sapphire::Network::SapphireAPI::getNextCharId()
uint32_t SapphireApi::getNextCharId()
{
uint32_t charId = 0;
@ -250,7 +254,7 @@ uint32_t Sapphire::Network::SapphireAPI::getNextCharId()
return charId;
}
uint64_t Sapphire::Network::SapphireAPI::getNextContentId()
uint64_t SapphireApi::getNextContentId()
{
uint64_t contentId = 0;
@ -266,7 +270,7 @@ uint64_t Sapphire::Network::SapphireAPI::getNextContentId()
return contentId;
}
int Sapphire::Network::SapphireAPI::checkSession( const std::string& sId )
int SapphireApi::checkSession( const std::string& sId )
{
auto it = m_sessionMap.find( sId );
@ -277,7 +281,7 @@ int Sapphire::Network::SapphireAPI::checkSession( const std::string& sId )
}
bool Sapphire::Network::SapphireAPI::removeSession( const std::string& sId )
bool SapphireApi::removeSession( const std::string& sId )
{
auto it = m_sessionMap.find( sId );

View file

@ -7,19 +7,15 @@
#include <memory>
#include "PlayerMinimal.h"
namespace Sapphire
namespace Sapphire::Api
{
class Session;
}
namespace Sapphire::Network
{
class SapphireAPI
class SapphireApi
{
public:
SapphireAPI() = default;
~SapphireAPI() = default;
SapphireApi() = default;
~SapphireApi() = default;
using SessionMap = std::map< std::string, std::shared_ptr< Session > >;
@ -34,7 +30,7 @@ namespace Sapphire::Network
bool insertSession( uint32_t accountId, std::string& sId );
std::vector< Sapphire::PlayerMinimal > getCharList( uint32_t accountId );
std::vector< Api::PlayerMinimal > getCharList( uint32_t accountId );
bool checkNameTaken( std::string name );

View file

@ -1,6 +1,7 @@
#include "Session.h"
namespace Sapphire {
using namespace Sapphire::Api;
Session::Session()
{
@ -35,4 +36,3 @@ void Session::setAccountId( uint32_t id )
{
m_accountId = id;
}
}

View file

@ -5,7 +5,7 @@
#include <string>
#include <string.h>
namespace Sapphire
namespace Sapphire::Api
{
class Session

View file

@ -22,25 +22,23 @@
//Added for the default_resource example
#include <fstream>
#include <string>
#include <experimental/filesystem>
#include <filesystem>
#include <vector>
#include <algorithm>
#include <Framework.h>
#include <Logging/Logger.h>
#include "Forwards.h"
#include "SapphireAPI.h"
#include "SapphireApi.h"
#include <Util/CrashHandler.h>
Sapphire::Common::Util::CrashHandler crashHandler;
[[maybe_unused]] Sapphire::Common::Util::CrashHandler crashHandler;
Sapphire::Db::DbWorkerPool< Sapphire::Db::ZoneDbConnection > g_charaDb;
Sapphire::Data::ExdDataGenerated g_exdDataGen;
Sapphire::Network::SapphireAPI g_sapphireAPI;
Sapphire::Api::SapphireApi g_sapphireAPI;
namespace fs = std::experimental::filesystem;
namespace fs = std::filesystem;
using namespace std;
using namespace Sapphire;
@ -59,7 +57,7 @@ Sapphire::Common::Config::ApiConfig m_config;
void reloadConfig()
{
auto pConfig = std::make_shared< Sapphire::ConfigMgr >();
auto pConfig = std::make_shared< Sapphire::Common::ConfigMgr >();
Logger::info( "Loading config " + configPath );
@ -106,7 +104,7 @@ bool loadSettings( int32_t argc, char* argv[] )
try
{
arg = Sapphire::Util::toLowerCopy( std::string( args[ i ] ) );
arg = Common::Util::toLowerCopy( std::string( args[ i ] ) );
val = std::string( args[ i + 1 ] );
// trim '-' from start of arg
@ -336,7 +334,7 @@ void createCharacter( shared_ptr< HttpServer::Response > response, shared_ptr< H
std::string name = json["name"];
std::string infoJson = json["infoJson"];
std::string finalJson = Sapphire::Util::base64Decode( infoJson );
std::string finalJson = Common::Util::base64Decode( infoJson );
// reloadConfig();
@ -672,8 +670,9 @@ void defaultGet( shared_ptr< HttpServer::Response > response, shared_ptr< HttpSe
print_request_info( request );
try
{
auto web_root_path = fs::canonical( "web" );
auto path = fs::canonical( web_root_path / request->path );
auto web_root_path = fs::current_path() / "web";
auto path = web_root_path / request->path;
//Check if path is within web_root_path
if( distance( web_root_path.begin(), web_root_path.end() ) > distance( path.begin(), path.end() ) ||
!std::equal( web_root_path.begin(), web_root_path.end(), path.begin() ) )
@ -700,7 +699,7 @@ void defaultGet( shared_ptr< HttpServer::Response > response, shared_ptr< HttpSe
catch( const exception& )
{
string content = "Path not found: " + request->path;
*response << buildHttpResponse( 400, content );
*response << buildHttpResponse( 404, content );
}
}
@ -719,19 +718,19 @@ int main( int argc, char* argv[] )
Logger::setLogLevel( m_config.global.general.logLevel );
server.resource[ "^/ZoneName/([0-9]+)$" ][ "GET" ] = &getZoneName;
server.resource[ "^/sapphire-api/lobby/createAccount" ][ "POST" ] = &createAccount;
server.resource[ "^/sapphire-api/lobby/login" ][ "POST" ] = &login;
server.resource[ "^/sapphire-api/lobby/deleteCharacter" ][ "POST" ] = &deleteCharacter;
server.resource[ "^/sapphire-api/lobby/createCharacter" ][ "POST" ] = &createCharacter;
server.resource[ "^/sapphire-api/lobby/insertSession" ][ "POST" ] = &insertSession;
server.resource[ "^/sapphire-api/lobby/checkNameTaken" ][ "POST" ] = &checkNameTaken;
server.resource[ "^/sapphire-api/lobby/checkSession" ][ "POST" ] = &checkSession;
server.resource[ "^/sapphire-api/lobby/getNextCharId" ][ "POST" ] = &getNextCharId;
server.resource[ "^/sapphire-api/lobby/getNextContentId" ][ "POST" ] = &getNextContentId;
server.resource[ "^/sapphire-api/lobby/getCharacterList" ][ "POST" ] = &getCharacterList;
server.resource[ "^(/frontier-api/ffxivsupport/view/get_init)(.*)" ][ "GET" ] = &get_init;
server.resource[ "^(/frontier-api/ffxivsupport/information/get_headline_all)(.*)" ][ "GET" ] = &get_headline_all;
server.resource[ "^ZoneName/([0-9]+)$" ][ "GET" ] = &getZoneName;
server.resource[ "^sapphire-api/lobby/createAccount" ][ "POST" ] = &createAccount;
server.resource[ "^sapphire-api/lobby/login" ][ "POST" ] = &login;
server.resource[ "^sapphire-api/lobby/deleteCharacter" ][ "POST" ] = &deleteCharacter;
server.resource[ "^sapphire-api/lobby/createCharacter" ][ "POST" ] = &createCharacter;
server.resource[ "^sapphire-api/lobby/insertSession" ][ "POST" ] = &insertSession;
server.resource[ "^sapphire-api/lobby/checkNameTaken" ][ "POST" ] = &checkNameTaken;
server.resource[ "^sapphire-api/lobby/checkSession" ][ "POST" ] = &checkSession;
server.resource[ "^sapphire-api/lobby/getNextCharId" ][ "POST" ] = &getNextCharId;
server.resource[ "^sapphire-api/lobby/getNextContentId" ][ "POST" ] = &getNextContentId;
server.resource[ "^sapphire-api/lobby/getCharacterList" ][ "POST" ] = &getCharacterList;
server.resource[ "^(frontier-api/ffxivsupport/view/get_init)(.*)" ][ "GET" ] = &get_init;
server.resource[ "^(frontier-api/ffxivsupport/information/get_headline_all)(.*)" ][ "GET" ] = &get_headline_all;
server.default_resource[ "GET" ] = &defaultGet;

View file

@ -18,7 +18,7 @@
class case_insensitive_equals {
public:
bool operator()(const std::string &key1, const std::string &key2) const {
return Sapphire::Util::toLowerCopy( key1 ) == Sapphire::Util::toLowerCopy( key2 );
return Sapphire::Common::Util::toLowerCopy( key1 ) == Sapphire::Common::Util::toLowerCopy( key2 );
}
};
class case_insensitive_hash {
@ -27,7 +27,7 @@ public:
{
std::size_t seed=0;
for( auto &c : key )
Sapphire::Util::hashCombine< char >( seed, std::tolower( c ) );
Sapphire::Common::Util::hashCombine< char >( seed, std::tolower( c ) );
return seed;
}
};
@ -304,7 +304,7 @@ namespace SimpleWeb {
size_t path_end;
if((path_end=line.find(' ', method_end+1))!=std::string::npos) {
request->method=line.substr(0, method_end);
request->path=line.substr(method_end+1, path_end-method_end-1);
request->path=line.substr(method_end+2, path_end-method_end-2);
size_t protocol_end;
if((protocol_end=line.find('/', path_end+1))!=std::string::npos) {
@ -388,7 +388,7 @@ namespace SimpleWeb {
auto range=request->header.equal_range("Connection");
for(auto it=range.first;it!=range.second;it++) {
if( Sapphire::Util::toLowerCopy( it->second ) == "close" )
if( Sapphire::Common::Util::toLowerCopy( it->second ) == "close" )
return;
}
if(http_version>1.05)

View file

@ -26,10 +26,6 @@ if( UNIX )
PUBLIC
pthread
stdc++fs )
else()
target_link_libraries( common
PUBLIC
stackwalker )
endif()
target_include_directories( common

View file

@ -21,6 +21,14 @@ namespace Sapphire::Common
const int32_t INVALID_GAME_OBJECT_ID = 0xE0000000;
const uint64_t INVALID_GAME_OBJECT_ID64 = 0xE0000000;
const uint16_t MAX_PLAYER_LEVEL = 80;
const uint8_t CURRENT_EXPANSION_ID = 3;
const uint8_t CLASSJOB_TOTAL = 38;
const uint8_t CLASSJOB_SLOTS = 28;
const uint8_t TOWN_COUNT = 6;
/*!
* @brief The maximum length (in ms) of a combo before it is canceled/voided.
*
@ -41,13 +49,13 @@ namespace Sapphire::Common
uint8_t plot;
};
enum InventoryOperation : uint8_t
enum InventoryOperation : uint16_t
{
Discard = 0x07,
Move = 0x08,
Swap = 0x09,
Merge = 0x0C,
Split = 0x0A
Discard = 0x013C,
Move = 0x013D,
Swap = 0x013E,
Split = 0x013F,
Merge = 0x0141,
};
enum ClientLanguage : uint8_t
@ -151,44 +159,46 @@ namespace Sapphire::Common
ModelRing2 = 9
};
enum EquipSlotCategory : uint8_t
enum class EquipSlotCategory : uint8_t
{
Unequippable = 0,
// main slots
CharaMainHand = 1,
CharaOffHand = 2,
CharaHead = 3,
CharaBody = 4,
CharaHands = 5,
CharaWaist = 6,
CharaLegs = 7,
CharaFeet = 8,
CharaEars = 9,
CharaNeck = 10,
CharaWrist = 11,
CharaRing = 12,
CharaSoulCrystal = 17,
CharaMainHand = 0,
CharaOffHand = 1,
CharaHead = 2,
CharaBody = 3,
CharaHands = 4,
CharaWaist = 5,
CharaLegs = 6,
CharaFeet = 7,
CharaEars = 8,
CharaNeck = 9,
CharaWrist = 10,
CharaRing = 11,
CharaSoulCrystal = 12,
// specials
/* following slots not seem to exist any more.
when multi-slot gear is moved into equipment slot, normal slot listed above is used.
client will move any incompatible gears into armory but no InventoryModifiyHandler is sent.
server need to move those silently in order to sync with client.
*/
/*! Cannot equip gear to offhand slot */
MainTwoHandedWeapon = 13,
//MainTwoHandedWeapon = 13,
/*! Can be equipped in either main or offhand slot */
MainOrOffHand = 14, // unused
//MainOrOffHand = 14, // unused
/*! Cannot equip gear to head */
BodyDisallowHead = 15,
//BodyDisallowHead = 15,
/*! Cannot equip gear to hands, legs and feet slots */
BodyDisallowHandsLegsFeet = 16,
//BodyDisallowHandsLegsFeet = 16,
/*! Cannot equip gear to feet slot */
LegsDisallowFeet = 18,
//LegsDisallowFeet = 18,
/*! Cannot equp gear to head, hands, legs, feet slots */
BodyDisallowAll = 19,
//BodyDisallowAll = 19,
/*! Cannot equip gear to hands slot */
BodyDisallowHands = 20,
//BodyDisallowHands = 20,
/*! Cannot equip gear to legs & feet slots */
BodyDisallowLegsFeet = 21,
//BodyDisallowLegsFeet = 21,
};
enum InventoryType : uint16_t
@ -208,6 +218,8 @@ namespace Sapphire::Common
HandIn = 2005,
DamagedGear = 2007,
//UNKNOWN_1 = 2008,
// Temporary inventory that is used for the "trade" window
TradeInventory = 2009,
ArmoryOff = 3200,
ArmoryHead = 3201,
@ -216,14 +228,20 @@ namespace Sapphire::Common
ArmoryWaist = 3204,
ArmoryLegs = 3205,
ArmoryFeet = 3206,
ArmoryNeck = 3207,
ArmoryEar = 3208,
ArmoryEar = 3207,
ArmoryNeck = 3208,
ArmoryWrist = 3209,
ArmoryRing = 3300,
ArmorySoulCrystal = 3400,
ArmoryMain = 3500,
SaddleBag0 = 4000,
SaddleBag1 = 4001,
// These are the ones you get when paying for premium companion app
PremiumSaddleBag0 = 4100,
PremiumSaddleBag1 = 4101,
RetainerBag0 = 10000,
RetainerBag1 = 10001,
RetainerBag2 = 10002,
@ -396,7 +414,7 @@ namespace Sapphire::Common
struct StatusEffect
{
uint16_t effect_id;
uint16_t unknown1;
uint16_t param;
float duration;
uint32_t sourceActorId;
};
@ -548,6 +566,30 @@ namespace Sapphire::Common
};
enum FieldMarkerStatus : uint32_t
{
A = 0x1,
B = 0x2,
C = 0x4,
D = 0x8,
One = 0x10,
Two = 0x20,
Three = 0x40,
Four = 0x80
};
// TODO: consolidate these two into one since FieldMarkerStatus == 1 << FieldMarkerId?
enum class FieldMarkerId : uint8_t
{
A,
B,
C,
D,
One,
Two,
Three,
Four
};
enum struct ActionAspect : uint8_t
{
None = 0, // Doesn't imply unaspected
@ -565,19 +607,27 @@ namespace Sapphire::Common
None = 0, // ?
MagicPoints = 3,
TacticsPoints = 5,
// WARGauge = 22,
// DRKGauge = 25,
StatusEffect = 10,
WARGauge = 22,
DRKGauge = 25,
// AetherflowStack = 30,
// Status = 32,
// PLDGauge = 41,
SAMKenki = 39,
SAMSen = 40,
PLDGauge = 41,
GNBAmmo = 55,
WHMBloodLily = 56,
WHMLily = 57,
SAMMeditation = 63,
// RDMGaugeBoth = 74,
//// RDMGaugeBlack = 75, // not right?
// DRGGauge3Eyes = 76,
};
enum class ActionType : int8_t
enum class AttackType : int8_t
{
WeaponOverride = -1, // Needs more investigation (takes the damage type of the equipped weapon)?
//WeaponOverride = -1, // Needs more investigation (takes the damage type of the equipped weapon)?
Physical = -1, // seems to be the case
Unknown_0 = 0,
Slashing = 1,
Piercing = 2,
@ -606,28 +656,41 @@ namespace Sapphire::Common
TpLoss = 12,
TpGain = 13,
GpGain = 14,
ApplyStatusEffectTarget = 15,
ApplyStatusEffectSource = 16, // effect entry on target but buff applies to source, like storm's eye
StatusNoEffect = 20, // shifted one up from 5.18
/*!
* @brief Tells the client that it should show combo indicators on actions.
*
* @param flags Required to be 128, doesn't show combo rings on hotbars otherwise
* @param value The actionid that starts/continues the combo. eg, 3617 will start a spinning slash and/or syphon strike combo
*/
StartActionCombo = 28,
StartActionCombo = 27, // shifted one up from 5.18
ComboSucceed = 28, // shifted one up from 5.18, on retail this is not seen anymore, still working though.
Knockback = 33,
Mount = 38,
Mount = 40, // shifted one down from 5.18
VFX = 59, // links to VFX sheet
};
enum class ActionHitSeverityType : uint8_t
{
NormalDamage = 0,
CritHeal = 0,
NormalHeal = 0,
CritDamage = 1,
NormalHeal = 1,
CritHeal = 1,
DirectHitDamage = 2,
CritDirectHitDamage = 3
};
enum class ActionEffectResultFlag : uint8_t
{
None = 0,
Absorbed = 0x04,
ExtendedValue = 0x40,
EffectOnSource = 0x80,
Reflected = 0xA0,
};
enum ItemActionType : uint16_t
{
ItemActionVFX = 852,
@ -644,15 +707,15 @@ namespace Sapphire::Common
struct EffectEntry
{
Common::ActionEffectType effectType;
Common::ActionHitSeverityType hitSeverity;
uint8_t param;
uint8_t param0;
uint8_t param1;
/*!
* @brief Shows an additional percentage in the battle log
*
* Has no effect on what is shown and stored in value
*/
int8_t bonusPercent;
uint8_t valueMultiplier; // This multiplies whatever value is in the 'value' param by 10. Possibly a workaround for big numbers
uint8_t param2;
uint8_t extendedValueHighestByte;
uint8_t flags;
int16_t value;
};
@ -968,8 +1031,6 @@ namespace Sapphire::Common
enum LevelTableEntry : uint8_t
{
PIE,
MP,
MAIN,
SUB,
DIV,
@ -982,7 +1043,225 @@ namespace Sapphire::Common
{
SingleTarget = 1,
CircularAOE = 2,
Type3 = 3, // another single target? no idea how to call it
RectangularAOE = 4,
CircularAoEPlaced = 7
};
enum class Role : uint8_t
{
None,
Tank,
Healer,
RangedPhysical,
RangedMagical,
Melee,
Crafter,
Gatherer
};
enum class AstCardType : uint8_t
{
None = 0,
Balance = 1,
Bole = 2,
Arrow = 3,
Spear = 4,
Ewer = 5,
Spire = 6,
Lord = 0x70,
Lady = 0x80,
};
enum class AstSealType : uint8_t
{
None = 0,
Sun = 1,
Moon = 2,
Celestrial = 3,
};
enum class DrgState : uint8_t
{
None = 0,
BloodOfTheDragon = 1,
LifeOfTheDragon = 2,
};
enum class SamSen : uint8_t
{
None = 0,
Setsu = 1,
Getsu = 2,
Ka = 4,
};
enum class SchDismissedFairy : uint8_t
{
None = 0,
Eos = 6,
Selene = 7,
};
enum class SmnPet : uint8_t
{
None = 0,
Ifrit = 3,
Titan = 4,
Garuda = 5,
};
enum class SmnPetGlam : uint8_t
{
None = 0,
Emerald = 1,
Topaz = 2,
Ruby = 3,
};
enum class BrdSong : uint8_t
{
Mage = 5,
Army = 0x0A,
Wanderer = 0x0F,
};
union JobGauge
{
struct
{
uint8_t gauge_data[15];
} _raw;
struct
{
uint32_t unused;
AstCardType card;
AstSealType seals[3];
} ast;
struct
{
uint16_t timeUntilNextPolyglot;
uint16_t elementTimer;
uint8_t elementStance;
uint8_t umbralhearts;
uint8_t polyglotStacks;
uint8_t enochainState;
} blm;
struct
{
uint16_t songTimer;
uint8_t songStacks;
uint8_t unused;
BrdSong song;
} brd;
struct
{
uint8_t feathers;
uint8_t esprit;
uint8_t stepOrder[4];
uint8_t completeSteps;
} dnc;
struct
{
uint16_t dragonTimer;
DrgState dragonState;
uint8_t eyes;
} drg;
struct
{
uint8_t blood;
uint8_t unused;
uint16_t darksideTimer;
uint8_t darkArts;
uint8_t unused2;
uint16_t shadowTimer;
} drk;
struct
{
uint8_t ammo;
uint8_t unused;
uint16_t maxTimerDuration;
uint8_t ammoComboStep;
} gnb;
struct
{
uint16_t overheatTimer;
uint16_t robotTimer;
uint8_t heat;
uint8_t battery;
uint8_t lastRobotBatteryPower;
uint8_t activeTimerFlag;
} mch;
struct
{
uint8_t greasedLightningTimer;
uint8_t unused;
uint8_t greasedLightningStacks;
uint8_t chakra;
uint8_t greasedLightningTimerFreezed;
} mnk;
struct
{
uint32_t hutonTimer;
uint8_t tenChiJinMudrasUsed;
uint8_t ninki;
uint8_t hutonManualCasts;
} nin;
struct
{
uint8_t oathGauge;
} pld;
struct
{
uint8_t whiteGauge;
uint8_t blackGauge;
} rdm;
struct
{
uint16_t unused;
uint8_t unused2;
uint8_t kenki;
uint8_t meditationStacks;
SamSen sen;
} sam;
struct
{
uint16_t unused;
uint8_t aetherflowStacks;
uint8_t fairyGauge;
uint16_t seraphTimer;
SchDismissedFairy dismissedFairy;
} sch;
struct
{
uint16_t timer;
SmnPet returnSummon;
SmnPetGlam petGlam;
uint8_t stacks;
} smn;
struct
{
uint8_t beastGauge;
} war;
struct
{
uint16_t unused;
uint16_t lilyTimer;
uint8_t lilies;
uint8_t bloodLilies;
} whm;
};
enum class LootMessageType : uint8_t
{
GetItem1 = 1, // p1: actorId, p4: itemId (HQ: itemId + 1,000,000 lol), p5: amount
GetItem2 = 3, // p1: actorId, p2: itemId, p3: amount, seems like same thing as GetItem1 but different param position.
FailedToGetLootNoFreeInventorySlot = 5, // p1: actorId
LootRolled = 7, // p1: actorId, p2: itemId, p3: amount
GetGil = 9, // p1: gil
EmptyCoffer = 11, // seems like no param
};
using PlayerStateFlagList = std::vector< PlayerStateFlag >;

View file

@ -6,8 +6,7 @@
/* This file has been automatically generated.
Changes will be lost upon regeneration.
To change the content edit tools/exd_common_gen */
namespace Sapphire {
namespace Common {
namespace Sapphire::Common {
///////////////////////////////////////////////////////////
//ActionCategory.exd
@ -173,6 +172,8 @@ enum class ClassJob : uint8_t
Samurai = 34,
Redmage = 35,
Bluemage = 36,
Gunbreaker = 37,
Dancer = 38,
};
///////////////////////////////////////////////////////////
@ -199,14 +200,10 @@ enum class ContentType : uint8_t
DisciplesoftheHand = 17,
RetainerVentures = 18,
GoldSaucer = 19,
one = 20,
DeepDungeons = 21,
two = 22,
three = 23,
WondrousTails = 24,
CustomDeliveries = 25,
Eureka = 26,
four = 27,
};
///////////////////////////////////////////////////////////
@ -217,7 +214,6 @@ enum class EmoteCategory : uint8_t
General = 1,
Special = 2,
Expressions = 3,
one = 4,
};
///////////////////////////////////////////////////////////
@ -227,7 +223,7 @@ enum class ExVersion : uint8_t
ARealmReborn = 0,
Heavensward = 1,
Stormblood = 2,
three = 3,
Shadowbringers = 3,
};
///////////////////////////////////////////////////////////
@ -369,6 +365,8 @@ enum class ItemUICategory : uint8_t
SubmersibleBow = 103,
SubmersibleBridge = 104,
BlueMagesArm = 105,
GunbreakersArm = 106,
DancersArm = 107,
};
///////////////////////////////////////////////////////////
@ -393,7 +391,7 @@ enum class ItemSearchCategory : uint8_t
ConjurersArms = 15,
ArcanistsArms = 16,
Shields = 17,
ThrowingWeapons = 18,
DancersArms = 18,
CarpentersTools = 19,
BlacksmithsTools = 20,
ArmorersTools = 21,
@ -454,13 +452,15 @@ enum class ItemSearchCategory : uint8_t
DarkKnightsArms = 76,
MachinistsArms = 77,
AstrologiansArms = 78,
Airship_SubmersibleComponents = 79,
AirshipSubmersibleComponents = 79,
OrchestrionComponents = 80,
GardeningItems = 81,
Paintings = 82,
SamuraisArms = 83,
RedMagesArms = 84,
ScholarsArms = 85,
GunbreakersArms = 86,
ThrowingWeapons = 87,
};
///////////////////////////////////////////////////////////
@ -527,6 +527,8 @@ enum class Race : uint8_t
Miqote = 4,
Roegadyn = 5,
AuRa = 6,
Hrothgar = 7,
Viera = 8,
};
///////////////////////////////////////////////////////////
@ -546,6 +548,10 @@ enum class Tribe : uint8_t
Hellsguard = 10,
Raen = 11,
Xaela = 12,
Helions = 13,
TheLost = 14,
Rava = 15,
Veena = 16,
};
///////////////////////////////////////////////////////////
@ -558,6 +564,7 @@ enum class Town : uint8_t
Uldah = 3,
Ishgard = 4,
Kugane = 7,
TheCrystarium = 10,
};
///////////////////////////////////////////////////////////
@ -680,7 +687,21 @@ enum class Weather : uint8_t
TrueBlue = 113,
TrueBlue1 = 114,
TrueBlue2 = 115,
UmbralTurbulence = 116,
TrueBlue3 = 117,
EverlastingLight = 118,
Gales2 = 119,
Termination = 120,
Termination1 = 121,
Dreams = 122,
Dreams1 = 123,
Dreams2 = 124,
Brilliance = 125,
Brilliance1 = 126,
Termination2 = 127,
Termination3 = 128,
EverlastingLight1 = 129,
Termination4 = 131,
};
///////////////////////////////////////////////////////////
@ -703,8 +724,12 @@ enum class HousingAppeal : uint8_t
Library = 14,
PhotoStudio = 15,
HauntedHouse = 16,
Atelier = 17,
Bathhouse = 18,
Garden = 19,
FarEastern = 20,
};
}
}
#endif

View file

@ -1,16 +1,18 @@
#include "ConfigMgr.h"
#include <iostream>
#include <fstream>
#include <experimental/filesystem>
#include <filesystem>
namespace fs = std::experimental::filesystem;
namespace fs = std::filesystem;
using namespace Sapphire;
using namespace Sapphire::Common;
/**
* Loads an ini file and parses it
* @param configName the name of ini file relative to m_configFolderRoot to load alongside global.ini
* @return true if loading was successful
*/
bool Sapphire::ConfigMgr::loadConfig( const std::string& configName )
bool ConfigMgr::loadConfig( const std::string& configName )
{
// get global config
auto configFile = fs::path( fs::path( m_configFolderRoot ) / configName );
@ -29,7 +31,7 @@ bool Sapphire::ConfigMgr::loadConfig( const std::string& configName )
return true;
}
bool Sapphire::ConfigMgr::loadGlobalConfig( Common::Config::GlobalConfig& config, const std::string& configName )
bool ConfigMgr::loadGlobalConfig( Common::Config::GlobalConfig& config, const std::string& configName )
{
auto configFile = fs::path( fs::path( m_configFolderRoot ) / configName );
@ -71,7 +73,7 @@ bool Sapphire::ConfigMgr::loadGlobalConfig( Common::Config::GlobalConfig& config
return true;
}
bool Sapphire::ConfigMgr::copyDefaultConfig( const std::string& configName )
bool ConfigMgr::copyDefaultConfig( const std::string& configName )
{
fs::path configPath( m_configFolderRoot );
configPath /= configName;

View file

@ -8,7 +8,7 @@
#include <stdint.h>
#include "ConfigDef.h"
namespace Sapphire
namespace Sapphire::Common
{
class ConfigMgr
{

View file

@ -41,7 +41,7 @@ static inline bool is_base64( uint8_t c )
return ( isalnum( c ) || ( c == '+' ) || ( c == '/' ) );
}
std::string Sapphire::Util::base64Encode( uint8_t const* bytes_to_encode, uint32_t in_len )
std::string Sapphire::Common::Util::base64Encode( uint8_t const* bytes_to_encode, uint32_t in_len )
{
std::string ret;
int32_t i = 0;
@ -87,7 +87,7 @@ std::string Sapphire::Util::base64Encode( uint8_t const* bytes_to_encode, uint32
}
std::string Sapphire::Util::base64Decode( std::string const& encoded_string )
std::string Sapphire::Common::Util::base64Decode( std::string const& encoded_string )
{
int32_t in_len = encoded_string.size();
int32_t i = 0;

View file

@ -1,6 +1,6 @@
#include <string>
namespace Sapphire::Util
namespace Sapphire::Common::Util
{
std::string base64Encode( uint8_t const*, uint32_t len );

View file

@ -37,7 +37,7 @@
(b)[(i) + 3] = (uint8_t) ( (n) >> 24 ); \
}
void Sapphire::Util::md5_starts( md5_context* ctx )
void Sapphire::Common::Util::md5_starts( md5_context* ctx )
{
ctx->total[ 0 ] = 0;
ctx->total[ 1 ] = 0;
@ -48,7 +48,7 @@ void Sapphire::Util::md5_starts( md5_context* ctx )
ctx->state[ 3 ] = 0x10325476;
}
void md5_process( Sapphire::Util::md5_context* ctx, uint8_t data[64] )
void md5_process( Sapphire::Common::Util::md5_context* ctx, uint8_t data[64] )
{
uint32_t X[16], A, B, C, D;
@ -171,7 +171,7 @@ void md5_process( Sapphire::Util::md5_context* ctx, uint8_t data[64] )
ctx->state[ 3 ] += D;
}
void Sapphire::Util::md5_update( md5_context* ctx, uint8_t* input, uint32_t length )
void Sapphire::Common::Util::md5_update( md5_context* ctx, uint8_t* input, uint32_t length )
{
uint32_t left, fill;
@ -219,7 +219,7 @@ static uint8_t md5_padding[64] =
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
void Sapphire::Util::md5_finish( md5_context* ctx, uint8_t digest[16] )
void Sapphire::Common::Util::md5_finish( md5_context* ctx, uint8_t digest[16] )
{
uint32_t last, padn;
uint32_t high, low;
@ -248,7 +248,7 @@ void Sapphire::Util::md5_finish( md5_context* ctx, uint8_t digest[16] )
* those are the standard RFC 1321 test vectors
*/
void Sapphire::Util::md5( uint8_t* text, uint8_t* hash, int32_t size )
void Sapphire::Common::Util::md5( uint8_t* text, uint8_t* hash, int32_t size )
{
md5_context ctx;
md5_starts( &ctx );

View file

@ -3,7 +3,7 @@
#include <stdint.h>
namespace Sapphire::Util
namespace Sapphire::Common::Util
{
using md5_context = struct
{

View file

@ -1,6 +1,8 @@
#ifndef SAPPHIRE_DBCOMMON_H
#define SAPPHIRE_DBCOMMON_H
#include <string>
namespace Sapphire::Db
{
struct ConnectionInfo

View file

@ -4,7 +4,6 @@
#include "Logging/Logger.h"
#include "PreparedStatement.h"
#include "Framework.h"
Sapphire::Db::DbConnection::DbConnection( ConnectionInfo& connInfo ) :
m_reconnecting( false ),
@ -17,7 +16,7 @@ Sapphire::Db::DbConnection::DbConnection( ConnectionInfo& connInfo ) :
}
Sapphire::Db::DbConnection::DbConnection( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* queue,
Sapphire::Db::DbConnection::DbConnection( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* queue,
Sapphire::Db::ConnectionInfo& connInfo ) :
m_reconnecting( false ),
m_prepareError( false ),

View file

@ -42,7 +42,7 @@ namespace Sapphire::Db
DbConnection( ConnectionInfo& connInfo );
// Constructor for asynchronous connections.
DbConnection( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* queue, ConnectionInfo& connInfo );
DbConnection( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* queue, ConnectionInfo& connInfo );
virtual ~DbConnection();
@ -92,7 +92,7 @@ namespace Sapphire::Db
bool m_prepareError;
private:
LockedWaitQueue< std::shared_ptr< Operation > >* m_queue;
Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* m_queue;
std::shared_ptr< DbWorker > m_worker;
std::shared_ptr< Mysql::Connection > m_pConnection;
ConnectionInfo& m_connectionInfo;

View file

@ -2,7 +2,9 @@
#include "Operation.h"
#include "Util/LockedWaitQueue.h"
Sapphire::Db::DbWorker::DbWorker( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* newQueue,
using namespace Sapphire::Common;
Sapphire::Db::DbWorker::DbWorker( Util::LockedWaitQueue< std::shared_ptr< Operation > >* newQueue,
DbConnection* pConn )
{
m_pConn = pConn;

View file

@ -14,12 +14,12 @@ namespace Sapphire::Db
class DbWorker
{
public:
DbWorker( LockedWaitQueue< std::shared_ptr< Operation > >* newQueue, DbConnection* connection );
DbWorker( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* newQueue, DbConnection* connection );
~DbWorker();
private:
LockedWaitQueue< std::shared_ptr< Operation > >* m_queue;
Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* m_queue;
DbConnection* m_pConn;
void workerThread();

View file

@ -5,7 +5,6 @@
#include "StatementTask.h"
#include "Operation.h"
#include "ZoneDbConnection.h"
#include "Framework.h"
#include "Logging/Logger.h"
#include <mysql.h>
@ -21,7 +20,7 @@ class PingOperation : public Sapphire::Db::Operation
template< class T >
Sapphire::Db::DbWorkerPool< T >::DbWorkerPool() :
m_queue( new Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >() ),
m_queue( new Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >() ),
m_asyncThreads( 0 ),
m_synchThreads( 0 )
{

View file

@ -83,7 +83,7 @@ namespace Sapphire::Db
const std::string& getDatabaseName() const;
std::unique_ptr< Sapphire::LockedWaitQueue< std::shared_ptr< Operation > > > m_queue;
std::unique_ptr< Common::Util::LockedWaitQueue< std::shared_ptr< Operation > > > m_queue;
std::array< std::vector< std::shared_ptr< T > >, IDX_SIZE > m_connections;
ConnectionInfo m_connectionInfo;
uint8_t m_asyncThreads;

View file

@ -6,7 +6,7 @@ Sapphire::Db::ZoneDbConnection::ZoneDbConnection( ConnectionInfo& connInfo ) :
{
}
Sapphire::Db::ZoneDbConnection::ZoneDbConnection( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* q,
Sapphire::Db::ZoneDbConnection::ZoneDbConnection( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* q,
ConnectionInfo& connInfo ) :
DbConnection( q, connInfo )
{
@ -22,7 +22,8 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
m_stmts.resize( MAX_STATEMENTS );
/// CHARA
prepareStatement( CHARA_SEL, "SELECT ContentId, Name, Hp, Mp, Tp, Gp, Mode, Mount, InvincibleGM, Voice, "
prepareStatement( CHARA_SEL,
"SELECT ContentId, Name, Hp, Mp, Tp, Gp, Mode, Mount, InvincibleGM, Voice, "
"Customize, ModelMainWeapon, ModelSubWeapon, ModelSystemWeapon, "
"ModelEquip, EmoteModeType, FirstLoginTime, Language, IsNewGame, "
"IsNewAdventurer, TerritoryType, TerritoryId, PosX, PosY, PosZ, PosR, "
@ -33,7 +34,8 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
"QuestCompleteFlags, OpeningSequence, QuestTracking, GrandCompany, "
"GrandCompanyRank, Discovery, GMRank, EquipDisplayFlags, Unlocks, CFPenaltyUntil, "
"Pose "
"FROM charainfo WHERE CharacterId = ?;", CONNECTION_SYNC );
"FROM charainfo WHERE CharacterId = ?;",
CONNECTION_SYNC );
prepareStatement( CHARA_UP,
@ -47,14 +49,18 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
"ActiveTitle = ?, TitleList = ?, Achievement = ?, Aetheryte = ?, HowTo = ?, Minions = ?, Mounts = ?, Orchestrion = ?, "
"EquippedMannequin = ?, ConfigFlags = ?, QuestCompleteFlags = ?, OpeningSequence = ?, "
"QuestTracking = ?, GrandCompany = ?, GrandCompanyRank = ?, Discovery = ?, GMRank = ?, EquipDisplayFlags = ?, Unlocks = ?, "
"CFPenaltyUntil = ?, Pose = ? WHERE CharacterId = ?;", CONNECTION_ASYNC );
"CFPenaltyUntil = ?, Pose = ? WHERE CharacterId = ?;",
CONNECTION_ASYNC );
prepareStatement( CHARA_SEL_MINIMAL, "SELECT Name, Customize, ModelMainWeapon, ModelSubWeapon, ModelEquip, TerritoryType, GuardianDeity, "
prepareStatement( CHARA_SEL_MINIMAL,
"SELECT Name, Customize, ModelMainWeapon, ModelSubWeapon, ModelEquip, TerritoryType, GuardianDeity, "
"Class, ContentId, BirthDay, BirthMonth, EquipDisplayFlags "
"FROM charainfo WHERE CharacterId = ?;", CONNECTION_SYNC );
"FROM charainfo WHERE CharacterId = ?;",
CONNECTION_SYNC );
prepareStatement( CHARA_INS, "INSERT INTO charainfo (AccountId, CharacterId, ContentId, Name, Hp, Mp, "
prepareStatement( CHARA_INS,
"INSERT INTO charainfo (AccountId, CharacterId, ContentId, Name, Hp, Mp, "
"Customize, Voice, IsNewGame, TerritoryType, PosX, PosY, PosZ, PosR, ModelEquip, "
"IsNewAdventurer, GuardianDeity, Birthday, BirthMonth, Class, Status, FirstClass, "
"HomePoint, StartTown, Discovery, HowTo, QuestCompleteFlags, Unlocks, QuestTracking, "

View file

@ -112,7 +112,7 @@ namespace Sapphire::Db
ZoneDbConnection( ConnectionInfo& connInfo );
ZoneDbConnection( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* q, ConnectionInfo& connInfo );
ZoneDbConnection( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* q, ConnectionInfo& connInfo );
~ZoneDbConnection();

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -5,12 +5,16 @@
namespace Sapphire
{
class ConfigMgr;
class Framework;
using ConfigMgrPtr = std::shared_ptr< ConfigMgr >;
using FrameworkPtr = std::shared_ptr< Framework >;
}
namespace Sapphire::Common
{
class ConfigMgr;
using ConfigMgrPtr = std::shared_ptr< ConfigMgr >;
}
namespace Sapphire::Network
{
class Hive;

View file

@ -1,2 +0,0 @@
#include "Framework.h"
#include "Logging/Logger.h"

View file

@ -1,37 +0,0 @@
#ifndef _CORE_FRAMEWORK_H
#define _CORE_FRAMEWORK_H
#include <map>
#include <typeindex>
#include <typeinfo>
#include <memory>
#include <cassert>
namespace Sapphire
{
class Framework
{
using TypenameToObject = std::map< std::type_index, std::shared_ptr< void > >;
TypenameToObject ObjectMap;
public:
template< typename T >
std::shared_ptr< T > get()
{
auto iType = ObjectMap.find( typeid( T ) );
assert( !( iType == ObjectMap.end() ) );
return std::static_pointer_cast< T >( iType->second );
}
template< typename T >
void set( std::shared_ptr< T > value )
{
assert( value ); // why would anyone store nullptrs....
ObjectMap[ typeid( T ) ] = value;
}
};
}
#endif // _CORE_FRAMEWORK_H

View file

@ -1,6 +1,6 @@
#include "Logger.h"
#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info", "warning", "error", "fatal", "off" }
#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info", "warn", "error", "fatal", "off" }
#include <spdlog/spdlog.h>
#include <spdlog/async.h>
@ -8,9 +8,9 @@
#include <spdlog/sinks/daily_file_sink.h>
// #include <iostream>
#include <experimental/filesystem> // or #include <filesystem>
#include <filesystem> // or #include <filesystem>
namespace fs = std::experimental::filesystem;
namespace fs = std::filesystem;
void Sapphire::Logger::init( const std::string& logPath )
{

View file

@ -2,7 +2,10 @@
#include "Acceptor.h"
#include "Connection.h"
Sapphire::Network::Acceptor::Acceptor( HivePtr hive ) :
using namespace Sapphire;
Network::Acceptor::Acceptor( HivePtr hive ) :
m_hive( hive ),
m_acceptor( hive->getService() ),
m_io_strand( hive->getService() ),
@ -10,21 +13,21 @@ Sapphire::Network::Acceptor::Acceptor( HivePtr hive ) :
{
}
Sapphire::Network::Acceptor::~Acceptor()
Network::Acceptor::~Acceptor()
{
}
bool Sapphire::Network::Acceptor::onAccept( ConnectionPtr connection, const std::string& host, uint16_t port )
bool Network::Acceptor::onAccept( ConnectionPtr connection, const std::string& host, uint16_t port )
{
return true;
}
void Sapphire::Network::Acceptor::onError( const asio::error_code& error )
void Network::Acceptor::onError( const asio::error_code& error )
{
}
void Sapphire::Network::Acceptor::startError( const asio::error_code& error )
void Network::Acceptor::startError( const asio::error_code& error )
{
uint32_t v1 = 1;
uint32_t v2 = 0;
@ -37,7 +40,7 @@ void Sapphire::Network::Acceptor::startError( const asio::error_code& error )
}
}
void Sapphire::Network::Acceptor::dispatchAccept( ConnectionPtr connection )
void Network::Acceptor::dispatchAccept( ConnectionPtr connection )
{
m_acceptor.async_accept( connection->getSocket(),
connection->getStrand().wrap( std::bind( &Acceptor::handleAccept,
@ -46,7 +49,7 @@ void Sapphire::Network::Acceptor::dispatchAccept( ConnectionPtr connection )
connection ) ) );
}
void Sapphire::Network::Acceptor::handleAccept( const asio::error_code& error, ConnectionPtr connection )
void Network::Acceptor::handleAccept( const asio::error_code& error, ConnectionPtr connection )
{
if( error || hasError() || m_hive->hasStopped() )
{
@ -72,17 +75,17 @@ void Sapphire::Network::Acceptor::handleAccept( const asio::error_code& error, C
}
}
void Sapphire::Network::Acceptor::stop()
void Network::Acceptor::stop()
{
}
void Sapphire::Network::Acceptor::accept( ConnectionPtr connection )
void Network::Acceptor::accept( ConnectionPtr connection )
{
m_io_strand.post( std::bind( &Acceptor::dispatchAccept, shared_from_this(), connection ) );
}
void Sapphire::Network::Acceptor::listen( const std::string& host, const uint16_t& port )
void Network::Acceptor::listen( const std::string& host, const uint16_t& port )
{
try
{
@ -103,17 +106,17 @@ void Sapphire::Network::Acceptor::listen( const std::string& host, const uint16_
}
Sapphire::Network::HivePtr Sapphire::Network::Acceptor::getHive()
Network::HivePtr Network::Acceptor::getHive()
{
return m_hive;
}
asio::ip::tcp::acceptor& Sapphire::Network::Acceptor::getAcceptor()
asio::ip::tcp::acceptor& Network::Acceptor::getAcceptor()
{
return m_acceptor;
}
bool Sapphire::Network::Acceptor::hasError()
bool Network::Acceptor::hasError()
{
uint32_t v1 = 1;
uint32_t v2 = 1;

View file

@ -24,6 +24,9 @@ enum ActorControlType : uint16_t
SetStatus = 0x02,
CastStart = 0x03,
ToggleAggro = 0x04,
/*!
* param1 = ClassJob ID
*/
ClassJobChange = 0x05,
DefeatMsg = 0x06,
GainExpMsg = 0x07,
@ -98,6 +101,8 @@ enum ActorControlType : uint16_t
FreeEventPos = 0x8A,
DailyQuestSeed = 0x90, // param1 = the daily quest seed
SetBGM = 0xA1,
UnlockAetherCurrentMsg = 0xA4,
@ -140,6 +145,15 @@ enum ActorControlType : uint16_t
SetPose = 0x127,
/*!
* This is used for general crafting events, I found some of them but some are missing:
*
* param1 = event type, the rest of the struct depends on this param.
* - 18 & 19: Quicksynth result, 19 means HQ result item, item ID is param2 and is + 1 000 000 when HQ.
* Quantity is param3 (possible quicksynth that gives more than one item in the future?)
*
* All the other values have unkown behavior for now.
*/
CraftingUnk = 0x12C,
GatheringSenseMsg = 0x130,
@ -173,6 +187,14 @@ enum ActorControlType : uint16_t
RelicInfuseMsg = 0x179,
/*!
* Sent as result of an aetherial reduction.
* param1 = Reduced item ID + 500 000 (idk what this 500 000 is but it's always here no matter what)
* param2 = First result item id (+ 1 000 000 if HQ)
* param3 = First result item quantity
* param4 = (Optional) Second result item id (+ 1 000 000 if HQ)
* param5 = (Optional) Second result item quantity
*/
AetherReductionDlg = 0x17D,
/*!
@ -204,6 +226,22 @@ enum ActorControlType : uint16_t
ChallengeEntryCompleteMsg = 0x20B,
ChallengeEntryUnlockMsg = 0x20C,
/*!
* Sent when a player desynths an item, one packet per result type (one for consumed item, one for each obtained items, and one for exp if the player received exp)
* param1 = result type
* 4921 => Desynth item consumed
* 4922 => Desynth item obtained
* 4925 => Desynth exp obtained)
* 3553 => Reduction item used
* 3555 => Reduction item obtained
* param3 = u32 item id (+100 000 if item is HQ)
* param4 = item amount (used only for reduction it seems)
* param5 = exp amount (x 100)
*
* Idk exactly how reduce's param3 is formatted, it seems like it's item id + 500 000 but it seems too... shady.
*/
DesynthOrReductionResult = 0x20F,
GilTrailMsg = 0x211,
HuntingLogRankUnlock = 0x21D,
@ -220,10 +258,22 @@ enum ActorControlType : uint16_t
GearSetEquipMsg = 0x321,
SetBait = 0x325, // param1: bait ID
SetFestival = 0x386, // param1: festival.exd index
ToggleOrchestrionUnlock = 0x396,
Dismount = 0x3A1, // updated 4.5
EventBattleDialog = 0x39D,
/*!
* param1 = mountSpeed
* Retail sends 12 for mount speed star 1 unlocked and 15 for mount speed star 2 unlocked
* This also has to be sent before mounting finishes for it to take effect
*/
SetMountSpeed = 0x3A0, // updated 5.35 hotfix
Dismount = 0x3A2, // updated 5.35 hotfix
// Duty Recorder
BeginReplayAck = 0x3A2,
@ -300,6 +350,7 @@ enum ActorControlType : uint16_t
DismountReq = 0x65,
SpawnCompanionReq = 0x66,
DespawnCompanionReq = 0x67,
RemoveStatusEffect = 0x68,
CastCancel = 0x69,
@ -315,20 +366,26 @@ enum ActorControlType : uint16_t
UpdatedSeenHowTos = 0x133,
AllotAttribute = 0x135,
ClearWaymarks = 0x13A,
ClearFieldMarkers = 0x13A,
CameraMode = 0x13B, // param12, 1 = camera mode enable, 0 = disable
CharaNameReq = 0x13D, // requests character name by content id
HuntingLogDetails = 0x194,
Timers = 0x1AB,
DyeItem = 0x1B5,
DyeItem = 0x1B0, // updated 5.21
RequestChocoboInventory = 0x1C4,
EmoteReq = 0x1F4,
EmoteCancel = 0x1F6,
PersistentEmoteCancel = 0x1F7,
/*!
* param2 = pose ID
* 0 = idle pose 0 (just standing)
* 1 = idle pose 1
* 2-4 = idle poses 2-4
*/
PoseChange = 0x1F9,
PoseReapply = 0x1FA,
PoseCancel = 0x1FB,
@ -337,6 +394,8 @@ enum ActorControlType : uint16_t
AchievementComp = 0x203,
AchievementCatChat = 0x206,
RequestEventBattle = 0x232C,
QuestJournalUpdateQuestVisibility = 0x2BE,
QuestJournalClosed = 0x2BF,

View file

@ -1,23 +1,21 @@
#include "Connection.h"
#include "Hive.h"
#include <functional>
#include "Framework.h"
Sapphire::Network::Connection::Connection( HivePtr hive, FrameworkPtr pFw ) :
using namespace Sapphire;
Network::Connection::Connection( HivePtr hive ) :
m_hive( hive ),
m_socket( hive->getService() ),
m_io_strand( hive->getService() ),
m_receive_buffer_size( 32000 ),
m_error_state( 0 ),
m_pFw( pFw )
m_error_state( 0 )
{
}
Sapphire::Network::Connection::~Connection()
{
}
Network::Connection::~Connection() = default;
void Sapphire::Network::Connection::bind( const std::string& ip, uint16_t port )
void Network::Connection::bind( const std::string& ip, uint16_t port )
{
asio::ip::tcp::endpoint endpoint( asio::ip::address::from_string( ip ), port );
m_socket.open( endpoint.protocol() );
@ -25,7 +23,7 @@ void Sapphire::Network::Connection::bind( const std::string& ip, uint16_t port )
m_socket.bind( endpoint );
}
void Sapphire::Network::Connection::startSend()
void Network::Connection::startSend()
{
if( !m_pending_sends.empty() )
{
@ -38,7 +36,7 @@ void Sapphire::Network::Connection::startSend()
}
}
void Sapphire::Network::Connection::startRecv( int32_t total_bytes )
void Network::Connection::startRecv( int32_t total_bytes )
{
if( total_bytes > 0 )
{
@ -61,7 +59,7 @@ void Sapphire::Network::Connection::startRecv( int32_t total_bytes )
}
}
void Sapphire::Network::Connection::startError( const asio::error_code& error )
void Network::Connection::startError( const asio::error_code& error )
{
uint32_t v1 = 1;
uint32_t v2 = 0;
@ -74,7 +72,7 @@ void Sapphire::Network::Connection::startError( const asio::error_code& error )
}
}
void Sapphire::Network::Connection::handleConnect( const asio::error_code& error )
void Network::Connection::handleConnect( const asio::error_code& error )
{
if( error || hasError() || m_hive->hasStopped() )
{
@ -94,7 +92,7 @@ void Sapphire::Network::Connection::handleConnect( const asio::error_code& error
}
}
void Sapphire::Network::Connection::handleSend( const asio::error_code& error,
void Network::Connection::handleSend( const asio::error_code& error,
std::list< std::vector< uint8_t > >::iterator itr )
{
if( error || hasError() || m_hive->hasStopped() )
@ -109,7 +107,7 @@ void Sapphire::Network::Connection::handleSend( const asio::error_code& error,
}
}
void Sapphire::Network::Connection::handleRecv( const asio::error_code& error, int32_t actual_bytes )
void Network::Connection::handleRecv( const asio::error_code& error, int32_t actual_bytes )
{
if( error || hasError() || m_hive->hasStopped() )
{
@ -128,7 +126,7 @@ void Sapphire::Network::Connection::handleRecv( const asio::error_code& error, i
}
}
void Sapphire::Network::Connection::dispatchSend( std::vector< uint8_t > buffer )
void Network::Connection::dispatchSend( std::vector< uint8_t > buffer )
{
bool should_start_send = m_pending_sends.empty();
m_pending_sends.push_back( buffer );
@ -138,7 +136,7 @@ void Sapphire::Network::Connection::dispatchSend( std::vector< uint8_t > buffer
}
}
void Sapphire::Network::Connection::dispatchRecv( int32_t total_bytes )
void Network::Connection::dispatchRecv( int32_t total_bytes )
{
bool should_start_receive = m_pending_recvs.empty();
m_pending_recvs.push_back( total_bytes );
@ -149,7 +147,7 @@ void Sapphire::Network::Connection::dispatchRecv( int32_t total_bytes )
}
void Sapphire::Network::Connection::connect( const std::string& host, uint16_t port )
void Network::Connection::connect( const std::string& host, uint16_t port )
{
asio::ip::tcp::resolver resolver( m_hive->getService() );
asio::ip::tcp::resolver::query query( host, std::to_string( port ) );
@ -160,48 +158,48 @@ void Sapphire::Network::Connection::connect( const std::string& host, uint16_t p
}
void Sapphire::Network::Connection::disconnect()
void Network::Connection::disconnect()
{
onDisconnect();
m_socket.close();
}
void Sapphire::Network::Connection::recv( int32_t total_bytes )
void Network::Connection::recv( int32_t total_bytes )
{
m_io_strand.post( std::bind( &Connection::dispatchRecv, shared_from_this(), total_bytes ) );
}
void Sapphire::Network::Connection::send( const std::vector< uint8_t >& buffer )
void Network::Connection::send( const std::vector< uint8_t >& buffer )
{
m_io_strand.post( std::bind( &Connection::dispatchSend, shared_from_this(), buffer ) );
}
asio::ip::tcp::socket& Sapphire::Network::Connection::getSocket()
asio::ip::tcp::socket& Network::Connection::getSocket()
{
return m_socket;
}
asio::strand& Sapphire::Network::Connection::getStrand()
asio::strand& Network::Connection::getStrand()
{
return m_io_strand;
}
Sapphire::Network::HivePtr Sapphire::Network::Connection::getHive()
Network::HivePtr Network::Connection::getHive()
{
return m_hive;
}
void Sapphire::Network::Connection::setReceiveBufferSize( int32_t size )
void Network::Connection::setReceiveBufferSize( int32_t size )
{
m_receive_buffer_size = size;
}
int32_t Sapphire::Network::Connection::getReceiveBufferSize() const
int32_t Network::Connection::getReceiveBufferSize() const
{
return m_receive_buffer_size;
}
bool Sapphire::Network::Connection::hasError()
bool Network::Connection::hasError()
{
uint32_t v1 = 1;
uint32_t v2 = 1;

View file

@ -12,12 +12,6 @@
#include "Acceptor.h"
#include <memory>
namespace Sapphire
{
class Framework;
using FrameworkPtr = std::shared_ptr< Framework >;
}
namespace Sapphire::Network
{
@ -41,9 +35,8 @@ namespace Sapphire::Network
std::list< std::vector< uint8_t > > m_pending_sends;
int32_t m_receive_buffer_size;
std::atomic< uint32_t > m_error_state;
Sapphire::FrameworkPtr m_pFw;
Connection( HivePtr hive, FrameworkPtr pFw );
Connection( HivePtr hive );
virtual ~Connection();
@ -147,13 +140,13 @@ namespace Sapphire::Network
//-----------------------------------------------------------------------------
template< class T >
std::shared_ptr< T > addServerToHive( const std::string& listenIp, uint32_t port, HivePtr pHive, FrameworkPtr pFw )
std::shared_ptr< T > addServerToHive( const std::string& listenIp, uint32_t port, HivePtr pHive )
{
try
{
AcceptorPtr acceptor( new Acceptor( pHive ) );
acceptor->listen( listenIp, port );
std::shared_ptr< T > connection( new T( pHive, acceptor, pFw ) );
std::shared_ptr< T > connection( new T( pHive, acceptor ) );
acceptor->accept( connection );
return connection;
}

View file

@ -257,7 +257,7 @@ namespace Sapphire::Network::Packets
// The IPC type itself.
m_ipcHdr.type = static_cast< ServerZoneIpcType >( m_data._ServerIpcType );
m_ipcHdr.timestamp = Util::getTimeSeconds();
m_ipcHdr.timestamp = Common::Util::getTimeSeconds();
m_segHdr.size = sizeof( T ) + sizeof( FFXIVARR_IPC_HEADER ) + sizeof( FFXIVARR_PACKET_SEGMENT_HEADER );
};

View file

@ -3,9 +3,10 @@
#include <string.h> // memcpy
using namespace Sapphire;
using namespace Sapphire::Network::Packets;
PacketParseResult Sapphire::Network::Packets::getHeader( const std::vector< uint8_t >& buffer,
PacketParseResult Network::Packets::getHeader( const std::vector< uint8_t >& buffer,
const uint32_t offset,
FFXIVARR_PACKET_HEADER& header )
{
@ -25,7 +26,7 @@ PacketParseResult Sapphire::Network::Packets::getHeader( const std::vector< uint
return Success;
}
PacketParseResult Sapphire::Network::Packets::getSegmentHeader( const std::vector< uint8_t >& buffer,
PacketParseResult Network::Packets::getSegmentHeader( const std::vector< uint8_t >& buffer,
const uint32_t offset,
FFXIVARR_PACKET_SEGMENT_HEADER& header )
{
@ -42,7 +43,7 @@ PacketParseResult Sapphire::Network::Packets::getSegmentHeader( const std::vecto
return Success;
}
PacketParseResult Sapphire::Network::Packets::getPackets( const std::vector< uint8_t >& buffer,
PacketParseResult Network::Packets::getPackets( const std::vector< uint8_t >& buffer,
const uint32_t offset,
const FFXIVARR_PACKET_HEADER& packetHeader,
std::vector< FFXIVARR_PACKET_RAW >& packets )
@ -81,7 +82,7 @@ PacketParseResult Sapphire::Network::Packets::getPackets( const std::vector< uin
return Success;
}
PacketParseResult Sapphire::Network::Packets::getPacket( const std::vector< uint8_t >& buffer, const uint32_t offset,
PacketParseResult Network::Packets::getPacket( const std::vector< uint8_t >& buffer, const uint32_t offset,
FFXIVARR_PACKET_RAW& packet )
{
// Copy segment header
@ -103,7 +104,7 @@ PacketParseResult Sapphire::Network::Packets::getPacket( const std::vector< uint
return Success;
}
bool Sapphire::Network::Packets::checkHeader( const FFXIVARR_PACKET_HEADER& header )
bool Network::Packets::checkHeader( const FFXIVARR_PACKET_HEADER& header )
{
// Max size of the packet is capped at 1MB for now.
if( header.size > 1 * 1024 * 1024 )
@ -116,7 +117,7 @@ bool Sapphire::Network::Packets::checkHeader( const FFXIVARR_PACKET_HEADER& head
return true;
}
bool Sapphire::Network::Packets::checkSegmentHeader( const FFXIVARR_PACKET_SEGMENT_HEADER& header )
bool Network::Packets::checkSegmentHeader( const FFXIVARR_PACKET_SEGMENT_HEADER& header )
{
// Max size of individual message is capped at 256KB for now.
if( header.size > 256 * 1024 )

View file

@ -2,41 +2,43 @@
#include <functional>
#include "Hive.h"
using namespace Sapphire;
//-----------------------------------------------------------------------------
Sapphire::Network::Hive::Hive() :
Network::Hive::Hive() :
m_work_ptr( new asio::io_service::work( m_io_service ) ),
m_shutdown( 0 )
{
}
Sapphire::Network::Hive::~Hive()
Network::Hive::~Hive()
{
}
asio::io_service& Sapphire::Network::Hive::getService()
asio::io_service& Network::Hive::getService()
{
return m_io_service;
}
bool Sapphire::Network::Hive::hasStopped()
bool Network::Hive::hasStopped()
{
uint32_t v1 = 1;
uint32_t v2 = 1;
return m_shutdown.compare_exchange_strong( v1, v2 );
}
void Sapphire::Network::Hive::poll()
void Network::Hive::poll()
{
m_io_service.poll();
}
void Sapphire::Network::Hive::run()
void Network::Hive::run()
{
m_io_service.run();
}
void Sapphire::Network::Hive::stop()
void Network::Hive::stop()
{
uint32_t v1 = 1;
uint32_t v2 = 0;
@ -48,7 +50,7 @@ void Sapphire::Network::Hive::stop()
}
}
void Sapphire::Network::Hive::reset()
void Network::Hive::reset()
{
uint32_t v1 = 0;
uint32_t v2 = 1;

View file

@ -7,7 +7,9 @@
#include <string.h>
#include <memory>
Sapphire::Network::Packets::PacketContainer::PacketContainer( uint32_t segmentTargetOverride ) :
using namespace Sapphire;
Network::Packets::PacketContainer::PacketContainer( uint32_t segmentTargetOverride ) :
m_segmentTargetOverride( segmentTargetOverride )
{
memset( &m_ipcHdr, 0, sizeof( FFXIVARR_PACKET_HEADER ) );
@ -15,12 +17,12 @@ Sapphire::Network::Packets::PacketContainer::PacketContainer( uint32_t segmentTa
m_ipcHdr.count = 0;
}
Sapphire::Network::Packets::PacketContainer::~PacketContainer()
Network::Packets::PacketContainer::~PacketContainer()
{
m_entryList.clear();
}
void Sapphire::Network::Packets::PacketContainer::addPacket( Sapphire::Network::Packets::FFXIVPacketBasePtr entry )
void Network::Packets::PacketContainer::addPacket( Network::Packets::FFXIVPacketBasePtr entry )
{
m_entryList.push_back( entry );
@ -28,7 +30,7 @@ void Sapphire::Network::Packets::PacketContainer::addPacket( Sapphire::Network::
m_ipcHdr.count++;
}
void Sapphire::Network::Packets::PacketContainer::fillSendBuffer( std::vector< uint8_t >& sendBuffer )
void Network::Packets::PacketContainer::fillSendBuffer( std::vector< uint8_t >& sendBuffer )
{
std::vector< uint8_t > tempBuffer( m_ipcHdr.size );
memset( &tempBuffer[ 0 ], 0, m_ipcHdr.size );
@ -67,7 +69,7 @@ void Sapphire::Network::Packets::PacketContainer::fillSendBuffer( std::vector< u
}
std::string Sapphire::Network::Packets::PacketContainer::toString()
std::string Network::Packets::PacketContainer::toString()
{
std::vector< uint8_t > tmpBuffer;
@ -76,7 +78,7 @@ std::string Sapphire::Network::Packets::PacketContainer::toString()
std::string str = "\n";
for( uint32_t i = 0; i < m_ipcHdr.size; i++ )
{
str += Util::intToHexString( static_cast< int32_t >( tmpBuffer[ i ] & 0xFF ) ) + " ";
str += Common::Util::intToHexString( static_cast< int32_t >( tmpBuffer[ i ] & 0xFF ) ) + " ";
if( ( i + 1 ) % 16 == 0 )
str += "\n";

View file

@ -4,10 +4,8 @@
#include <Common.h>
#include <Network/CommonNetwork.h>
namespace Sapphire {
namespace Network {
namespace Packets {
namespace Server {
namespace Sapphire::Network::Packets::Server
{
/**
* Structural representation of the packet sent by the server as response
@ -31,10 +29,37 @@ struct FFXIVIpcTellErrNotFound : FFXIVIpcBasePacket< TellErrNotFound >
char receipientName[32];
};
} /* Server */
} /* Packets */
} /* Network */
} /* Sapphire */
struct FFXIVIpcFreeCompanyEvent : FFXIVIpcBasePacket< FreeCompanyEvent >
{
uint16_t unknown;
uint16_t unknown1;
uint16_t unknown2;
uint16_t unknown3;
uint16_t unknown4;
char padding[6];
uint8_t eventID;
/*
* 0x0F Login
* 0x10 Logout
*/
uint8_t padding1;
char padding2[6];
uint16_t unknown5;
char parameter[46];
/**
* eventID | parameter usage
* 0x0F FC name
* 0x10 FC name
*/
char parameter1[32];
/**
* eventID | parameter1 usage
* 0x0F Character name
* 0x10 Character name
*/
};
} /* Sapphire::Common::Network::Packets::Server */

View file

@ -43,176 +43,219 @@ namespace Sapphire::Network::Packets
*/
enum ServerZoneIpcType : uint16_t
{
Ping = 0x0219, // updated 5.35 hotfix
Init = 0x0185, // updated 5.35 hotfix
// static opcode ( the ones that rarely, if ever, change )
Ping = 0x0065,
Init = 0x0066,
ActorFreeSpawn = 0x0239, // updated 5.35 hotfix
InitZone = 0x03CD, // updated 5.35 hotfix
ActorFreeSpawn = 0x0191,
InitZone = 0x019A,
EffectResult = 0x01C2, // updated 5.35 hotfix
ActorControl = 0x02A4, // updated 5.35 hotfix
ActorControlSelf = 0x02C8, // updated 5.35 hotfix
ActorControlTarget = 0x0209, // updated 5.35 hotfix
AddStatusEffect = 0x0141,
ActorControl142 = 0x0142,
ActorControl143 = 0x0143,
ActorControl144 = 0x0144,
UpdateHpMpTp = 0x0145,
/*!
* @brief Used when resting
*/
UpdateHpMpTp = 0x0319, // updated 5.35 hotfix
///////////////////////////////////////////////////
ChatBanned = 0x006B,
Playtime = 0x006C, // updated 4.5
Logout = 0x0077, // updated 4.5
CFNotify = 0x0078,
ChatBanned = 0xF06B,
Playtime = 0x03A4, // updated 5.35 hotfix
Logout = 0x02AD, // updated 5.35 hotfix
CFNotify = 0x02C4, // updated 5.35 hotfix
CFMemberStatus = 0x0079,
CFDutyInfo = 0x007A,
CFPlayerInNeed = 0x007F,
CFPlayerInNeed = 0xF07F,
CFPreferredRole = 0x0196, // updated 5.35 hotfix
CFCancel = 0x00EC, // updated 5.35 hotfix
SocialRequestError = 0xF0AD,
SocialRequestError = 0x00AD,
CFRegistered = 0x00B8, // updated 4.1
SocialRequestResponse = 0x00BB, // updated 4.1
CFRegistered = 0x010C, // updated 5.35 hotfix
SocialRequestResponse = 0x01C7, // updated 5.35 hotfix
SocialMessage = 0x0308, // updated 5.35 hotfix
SocialMessage2 = 0x037C, // updated 5.35 hotfix
CancelAllianceForming = 0x00C6, // updated 4.2
Chat = 0x00F7, // updated 4.5?
SocialList = 0x0103, // updated 4.5
UpdateSearchInfo = 0x0106, // updated 4.5
InitSearchInfo = 0x0107, // updated 4.4
ExamineSearchComment = 0x0102, // updated 4.1
ServerNoticeShort = 0x010B, // added 4.5
ServerNotice = 0x010C, // updated 4.5
SetOnlineStatus = 0x010D, // updated 4.5
CountdownInitiate = 0x0114, // updated 4.5
CountdownCancel = 0x0115, // updated 4.5
BlackList = 0x0118, // updated 4.5
LogMessage = 0x00D0,
LinkshellList = 0x011F, // updated 4.5
Chat = 0x0349, // updated 5.35 hotfix
PartyChat = 0x0065,
MailDeleteRequest = 0x0120, // updated 4.5
ReqMoogleMailList = 0x0121, // updated 4.5
ReqMoogleMailLetter = 0x0122, // updated 4.5
MailLetterNotification = 0x0123, // updated 4.5
WorldVisitList = 0xF0FE, // added 4.5
MarketBoardItemListingCount = 0x0125, // updated 4.5
MarketBoardItemListing = 0x0126, // updated 4.5
MarketBoardItemListingHistory = 0x012A, // updated 4.5
MarketBoardSearchResult = 0x0139, // updated 4.5
SocialList = 0x0216, // updated 5.35 hotfix
ExamineSearchInfo = 0x03C3, // updated 5.35 hotfix
UpdateSearchInfo = 0x0121, // updated 5.35 hotfix
InitSearchInfo = 0x036F, // updated 5.35 hotfix
ExamineSearchComment = 0x0102, // updated 4.1
ServerNoticeShort = 0x0115, // updated 5.0
ServerNotice = 0x02F8, // updated 5.35 hotfix
SetOnlineStatus = 0x03D7, // updated 5.35 hotfix
CountdownInitiate = 0x0237, // updated 5.25
CountdownCancel = 0x00D9, // updated 5.18
PlayerAddedToBlacklist = 0x033F, // updated 5.1
PlayerRemovedFromBlacklist = 0x0385, // updated 5.1
BlackList = 0x02DB, // updated 5.35 hotfix
LinkshellList = 0x01F0, // updated 5.35 hotfix
MailDeleteRequest = 0xF12B, // updated 5.0
// 12D - 137 - constant gap between 4.5x -> 5.0
ReqMoogleMailList = 0xF138, // updated 5.0
ReqMoogleMailLetter = 0xF139, // updated 5.0
MailLetterNotification = 0x013A, // updated 5.0
MarketTaxRates = 0x01F8, // updated 5.35 hotfix
MarketBoardSearchResult = 0x032C, // updated 5.35 hotfix
MarketBoardItemListingCount = 0x038F, // updated 5.35 hotfix
MarketBoardItemListingHistory = 0x0186, // updated 5.35 hotfix
MarketBoardItemListing = 0x025F, // updated 5.35 hotfix
CharaFreeCompanyTag = 0x013B, // updated 4.5
FreeCompanyBoardMsg = 0x013C, // updated 4.5
FreeCompanyInfo = 0x013D, // updated 4.5
ExamineFreeCompanyInfo = 0x013E, // updated 4.5
FreeCompanyInfo = 0xF13D, // updated 4.5
ExamineFreeCompanyInfo = 0xF13E, // updated 4.5
StatusEffectList = 0x0151, // updated 4.5
Effect = 0x0154, // updated 4.5
AoeEffect8 = 0x0157, // updated 4.5
AoeEffect16 = 0x0158, // updated 4.5
AoeEffect24 = 0x0159, // updated 4.5
AoeEffect32 = 0x015A, // updated 4.5
PersistantEffect = 0x015B, // updated 4.5
FreeCompanyUpdateShortMessage = 0xF157, // added 5.0
GCAffiliation = 0x0165, // updated 4.5
StatusEffectList = 0x0382, // updated 5.35 hotfix
EurekaStatusEffectList = 0x0167, // updated 5.18
BossStatusEffectList = 0x0312, // added 5.1
Effect = 0x0192, // updated 5.35 hotfix
AoeEffect8 = 0x012C, // updated 5.35 hotfix
AoeEffect16 = 0x03BF, // updated 5.3
AoeEffect24 = 0x027E, // updated 5.3
AoeEffect32 = 0x017E, // updated 5.3
PersistantEffect = 0x0317, // updated 5.35 hotfix
PlayerSpawn = 0x0175, // updated 4.5
NpcSpawn = 0x0176, // updated 4.5
NpcSpawn2 = 0x0177, // ( Bigger statuseffectlist? ) updated 4.5
ActorMove = 0x0178, // updated 4.5
GCAffiliation = 0xF16F, // updated 5.0
ActorSetPos = 0x017A, // updated 4.5
PlayerSpawn = 0x0179, // updated 5.35 hotfix
NpcSpawn = 0x03A8, // updated 5.35 hotfix
NpcSpawn2 = 0x01CB, // ( Bigger statuseffectlist? ) updated 5.3
ActorMove = 0x01BF, // updated 5.35 hotfix
ActorCast = 0x017C, // updated 4.5
ActorSetPos = 0x03DF, // updated 5.35 hotfix
PartyList = 0x017E, // updated 4.5
ActorCast = 0x0302, // updated 5.35 hotfix
SomeCustomiseChangePacketProbably = 0x00CD, // added 5.18
HateList = 0x0180, // updated 4.5
ObjectSpawn = 0x0181, // updated 4.5
ObjectDespawn = 0x0182, // updated 4.5
UpdateClassInfo = 0x0183, // updated 4.5
SilentSetClassJob = 0x0184, // updated 4.5 - seems to be the case, not sure if it's actually used for anything
InitUI = 0x0185, // updated 4.5
PlayerStats = 0x0186, // updated 4.5
ActorOwner = 0x0187, // updated 4.5
PlayerStateFlags = 0x0188, // updated 4.5
PlayerClassInfo = 0x0189, // updated 4.5
PartyList = 0x02B2, // updated 5.35 hotfix
PartyMessage = 0x00AE, // updated 5.35 hotfix
HateRank = 0x02CC, // updated 5.35 hotfix
HateList = 0x0198, // updated 5.35 hotfix
ObjectSpawn = 0x02B8, // updated 5.35 hotfix
ObjectDespawn = 0xF34B, // updated 5.18
UpdateClassInfo = 0x0235, // updated 5.35 hotfix
SilentSetClassJob = 0x018E, // updated 5.0 - seems to be the case, not sure if it's actually used for anything
PlayerSetup = 0x0290, // updated 5.35 hotfix
PlayerStats = 0x023B, // updated 5.35 hotfix
ActorOwner = 0x00E8, // updated 5.35 hotfix
PlayerStateFlags = 0x00F8, // updated 5.35 hotfix
PlayerClassInfo = 0x02C3, // updated 5.35 hotfix
CharaVisualEffect = 0x02E2, // updated 5.35 hotfix
ModelEquip = 0x018B, // updated 4.5
Examine = 0x018C, // updated 4.5
CharaNameReq = 0x018D, // updated 4.5
ModelEquip = 0x0277, // updated 5.35 hotfix
Examine = 0x00BC, // updated 5.35 hotfix
CharaNameReq = 0x008E, // updated 5.35 hotfix
// nb: see #565 on github
UpdateRetainerItemSalePrice = 0xF19F, // updated 5.0
RetainerSaleHistory = 0x020E, // updated 5.21 hotfix
RetainerInformation = 0x01F9, // updated 5.35 hotfix
SetLevelSync = 0x1186, // not updated for 4.4, not sure what it is anymore
ItemInfo = 0x0196, // updated 4.5
ContainerInfo = 0x0197, // updated 4.5
InventoryTransactionFinish = 0x0198, // updated 4.5
InventoryTransaction = 0x0199, // updated 4.5
ItemInfo = 0x0214, // updated 5.35 hotfix
ContainerInfo = 0x00C5, // updated 5.35 hotfix
InventoryTransactionFinish = 0x02F0, // updated 5.35 hotfix
InventoryTransaction = 0x01FD, // updated 5.35 hotfix
CurrencyCrystalInfo = 0x0379, // updated 5.35 hotfix
CurrencyCrystalInfo = 0x019B, // updated 4.5
InventoryActionAck = 0x03E4, // updated 5.35 hotfix
UpdateInventorySlot = 0x036A, // updated 5.35 hotfix
InventoryActionAck = 0x019D, // updated 4.5
UpdateInventorySlot = 0x019E, // updated 4.5
HuntingLogEntry = 0x0146, // updated 5.35 hotfix
HuntingLogEntry = 0x01A9, // added 4.5
EventPlay = 0x00F3, // updated 5.35 hotfix
EventPlay4 = 0x00AC, // updated 5.35 hotfix
EventPlay8 = 0x023F, // updated 5.35 hotfix
EventPlay16 = 0x025B, // updated 5.35 hotfix
EventPlay32 = 0x029A, // updated 5.35 hotfix
EventPlay64 = 0x02C1, // updated 5.35 hotfix
EventPlay128 = 0x038A, // updated 5.35 hotfix
EventPlay255 = 0x034B, // updated 5.35 hotfix
EventPlay = 0x01AB, // updated 4.5
DirectorPlayScene = 0x01AF, // updated 4.5
EventOpenGilShop = 0x01B2, // updated 4.5
EventStart = 0x01B4, // updated 4.5
EventFinish = 0x01B5, // updated 4.5
EventStart = 0x009A, // updated 5.35 hotfix
EventFinish = 0x007E, // updated 5.35 hotfix
EventLinkshell = 0x1169,
QuestActiveList = 0x01C8, // updated 4.5
QuestUpdate = 0x01C9, // updated 4.5
QuestCompleteList = 0x01CA, // updated 4.5
QuestActiveList = 0x0117, // updated 5.35 hotfix
QuestUpdate = 0x0073, // updated 5.35 hotfix
QuestCompleteList = 0x0240, // updated 5.35 hotfix
QuestFinish = 0x01CB, // updated 4.5
MSQTrackerComplete = 0x01CC, // updated 4.5
QuestFinish = 0x00E9, // updated 5.35 hotfix
MSQTrackerComplete = 0xF1D6, // updated 5.0
MSQTrackerProgress = 0xF1CD, // updated 4.5 ? this actually looks like the two opcodes have been combined, see #474
QuestMessage = 0x01D3, // updated 4.5
QuestMessage = 0x0381, // updated 5.35 hotfix
QuestTracker = 0x01D8, // updated 4.5
QuestTracker = 0x018B, // updated 5.35 hotfix
Mount = 0x01E8, // updated 4.5
Mount = 0x01B5, // updated 5.35 hotfix
DirectorVars = 0x01EA, // updated 4.5
DirectorPopUp = 0x01F5, // display dialogue pop-ups in duties and FATEs, for example, Teraflare's countdown
DirectorVars = 0x00E6, // updated 5.18
SomeDirectorUnk1 = 0x0084, // updated 5.18
SomeDirectorUnk2 = 0xF0C1, // updated 5.18
SomeDirectorUnk4 = 0x0202, // updated 5.35 hotfix
SomeDirectorUnk8 = 0x028A, // updated 5.18
SomeDirectorUnk16 = 0x028C, // updated 5.18
DirectorPopUp = 0xF162, // updated 5.18 - display dialogue pop-ups in duties and FATEs, for example, Teraflare's countdown
DirectorPopUp4 = 0x0214, // updated 5.18
DirectorPopUp8 = 0x00F8, // updated 5.18
CFAvailableContents = 0xF1FD, // updated 4.2
WeatherChange = 0x0205, // updated 4.5
PlayerTitleList = 0x0206, // updated 4.5?
Discovery = 0x0207, // updated 4.5?
WeatherChange = 0x027B, // updated 5.35 hotfix
PlayerTitleList = 0x037D, // updated 5.1
Discovery = 0x031B, // updated 5.35 hotfix
EorzeaTimeOffset = 0x0209, // updated 4.5
EorzeaTimeOffset = 0xF3B8, // updated 5.1
EquipDisplayFlags = 0x0215, // updated 4.5
EquipDisplayFlags = 0x00BE, // updated 5.35 hotfix
MiniCactpotInit = 0x0286, // added 5.31
ShopMessage = 0x0197, // updated 5.35 hotfix
LootMessage = 0x01B7, // updated 5.35 hotfix
/// Housing //////////////////////////////////////
LandSetInitialize = 0x0229, // updated 4.5
LandUpdate = 0x022A, // updated 4.5
YardObjectSpawn = 0x022B, // updated 4.5
HousingIndoorInitialize = 0x022C, // updated 4.5
LandPriceUpdate = 0x022D, // updated 4.5
LandInfoSign = 0x022E, // updated 4.5
LandRename = 0x022F, // updated 4.5
HousingEstateGreeting = 0x0230, // updated 4.5
HousingUpdateLandFlagsSlot = 0x0231, // updated 4.5
HousingLandFlags = 0x0232, // updated 4.5
HousingShowEstateGuestAccess = 0x0233, // updated 4.5
LandSetInitialize = 0x0234, // updated 5.0
LandUpdate = 0x0235, // updated 5.0
YardObjectSpawn = 0xF236, // updated 5.0
HousingIndoorInitialize = 0x0237, // updated 5.0
LandPriceUpdate = 0x0238, // updated 5.0
LandInfoSign = 0x023D, // updated 5.35 hotfix
LandRename = 0x023A, // updated 5.0
HousingEstateGreeting = 0x023B, // updated 5.0
HousingUpdateLandFlagsSlot = 0x023C, // updated 5.0
HousingLandFlags = 0x022F, // updated 5.35 hotfix
HousingShowEstateGuestAccess = 0x023E, // updated 5.0
HousingObjectInitialize = 0x0235, // updated 4.45
HousingInternalObjectSpawn = 0x236, // updated 4.5
HousingObjectInitialize = 0x01AA, // updated 5.35 hotfix
HousingInternalObjectSpawn = 0xF241, // updated 5.0
HousingWardInfo = 0x0238, // updated 4.5
HousingObjectMove = 0x0239, // updated 4.5
HousingWardInfo = 0x02FD, // updated 5.35 hotfix
HousingObjectMove = 0xF244, // updated 5.0
SharedEstateSettingsResponse = 0x0245, // updated 4.5
@ -225,16 +268,15 @@ namespace Sapphire::Network::Packets
DuelChallenge = 0x0277, // 4.2; this is responsible for opening the ui
PerformNote = 0x0286, // updated 4.3
PrepareZoning = 0x0299, // updated 4.5
ActorGauge = 0x0292, // updated 4.3
PrepareZoning = 0x026C, // updated 5.35 hotfix
ActorGauge = 0x0112, // updated 5.35 hotfix
// Unknown IPC types that still need to be sent
// TODO: figure all these out properly
IPCTYPE_UNK_320 = 0x0253, // updated 4.5
IPCTYPE_UNK_322 = 0x0255, // updated 4.5
// daily quest info -> without them sent, login will take longer...
DailyQuests = 0x0139, // updated 5.35 hotfix
DailyQuestRepeatFlags = 0x024C, // updated 5.35 hotfix
/// Doman Mahjong //////////////////////////////////////
MahjongOpenGui = 0x02BC, // only available in mahjong instance
MahjongOpenGui = 0x02A4, // only available in mahjong instance
MahjongNextRound = 0x02BD, // initial hands(baipai), # of riichi(wat), winds, honba, score and stuff
MahjongPlayerAction = 0x02BE, // tsumo(as in drawing a tile) called chi/pon/kan/riichi
MahjongEndRoundTsumo = 0x02BF, // called tsumo
@ -251,37 +293,43 @@ namespace Sapphire::Network::Packets
*/
enum ClientZoneIpcType : uint16_t
{
PingHandler = 0x0219, // updated 5.35 hotfix
InitHandler = 0x0185, // updated 5.35 hotfix
PingHandler = 0x0065, // unchanged 4.5
InitHandler = 0x0066, // unchanged 4.5
FinishLoadingHandler = 0x01BE, // updated 5.35 hotfix
FinishLoadingHandler = 0x0069, // unchanged 4.5
CFCommenceHandler = 0x0118, // updated 5.35 hotfix
CFCommenceHandler = 0x006F,
CFRegisterDuty = 0x0071,
CFRegisterRoulette = 0x0072,
PlayTimeHandler = 0x0073, // unchanged 4.5
LogoutHandler = 0x0074, // unchanged 4.5
CFCancelHandler = 0x0332, // updated 5.35 hotfix
CFRegisterDuty = 0x0289, // updated 5.35 hotfix
CFRegisterRoulette = 0x0088, // updated 5.35 hotfix
PlayTimeHandler = 0x02A8, // updated 5.35 hotfix
LogoutHandler = 0x00EC, // updated 5.35 hotfix
CancelLogout = 0x03DB, // updated 5.35 hotfix
CFDutyInfoHandler = 0x0078, // updated 4.2
SocialReqSendHandler = 0x00AE, // updated 4.1
SocialReqSendHandler = 0x0387, // updated 5.35 hotfix
SocialResponseHandler = 0x028D, // updated 5.35 hotfix
CreateCrossWorldLS = 0x00AF, // updated 4.3
ChatHandler = 0x00D7, // updated 4.5
ChatHandler = 0x0131, // updated 5.35 hotfix
PartyChatHandler = 0x0065,
PartySetLeaderHandler = 0x0208, // updated 5.35 hotfix
LeavePartyHandler = 0x0337, // updated 5.35 hotfix
KickPartyMemberHandler = 0x014C, // updated 5.35 hotfix
DisbandPartyHandler = 0x0205, // updated 5.35 hotfix
SocialListHandler = 0x00DF, // updated 4.5
ReqSearchInfoHandler = 0x00E4, // updated 4.5
ReqExamineSearchCommentHandler = 0x00E5, // updated 4.5
SocialListHandler = 0x0340, // updated 5.35 hotfix
SetSearchInfoHandler = 0x0314, // updated 5.35 hotfix
ReqSearchInfoHandler = 0x01E9, // updated 5.35 hotfix
ReqExamineSearchCommentHandler = 0x00E7, // updated 5.0
SetSearchInfoHandler = 0x00E2, // unchanged 4.5
ReqRemovePlayerFromBlacklist = 0x00F1, // updated 5.0
BlackListHandler = 0x0079, // updated 5.35 hotfix
PlayerSearchHandler = 0x00F4, // updated 5.0
BlackListHandler = 0x00F0, // updated 4.5
PlayerSearchHandler = 0x00E6, // updated 4.5
LinkshellListHandler = 0x00F8, // updated 4.5
LinkshellListHandler = 0x024B, // updated 5.35 hotfix
MarketBoardRequestItemListingInfo = 0x0102, // updated 4.5
MarketBoardRequestItemListings = 0x0103, // updated 4.5
@ -291,58 +339,63 @@ namespace Sapphire::Network::Packets
FcInfoReqHandler = 0x011A, // updated 4.2
FreeCompanyUpdateShortMessageHandler = 0x0123, // added 5.0
ReqMarketWishList = 0x012C, // updated 4.3
ReqJoinNoviceNetwork = 0x0129, // updated 4.2
ReqCountdownInitiate = 0x0133, // updated 4.5
ReqCountdownCancel = 0x0134, // updated 4.5
ClearWaymarks = 0x0135, // updated 4.5
ReqCountdownInitiate = 0x009A, // updated 5.25
ReqCountdownCancel = 0x0244, // updated 5.25
ZoneLineHandler = 0x0137, // updated 4.5
ClientTrigger = 0x0138, // updated 4.5
DiscoveryHandler = 0x0139, // updated 4.5
ZoneLineHandler = 0x0279, // updated 5.35 hotfix
ClientTrigger = 0x03D3, // updated 5.35 hotfix
DiscoveryHandler = 0x00E3, // updated 5.35 hotfix
AddWaymark = 0x013A, // updated 4.5
PlaceFieldMarkerPreset = 0x023F, // updated 5.25
PlaceFieldMarker = 0x01BA, // updated 5.25
SkillHandler = 0x01CD, // updated 5.35 hotfix
GMCommand1 = 0x02AC, // updated 5.35 hotfix
GMCommand2 = 0x029F, // updated 5.35 hotfix
AoESkillHandler = 0x030C, // updated 5.35 hotfix
SkillHandler = 0x013B, // updated 4.5
GMCommand1 = 0x013C, // updated 4.5
GMCommand2 = 0x013D, // updated 4.5
AoESkillHandler = 0x13E, // updated 4.5
UpdatePositionHandler = 0x0236, // updated 5.35 hotfix
UpdatePositionHandler = 0x013F, // updated 4.5
UpdatePositionInstance = 0x0183, // updated 4.3
InventoryModifyHandler = 0x0135, // updated 5.35 hotfix
InventoryModifyHandler = 0x0146, // updated 4.5 ( +4 )
InventoryEquipRecommendedItems = 0x0149, // updated 5.0
ReqPlaceHousingItem = 0x149, // updated 4.5
ReqPlaceHousingItem = 0x014B, // updated 5.0
BuildPresetHandler = 0x0150, // updated 5.0
BuildPresetHandler = 0x014E, // updated 4.5
TalkEventHandler = 0x014F, // updated 4.5
EmoteEventHandler = 0x0150, // updated 4.5
WithinRangeEventHandler = 0x0151, // updated 4.5
OutOfRangeEventHandler = 0x0152, // updated 4.5
EnterTeriEventHandler = 0x0153, // updated 4.5
TalkEventHandler = 0x02A4, // updated 5.35 hotfix
EmoteEventHandler = 0x02C8, // updated 5.35 hotfix
WithinRangeEventHandler = 0x0209, // updated 5.35 hotfix
OutOfRangeEventHandler = 0x0319, // updated 5.35 hotfix
EnterTeriEventHandler = 0x0192, // updated 5.35 hotfix
ShopEventHandler = 0x0156, // updated 5.0
ShopEventHandler = 0x0155, // updated 4.5
ReturnEventHandler = 0x0158, // updated 4.5
TradeReturnEventHandler = 0x0159, // updated 4.5
ReturnEventHandler = 0x02B4, // updated 5.35 hotfix
TradeReturnEventHandler = 0x00A4, // updated 5.35 hotfix
TradeMultipleReturnEventHander = 0x035C, // updated 5.35 hotfix
LinkshellEventHandler = 0x016B, // updated 4.5
LinkshellEventHandler1 = 0x016C, // updated 4.5
LandRenameHandler = 0x0175, // updated 4.5
HousingUpdateHouseGreeting = 0x0176, // updated 4.5
HousingUpdateObjectPosition = 0x0177, // updated 4.5
ReqEquipDisplayFlagsChange = 0x02F6, // updated 5.35 hotfix
SetSharedEstateSettings = 0x017B, // updated 4.5
LandRenameHandler = 0xF177, // updated 5.0
HousingUpdateHouseGreeting = 0x0178, // updated 5.0
HousingUpdateObjectPosition = 0x0159, // updated 5.25
SetSharedEstateSettings = 0x017B, // updated 5.0
UpdatePositionInstance = 0x0345, // updated 5.35 hotfix
PerformNoteHandler = 0x029B, // updated 4.3
ReqEquipDisplayFlagsChange = 0x0173, // updated 4.5
WorldInteractionHandler = 0x00A9, // updated 5.35 hotfix
Dive = 0x02CC, // updated 5.35 hotfix
};
////////////////////////////////////////////////////////////////////////////////
@ -354,6 +407,8 @@ namespace Sapphire::Network::Packets
{
Tell = 0x0064, // updated for sb
TellErrNotFound = 0x0066,
FreeCompanyEvent = 0x012C, // added 5.0
};
/**

View file

@ -4,10 +4,7 @@
#include <Common.h>
#include <Network/CommonNetwork.h>
namespace Sapphire {
namespace Network {
namespace Packets {
namespace Server {
namespace Sapphire::Network::Packets::Server {
struct FFXIVIpcRetainerList :
FFXIVIpcBasePacket< LobbyRetainerList >
@ -152,7 +149,5 @@ struct FFXIVIpcLobbyError : FFXIVIpcBasePacket< LobbyError >
};
}
}
}
}
#endif

View file

@ -4,10 +4,8 @@
#include <Common.h>
#include <Network/CommonNetwork.h>
namespace Sapphire {
namespace Network {
namespace Packets {
namespace Client {
namespace Sapphire::Network::Packets::Client
{
struct FFXIVIpcGmCommand1 :
FFXIVIpcBasePacket< GMCommand1 >
@ -51,15 +49,26 @@ struct FFXIVIpcUpdatePosition :
FFXIVIpcBasePacket< UpdatePositionHandler >
{
/* 0000 */ float rotation;
/* 0004 */ uint8_t unk_1[ 3 ];
/* 0004 */ uint8_t animationType;
/* 0005 */ uint8_t animationState;
/* 0006 */ uint8_t clientAnimationType;
/* 0007 */ uint8_t headPosition;
/* 0008 */ uint8_t animationType;
/* 0009 */ uint8_t animationState;
/* 000A */ uint8_t clientAnimationType;
/* 000B */ uint8_t unk_2;
/* 000C */ Common::FFXIVARR_POSITION3 position;
/* 0008 */ Common::FFXIVARR_POSITION3 position;
/* 000C */ uint8_t unk[ 4 ]; // padding?
};
struct FFXIVIpcUpdatePositionInstance :
FFXIVIpcBasePacket< UpdatePositionInstance >
{
/* 0000 */ float rotation;
/* 0004 */ float interpolateRotation;
/* 0008 */ uint32_t flags;
/* 000C */ Common::FFXIVARR_POSITION3 position;
/* 0018 */ Common::FFXIVARR_POSITION3 interpolatePosition;
/* 0024 */ uint32_t unknown;
};
struct FFXIVIpcSkillHandler :
FFXIVIpcBasePacket< SkillHandler >
{
@ -198,6 +207,13 @@ struct FFXIVIpcChatHandler :
/* 001A */ char message[1012];
};
struct FFXIVIpcPartyChatHandler :
FFXIVIpcBasePacket< ChatHandler >
{
uint64_t unknown;
char message[1024];
};
struct FFXIVIpcShopEventHandler :
FFXIVIpcBasePacket< ShopEventHandler >
{
@ -219,7 +235,7 @@ struct FFXIVIpcInventoryModifyHandler :
{
/* 0000 */ uint32_t seq;
/* 0004 */ Common::InventoryOperation action;
/* 0005 */ uint8_t pad_0005[7];
/* 0006 */ uint8_t pad_0006[6];
/* 000C */ uint16_t fromContainer;
/* 000E */ uint8_t pad_000E[2];
/* 0010 */ uint8_t fromSlot;
@ -325,9 +341,91 @@ struct FFXIVIpcMarketBoardRequestItemListingInfo :
/* 0000 */ uint32_t requestId;
};
}
}
}
struct FFXIVIpcFreeCompanyUpdateShortMessageHandler :
FFXIVIpcBasePacket< FreeCompanyUpdateShortMessageHandler >
{
char shortMessage[104];
uint8_t padding;
uint8_t unknown;
uint32_t unknown1;
uint16_t unknown2;
};
struct FFXIVIpcWorldInteractionHandler :
FFXIVIpcBasePacket< WorldInteractionHandler >
{
uint32_t action;
uint32_t param1;
uint32_t param2;
uint32_t param3;
uint32_t param4;
Common::FFXIVARR_POSITION3 position;
};
struct FFXIVIpcSocialReqSendHandler :
FFXIVIpcBasePacket< SocialReqSendHandler >
{
uint64_t unknown;
uint8_t p1;
uint8_t p2;
uint8_t socialType;
char name[32];
uint8_t padding[5];
};
struct FFXIVIpcSocialResponseHandler :
FFXIVIpcBasePacket< SocialResponseHandler >
{
uint64_t contentId;
uint8_t p1;
uint8_t p2;
uint8_t socialType;
uint8_t response;
uint32_t unknown;
};
struct FFXIVIpcPartySetLeaderHandler :
FFXIVIpcBasePacket< PartySetLeaderHandler >
{
uint64_t contentId;
uint8_t p1;
uint8_t p2;
char name[32];
uint8_t padding[6];
};
struct FFXIVIpcLeavePartyHandler :
FFXIVIpcBasePacket< LeavePartyHandler >
{
uint64_t empty;
};
struct FFXIVIpcKickPartyMemberHander :
FFXIVIpcBasePacket< KickPartyMemberHandler >
{
uint64_t contentId;
uint8_t p1;
uint8_t p2;
char name[32];
uint8_t padding[6];
};
struct FFXIVIpcDisbandPartyHandler :
FFXIVIpcBasePacket< DisbandPartyHandler >
{
uint64_t empty;
};
struct FFXIVIpcDive :
FFXIVIpcBasePacket< Dive >
{
float unknown;
Common::FFXIVARR_POSITION3 posTarget;
Common::FFXIVARR_POSITION3 posOriginal;
uint32_t padding;
};
}
#endif //_CORE_NETWORK_PACKETS_ZONE_CLIENT_IPC_H

File diff suppressed because it is too large Load diff

115
src/common/Service.h Normal file
View file

@ -0,0 +1,115 @@
#ifndef SAPPHIRE_SERVICE_H
#define SAPPHIRE_SERVICE_H
#include <memory>
#include <utility>
#include <cassert>
// stolen from: https://github.com/skypjack/entt/blob/master/src/entt/locator/locator.hpp
namespace Sapphire::Common
{
/**
* @brief Service locator, nothing more.
*
* A service locator can be used to do what it promises: locate services.<br/>
* Usually service locators are tightly bound to the services they expose and
* thus it's hard to define a general purpose class to do that. This template
* based implementation tries to fill the gap and to get rid of the burden of
* defining a different specific locator for each application.
*
* @tparam SvcType Type of service managed by the locator.
*/
template< typename SvcType >
struct Service
{
/*! @brief Type of service offered. */
using ServiceType = SvcType;
/*! @brief Default constructor, deleted on purpose. */
Service() = delete;
/*! @brief Default destructor, deleted on purpose. */
~Service() = delete;
/**
* @brief Tests if a valid service implementation is set.
* @return True if the service is set, false otherwise.
*/
static bool empty() noexcept
{
return !static_cast< bool >( service );
}
/**
* @brief Returns a weak pointer to a service implementation, if any.
*
* Clients of a service shouldn't retain references to it. The recommended
* way is to retrieve the service implementation currently set each and
* every time the need of using it arises. Otherwise users can incur in
* unexpected behaviors.
*
* @return A reference to the service implementation currently set, if any.
*/
static std::weak_ptr< SvcType > get() noexcept
{
return service;
}
/**
* @brief Returns a weak reference to a service implementation, if any.
*
* Clients of a service shouldn't retain references to it. The recommended
* way is to retrieve the service implementation currently set each and
* every time the need of using it arises. Otherwise users can incur in
* unexpected behaviors.
*
* @warning
* In case no service implementation has been set, a call to this function
* results in undefined behavior.
*
* @return A reference to the service implementation currently set, if any.
*/
static SvcType& ref() noexcept
{
return *service;
}
/**
* @brief Sets or replaces a service.
* @tparam Impl Type of the new service to use.
* @tparam Args Types of arguments to use to construct the service.
* @param args Parameters to use to construct the service.
*/
template< typename Impl = SvcType, typename... Args >
static void set( Args&& ... args )
{
service = std::make_shared< Impl >( std::forward< Args >( args )... );
}
/**
* @brief Sets or replaces a service.
* @param ptr Service to use to replace the current one.
*/
static void set( std::shared_ptr< SvcType > ptr )
{
assert( static_cast< bool >( ptr ) );
service = std::move( ptr );
}
/**
* @brief Resets a service.
*
* The service is no longer valid after a reset.
*/
static void reset()
{
service.reset();
}
private:
inline static std::shared_ptr< SvcType > service = nullptr;
};
}
#endif //SAPPHIRE_SERVICE_H

View file

@ -7,18 +7,26 @@
#include <execinfo.h>
#include <cxxabi.h>
#else
#include <stackwalker/StackWalker.h>
class SapphireStackWalker : public StackWalker
#include <windows.h>
#include <intrin.h>
#include <dbghelp.h>
#pragma comment(lib, "dbghelp.lib")
inline std::string basename( const std::string& file )
{
public:
SapphireStackWalker() : StackWalker() {}
protected:
virtual void OnOutput( LPCSTR szText )
size_t i = file.find_last_of( "\\/" );
if ( i == std::string::npos )
{
Sapphire::Logger::fatal( "{}", szText );
return file;
}
};
else
{
return file.substr( i + 1 );
}
}
#endif
using namespace Sapphire::Common;
@ -148,8 +156,74 @@ void Util::CrashHandler::printStackTrace( unsigned int max_frames )
#else
SapphireStackWalker sw;
sw.ShowCallstack();
DWORD machine = IMAGE_FILE_MACHINE_AMD64;
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
CONTEXT context = {};
context.ContextFlags = CONTEXT_FULL;
RtlCaptureContext( &context );
SymInitialize( process, NULL, TRUE );
SymSetOptions( SYMOPT_LOAD_LINES );
STACKFRAME frame = {};
frame.AddrPC.Offset = context.Rip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Rbp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Rsp;
frame.AddrStack.Mode = AddrModeFlat;
while( StackWalk( machine, process, thread, &frame, &context, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL ) )
{
auto moduleBase = SymGetModuleBase( process, frame.AddrPC.Offset );
std::string moduleName;
std::string funcName;
std::string fileName;
int lineNum = 0;
char moduelBuff[MAX_PATH];
if( moduleBase && GetModuleFileNameA( ( HINSTANCE ) moduleBase, moduelBuff, MAX_PATH ) )
{
moduleName = basename( moduelBuff );
}
else
{
moduleName = "Unknown Module";
}
DWORD64 offset = 0;
char symbolBuffer[sizeof( IMAGEHLP_SYMBOL ) + 255];
PIMAGEHLP_SYMBOL symbol = ( PIMAGEHLP_SYMBOL ) symbolBuffer;
symbol->SizeOfStruct = ( sizeof IMAGEHLP_SYMBOL ) + 255;
symbol->MaxNameLength = 254;
if( SymGetSymFromAddr( process, frame.AddrPC.Offset, &offset, symbol ) )
{
funcName = symbol->Name;
}
else
{
funcName = "Unknown Function";
}
IMAGEHLP_LINE line;
line.SizeOfStruct = sizeof( IMAGEHLP_LINE );
DWORD offset_ln = 0;
if( SymGetLineFromAddr( process, frame.AddrPC.Offset, &offset_ln, &line ) )
{
fileName = line.FileName;
lineNum = line.LineNumber;
}
Logger::fatal( "[{:x}] {}({}): {} ({})", frame.AddrPC.Offset, fileName, lineNum, funcName, moduleName );
}
SymCleanup( process );
#endif
}

Some files were not shown because too many files have changed in this diff Show more