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:
commit
a9e6c85a5e
371 changed files with 32780 additions and 21115 deletions
|
@ -1,5 +1,5 @@
|
||||||
os:
|
os:
|
||||||
- Visual Studio 2017
|
- Visual Studio 2019
|
||||||
|
|
||||||
configuration:
|
configuration:
|
||||||
- Debug
|
- Debug
|
||||||
|
@ -20,8 +20,8 @@ before_build:
|
||||||
- git submodule update --init
|
- git submodule update --init
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- cmake .. -G "Visual Studio 15 2017 Win64"
|
- cmake .. -G "Visual Studio 16 2019" -A x64
|
||||||
- cmake --build . --target ALL_BUILD --config Release
|
- cmake --build . --target ALL_BUILD --config RelWithDebInfo
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- cd bin
|
- cd bin
|
||||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -7,3 +7,6 @@
|
||||||
[submodule "deps/recastnavigation"]
|
[submodule "deps/recastnavigation"]
|
||||||
path = deps/recastnavigation
|
path = deps/recastnavigation
|
||||||
url = https://github.com/SapphireServer/recastnavigation
|
url = https://github.com/SapphireServer/recastnavigation
|
||||||
|
[submodule "deps/ffxiv-actions"]
|
||||||
|
path = deps/ffxiv-actions
|
||||||
|
url = https://github.com/SapphireServer/ffxiv-actions.git
|
||||||
|
|
|
@ -14,9 +14,10 @@ matrix:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
packages:
|
packages:
|
||||||
- g++-7
|
- g++-8
|
||||||
env:
|
env:
|
||||||
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
|
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
|
||||||
|
- CXX=g++-8
|
||||||
|
|
||||||
# Setup cache
|
# Setup cache
|
||||||
cache:
|
cache:
|
||||||
|
|
|
@ -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}/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}/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_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 #
|
# Dependencies and compiler settings #
|
||||||
|
@ -44,7 +46,6 @@ add_subdirectory( "deps/MySQL" )
|
||||||
add_subdirectory( "deps/datReader" )
|
add_subdirectory( "deps/datReader" )
|
||||||
add_subdirectory( "deps/mysqlConnector" )
|
add_subdirectory( "deps/mysqlConnector" )
|
||||||
add_subdirectory( "deps/recastnavigation" )
|
add_subdirectory( "deps/recastnavigation" )
|
||||||
add_subdirectory( "deps/stackwalker" )
|
|
||||||
|
|
||||||
##############################
|
##############################
|
||||||
# Main Sapphire Components #
|
# Main Sapphire Components #
|
||||||
|
|
|
@ -1,21 +1,32 @@
|
||||||
{
|
{
|
||||||
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
|
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
|
||||||
|
"environments": [
|
||||||
|
{
|
||||||
|
"BuildDir": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build"
|
||||||
|
}
|
||||||
|
],
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "x64-Debug",
|
"name": "x64-Debug",
|
||||||
"generator": "Visual Studio 15 2017 Win64",
|
"generator": "Visual Studio 16 2019 Win64",
|
||||||
"configurationType": "Debug",
|
"configurationType": "Debug",
|
||||||
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
|
"buildRoot": "${env.BuildDir}\\${name}",
|
||||||
"cmakeCommandArgs": "-DCMAKE_BUILD_TYPE=\"Debug\"",
|
"cmakeCommandArgs": "-DCMAKE_BUILD_TYPE=\"Debug\"",
|
||||||
"buildCommandArgs": "-m -v:minimal"
|
"buildCommandArgs": "-m -v:minimal",
|
||||||
|
"inheritEnvironments": [
|
||||||
|
"msvc_x64"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "x64-Release",
|
"name": "x64-Release",
|
||||||
"generator": "Visual Studio 15 2017 Win64",
|
"generator": "Visual Studio 16 2019 Win64",
|
||||||
"configurationType": "Release",
|
"configurationType": "Release",
|
||||||
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
|
"buildRoot": "${env.BuildDir}\\${name}",
|
||||||
"cmakeCommandArgs": "",
|
"cmakeCommandArgs": "-DCMAKE_BUILD_TYPE=\"RelWithDebInfo\"",
|
||||||
"buildCommandArgs": "-m -v:minimal"
|
"buildCommandArgs": "-m -v:minimal",
|
||||||
|
"inheritEnvironments": [
|
||||||
|
"msvc_x64"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ Sapphire requires the following software:
|
||||||
|
|
||||||
| *Name* | *Windows* | *Linux* |
|
| *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 |
|
| 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.
|
Please check the [wiki](https://github.com/SapphireMordred/Sapphire/wiki) for detailed installation/build instructions for your OS.
|
||||||
|
|
|
@ -60,6 +60,7 @@ if( UNIX )
|
||||||
else( MYSQL_CONFIG )
|
else( MYSQL_CONFIG )
|
||||||
set(MYSQL_ADD_LIBRARIES "")
|
set(MYSQL_ADD_LIBRARIES "")
|
||||||
list(APPEND MYSQL_ADD_LIBRARIES "mysqlclient_r")
|
list(APPEND MYSQL_ADD_LIBRARIES "mysqlclient_r")
|
||||||
|
list(APPEND MYSQL_ADD_LIBRARIES "mariadbclient")
|
||||||
endif( MYSQL_CONFIG )
|
endif( MYSQL_CONFIG )
|
||||||
endif( UNIX )
|
endif( UNIX )
|
||||||
|
|
||||||
|
@ -76,6 +77,7 @@ find_path(MYSQL_INCLUDE_DIR
|
||||||
PATHS
|
PATHS
|
||||||
${MYSQL_ADD_INCLUDE_PATH}
|
${MYSQL_ADD_INCLUDE_PATH}
|
||||||
/usr/include
|
/usr/include
|
||||||
|
/usr/include/mariadb
|
||||||
/usr/include/mysql
|
/usr/include/mysql
|
||||||
/usr/local/include
|
/usr/local/include
|
||||||
/usr/local/include/mysql
|
/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/MySQL Server 5.7/include"
|
||||||
"${PROGRAM_FILES_64}/MySQL/include"
|
"${PROGRAM_FILES_64}/MySQL/include"
|
||||||
"${PROGRAM_FILES_64}/MariaDB 10.3/include/mysql"
|
"${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"
|
"C:/MySQL/include"
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/include"
|
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/include"
|
||||||
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.7/include"
|
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.7/include"
|
||||||
|
@ -97,7 +101,7 @@ if( UNIX )
|
||||||
foreach(LIB ${MYSQL_ADD_LIBRARIES})
|
foreach(LIB ${MYSQL_ADD_LIBRARIES})
|
||||||
find_library( MYSQL_LIBRARY
|
find_library( MYSQL_LIBRARY
|
||||||
NAMES
|
NAMES
|
||||||
mysql libmysql ${LIB}
|
mysql libmysql libmariadb ${LIB}
|
||||||
PATHS
|
PATHS
|
||||||
${MYSQL_ADD_LIBRARIES_PATH}
|
${MYSQL_ADD_LIBRARIES_PATH}
|
||||||
/usr/lib
|
/usr/lib
|
||||||
|
@ -105,6 +109,7 @@ if( UNIX )
|
||||||
/usr/local/lib
|
/usr/local/lib
|
||||||
/usr/local/lib/mysql
|
/usr/local/lib/mysql
|
||||||
/usr/local/mysql/lib
|
/usr/local/mysql/lib
|
||||||
|
/usr/lib/x86_64-linux-gnu
|
||||||
DOC "Specify the location of the mysql library here."
|
DOC "Specify the location of the mysql library here."
|
||||||
)
|
)
|
||||||
endforeach(LIB ${MYSQL_ADD_LIBRARY})
|
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/MySQL Server 5.7/lib/opt"
|
||||||
"${PROGRAM_FILES_64}/MySQL/lib"
|
"${PROGRAM_FILES_64}/MySQL/lib"
|
||||||
"${PROGRAM_FILES_64}/MariaDB 10.3/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"
|
"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"
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/lib/opt"
|
"[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/MySQL Server 5.7/bin/opt"
|
||||||
"${PROGRAM_FILES_64}/MySQL/bin"
|
"${PROGRAM_FILES_64}/MySQL/bin"
|
||||||
"${PROGRAM_FILES_64}/MariaDB 10.3/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"
|
"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"
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/bin/opt"
|
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/bin/opt"
|
||||||
|
|
|
@ -13,3 +13,4 @@ endif()
|
||||||
# Create log folder
|
# Create log folder
|
||||||
file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin/log )
|
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/navi )
|
||||||
|
file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin/data )
|
||||||
|
|
509
deps/datReader/Dat.cpp
vendored
509
deps/datReader/Dat.cpp
vendored
|
@ -4,308 +4,319 @@
|
||||||
|
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
const uint32_t model_section_count = 0xB;
|
||||||
const uint32_t model_section_count = 0xB;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
{
|
||||||
namespace dat
|
struct DatFileHeader
|
||||||
{
|
{
|
||||||
struct DatFileHeader
|
uint32_t size;
|
||||||
{
|
FileType entry_type;
|
||||||
uint32_t size;
|
uint32_t total_uncompressed_size;
|
||||||
FileType entry_type;
|
uint32_t unknown[0x2];
|
||||||
uint32_t total_uncompressed_size;
|
};
|
||||||
uint32_t unknown[0x2];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DatBlockRecord
|
struct DatBlockRecord
|
||||||
{
|
{
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t unknown[0x4];
|
uint32_t unknown[0x4];
|
||||||
SqPackBlockHash block_hash;
|
SqPackBlockHash block_hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DatBlockHeader
|
struct DatBlockHeader
|
||||||
{
|
{
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t unknown1;
|
uint32_t unknown1;
|
||||||
uint32_t compressed_size;
|
uint32_t compressed_size;
|
||||||
uint32_t uncompressed_size;
|
uint32_t uncompressed_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DatStdFileBlockInfos
|
struct DatStdFileBlockInfos
|
||||||
{
|
{
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint16_t uncompressed_size;
|
uint16_t uncompressed_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DatMdlFileBlockInfos
|
struct DatMdlFileBlockInfos
|
||||||
{
|
{
|
||||||
uint32_t unknown1;
|
uint32_t unknown1;
|
||||||
uint32_t uncompressed_sizes[::model_section_count];
|
uint32_t uncompressed_sizes[::model_section_count];
|
||||||
uint32_t compressed_sizes[::model_section_count];
|
uint32_t compressed_sizes[::model_section_count];
|
||||||
uint32_t offsets[::model_section_count];
|
uint32_t offsets[::model_section_count];
|
||||||
uint16_t block_ids[::model_section_count];
|
uint16_t block_ids[::model_section_count];
|
||||||
uint16_t block_counts[::model_section_count];
|
uint16_t block_counts[::model_section_count];
|
||||||
uint32_t unknown2[0x2];
|
uint32_t unknown2[0x2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DatTexFileBlockInfos
|
struct DatTexFileBlockInfos
|
||||||
{
|
{
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t uncompressed_size;
|
uint32_t uncompressed_size;
|
||||||
uint32_t block_id;
|
uint32_t block_id;
|
||||||
uint32_t block_count;
|
uint32_t block_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::utils::bparse
|
||||||
{
|
{
|
||||||
namespace utils
|
template<>
|
||||||
{
|
inline void reorder< xiv::dat::DatFileHeader >( xiv::dat::DatFileHeader& i_struct )
|
||||||
namespace bparse
|
{
|
||||||
{
|
xiv::utils::bparse::reorder( i_struct.size );
|
||||||
template <>
|
xiv::utils::bparse::reorder( i_struct.entry_type );
|
||||||
inline void reorder<xiv::dat::DatFileHeader>(xiv::dat::DatFileHeader& i_struct)
|
xiv::utils::bparse::reorder( i_struct.total_uncompressed_size );
|
||||||
{
|
for( int32_t i = 0; i < 0x2; ++i )
|
||||||
xiv::utils::bparse::reorder(i_struct.size);
|
{
|
||||||
xiv::utils::bparse::reorder(i_struct.entry_type);
|
xiv::utils::bparse::reorder( i_struct.unknown[ i ] );
|
||||||
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]); }
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template<>
|
||||||
inline void reorder<xiv::dat::DatBlockRecord>(xiv::dat::DatBlockRecord& i_struct)
|
inline void reorder< xiv::dat::DatBlockRecord >( xiv::dat::DatBlockRecord& i_struct )
|
||||||
{
|
{
|
||||||
xiv::utils::bparse::reorder(i_struct.offset);
|
xiv::utils::bparse::reorder( i_struct.offset );
|
||||||
xiv::utils::bparse::reorder(i_struct.size);
|
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.block_hash);
|
{
|
||||||
}
|
xiv::utils::bparse::reorder( i_struct.unknown[ i ] );
|
||||||
|
}
|
||||||
|
xiv::utils::bparse::reorder( i_struct.block_hash );
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template<>
|
||||||
inline void reorder<xiv::dat::DatBlockHeader>(xiv::dat::DatBlockHeader& i_struct)
|
inline void reorder< xiv::dat::DatBlockHeader >( xiv::dat::DatBlockHeader& i_struct )
|
||||||
{
|
{
|
||||||
xiv::utils::bparse::reorder(i_struct.size);
|
xiv::utils::bparse::reorder( i_struct.size );
|
||||||
xiv::utils::bparse::reorder(i_struct.unknown1);
|
xiv::utils::bparse::reorder( i_struct.unknown1 );
|
||||||
xiv::utils::bparse::reorder(i_struct.compressed_size);
|
xiv::utils::bparse::reorder( i_struct.compressed_size );
|
||||||
xiv::utils::bparse::reorder(i_struct.uncompressed_size);
|
xiv::utils::bparse::reorder( i_struct.uncompressed_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template<>
|
||||||
inline void reorder<xiv::dat::DatStdFileBlockInfos>(xiv::dat::DatStdFileBlockInfos& i_struct)
|
inline void reorder< xiv::dat::DatStdFileBlockInfos >( xiv::dat::DatStdFileBlockInfos& i_struct )
|
||||||
{
|
{
|
||||||
xiv::utils::bparse::reorder(i_struct.offset);
|
xiv::utils::bparse::reorder( i_struct.offset );
|
||||||
xiv::utils::bparse::reorder(i_struct.size);
|
xiv::utils::bparse::reorder( i_struct.size );
|
||||||
xiv::utils::bparse::reorder(i_struct.uncompressed_size);
|
xiv::utils::bparse::reorder( i_struct.uncompressed_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template<>
|
||||||
inline void reorder<xiv::dat::DatMdlFileBlockInfos>(xiv::dat::DatMdlFileBlockInfos& i_struct)
|
inline void reorder< xiv::dat::DatMdlFileBlockInfos >( xiv::dat::DatMdlFileBlockInfos& i_struct )
|
||||||
{
|
{
|
||||||
xiv::utils::bparse::reorder(i_struct.unknown1);
|
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 )
|
||||||
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]); }
|
xiv::utils::bparse::reorder( i_struct.uncompressed_sizes[ 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 < ::model_section_count; ++i )
|
||||||
for (auto i = 0; i < 0x2; ++i) { xiv::utils::bparse::reorder(i_struct.unknown2[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 <>
|
template<>
|
||||||
inline void reorder<xiv::dat::DatTexFileBlockInfos>(xiv::dat::DatTexFileBlockInfos& i_struct)
|
inline void reorder< xiv::dat::DatTexFileBlockInfos >( xiv::dat::DatTexFileBlockInfos& i_struct )
|
||||||
{
|
{
|
||||||
xiv::utils::bparse::reorder(i_struct.offset);
|
xiv::utils::bparse::reorder( i_struct.offset );
|
||||||
xiv::utils::bparse::reorder(i_struct.size);
|
xiv::utils::bparse::reorder( i_struct.size );
|
||||||
xiv::utils::bparse::reorder(i_struct.uncompressed_size);
|
xiv::utils::bparse::reorder( i_struct.uncompressed_size );
|
||||||
xiv::utils::bparse::reorder(i_struct.block_id);
|
xiv::utils::bparse::reorder( i_struct.block_id );
|
||||||
xiv::utils::bparse::reorder(i_struct.block_count);
|
xiv::utils::bparse::reorder( i_struct.block_count );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using xiv::utils::bparse::extract;
|
using xiv::utils::bparse::extract;
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
|
||||||
namespace 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 ),
|
SqPack( i_path ),
|
||||||
m_num( i_nb )
|
m_num( i_nb )
|
||||||
{
|
{
|
||||||
auto block_record = extract<DatBlockRecord>(m_handle);
|
auto block_record = extract< DatBlockRecord >( m_handle );
|
||||||
block_record.offset *= 0x80;
|
block_record.offset *= 0x80;
|
||||||
isBlockValid(block_record.offset, block_record.size, block_record.block_hash);
|
isBlockValid( block_record.offset, block_record.size, block_record.block_hash );
|
||||||
}
|
}
|
||||||
|
|
||||||
Dat::~Dat()
|
Dat::~Dat()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<File> Dat::getFile( uint32_t i_offset )
|
std::unique_ptr< File > Dat::getFile( uint32_t i_offset )
|
||||||
{
|
{
|
||||||
std::unique_ptr<File> outputFile(new File());
|
std::unique_ptr< File > outputFile( new File() );
|
||||||
{
|
{
|
||||||
// Lock in this scope
|
// Lock in this scope
|
||||||
std::lock_guard<std::mutex> lock(m_fileMutex);
|
std::lock_guard< std::mutex > lock( m_fileMutex );
|
||||||
|
|
||||||
// Seek to the start of the header of the file record and extract it
|
// Seek to the start of the header of the file record and extract it
|
||||||
m_handle.seekg(i_offset);
|
m_handle.seekg( i_offset );
|
||||||
auto file_header = extract<DatFileHeader>(m_handle);
|
auto file_header = extract< DatFileHeader >( m_handle );
|
||||||
|
|
||||||
switch (file_header.entry_type)
|
switch( file_header.entry_type )
|
||||||
{
|
{
|
||||||
case FileType::empty:
|
case FileType::empty:
|
||||||
throw std::runtime_error("File is empty");
|
throw std::runtime_error( "File is empty" );
|
||||||
|
|
||||||
case FileType::standard:
|
case FileType::standard:
|
||||||
{
|
{
|
||||||
outputFile->_type = FileType::standard;
|
outputFile->_type = FileType::standard;
|
||||||
|
|
||||||
uint32_t number_of_blocks = extract<uint32_t>(m_handle, "number_of_blocks");
|
uint32_t number_of_blocks = extract< uint32_t >( m_handle, "number_of_blocks" );
|
||||||
|
|
||||||
// Just extract offset infos for the blocks to extract
|
// Just extract offset infos for the blocks to extract
|
||||||
std::vector<DatStdFileBlockInfos> std_file_block_infos;
|
std::vector< DatStdFileBlockInfos > std_file_block_infos;
|
||||||
extract<DatStdFileBlockInfos>( m_handle, number_of_blocks, std_file_block_infos );
|
extract< DatStdFileBlockInfos >( m_handle, number_of_blocks, std_file_block_infos );
|
||||||
|
|
||||||
// Pre allocate data vector for the whole file
|
// Pre allocate data vector for the whole file
|
||||||
outputFile->_data_sections.resize(1);
|
outputFile->_data_sections.resize( 1 );
|
||||||
auto& data_section = outputFile->_data_sections.front();
|
auto& data_section = outputFile->_data_sections.front();
|
||||||
|
|
||||||
data_section.reserve(file_header.total_uncompressed_size);
|
data_section.reserve( file_header.total_uncompressed_size );
|
||||||
// Extract each block
|
// Extract each block
|
||||||
for (auto& file_block_info : std_file_block_infos)
|
for( auto& file_block_info : std_file_block_infos )
|
||||||
|
{
|
||||||
|
extractBlock( i_offset + file_header.size + file_block_info.offset, data_section );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileType::model:
|
||||||
|
{
|
||||||
|
outputFile->_type = FileType::model;
|
||||||
|
|
||||||
|
DatMdlFileBlockInfos mdlBlockInfo = extract< DatMdlFileBlockInfos >( m_handle );
|
||||||
|
|
||||||
|
// Getting the block number and read their sizes
|
||||||
|
const uint32_t block_count = mdlBlockInfo.block_ids[ ::model_section_count - 1 ] +
|
||||||
|
mdlBlockInfo.block_counts[ ::model_section_count - 1 ];
|
||||||
|
std::vector< uint16_t > block_sizes;
|
||||||
|
extract< uint16_t >( m_handle, "block_size", block_count, block_sizes );
|
||||||
|
|
||||||
|
// Preallocate sufficient space
|
||||||
|
outputFile->_data_sections.resize( ::model_section_count );
|
||||||
|
|
||||||
|
for( uint32_t i = 0; i < ::model_section_count; ++i )
|
||||||
|
{
|
||||||
|
// Preallocating for section
|
||||||
|
auto& data_section = outputFile->_data_sections[ i ];
|
||||||
|
data_section.reserve( mdlBlockInfo.uncompressed_sizes[ i ] );
|
||||||
|
|
||||||
|
uint32_t current_offset = i_offset + file_header.size + mdlBlockInfo.offsets[ i ];
|
||||||
|
for( uint32_t j = 0; j < mdlBlockInfo.block_counts[ i ]; ++j )
|
||||||
{
|
{
|
||||||
extractBlock(i_offset + file_header.size + file_block_info.offset, data_section);
|
extractBlock( current_offset, data_section );
|
||||||
|
current_offset += block_sizes[ mdlBlockInfo.block_ids[ i ] + j ];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case FileType::model:
|
case FileType::texture:
|
||||||
{
|
{
|
||||||
outputFile->_type = FileType::model;
|
outputFile->_type = FileType::texture;
|
||||||
|
|
||||||
DatMdlFileBlockInfos mdlBlockInfo = extract<DatMdlFileBlockInfos>(m_handle);
|
// Extracts mipmap entries and the block sizes
|
||||||
|
uint32_t sectionCount = extract< uint32_t >( m_handle, "sections_count" );
|
||||||
|
|
||||||
// Getting the block number and read their sizes
|
std::vector< DatTexFileBlockInfos > texBlockInfo;
|
||||||
const uint32_t block_count = mdlBlockInfo.block_ids[::model_section_count - 1] +
|
extract< DatTexFileBlockInfos >( m_handle, sectionCount, texBlockInfo );
|
||||||
mdlBlockInfo.block_counts[::model_section_count - 1];
|
|
||||||
std::vector<uint16_t> block_sizes;
|
|
||||||
extract<uint16_t>(m_handle, "block_size", block_count, block_sizes);
|
|
||||||
|
|
||||||
// Preallocate sufficient space
|
// Extracting block sizes
|
||||||
outputFile->_data_sections.resize(::model_section_count);
|
uint32_t block_count = texBlockInfo.back().block_id + texBlockInfo.back().block_count;
|
||||||
|
std::vector< uint16_t > block_sizes;
|
||||||
|
extract< uint16_t >( m_handle, "block_size", block_count, block_sizes );
|
||||||
|
|
||||||
for (uint32_t i = 0; i < ::model_section_count; ++i)
|
outputFile->_data_sections.resize( sectionCount + 1 );
|
||||||
|
|
||||||
|
// Extracting header in section 0
|
||||||
|
const uint32_t header_size = texBlockInfo.front().offset;
|
||||||
|
auto& header_section = outputFile->_data_sections[ 0 ];
|
||||||
|
header_section.resize( header_size );
|
||||||
|
|
||||||
|
m_handle.seekg( i_offset + file_header.size );
|
||||||
|
m_handle.read( header_section.data(), header_size );
|
||||||
|
|
||||||
|
// Extracting other sections
|
||||||
|
for( uint32_t i = 0; i < sectionCount; ++i )
|
||||||
|
{
|
||||||
|
auto& data_section = outputFile->_data_sections[ i + 1 ];
|
||||||
|
auto& section_infos = texBlockInfo[ i ];
|
||||||
|
data_section.reserve( section_infos.uncompressed_size );
|
||||||
|
|
||||||
|
uint32_t current_offset = i_offset + file_header.size + section_infos.offset;
|
||||||
|
for( uint32_t j = 0; j < section_infos.block_count; ++j )
|
||||||
{
|
{
|
||||||
// Preallocating for section
|
extractBlock( current_offset, data_section );
|
||||||
auto& data_section = outputFile->_data_sections[i];
|
current_offset += block_sizes[ section_infos.block_id + j ];
|
||||||
data_section.reserve(mdlBlockInfo.uncompressed_sizes[i]);
|
|
||||||
|
|
||||||
uint32_t current_offset = i_offset + file_header.size + mdlBlockInfo.offsets[i];
|
|
||||||
for (uint32_t j = 0; j < mdlBlockInfo.block_counts[i]; ++j)
|
|
||||||
{
|
|
||||||
extractBlock(current_offset, data_section);
|
|
||||||
current_offset += block_sizes[mdlBlockInfo.block_ids[i] + j];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case FileType::texture:
|
default:
|
||||||
{
|
throw std::runtime_error(
|
||||||
outputFile->_type = FileType::texture;
|
"Invalid entry_type: " + std::to_string( static_cast<uint32_t>(file_header.entry_type) ) );
|
||||||
|
|
||||||
// Extracts mipmap entries and the block sizes
|
|
||||||
uint32_t sectionCount = extract<uint32_t>(m_handle, "sections_count");
|
|
||||||
|
|
||||||
std::vector<DatTexFileBlockInfos> texBlockInfo;
|
|
||||||
extract<DatTexFileBlockInfos>(m_handle, sectionCount, texBlockInfo);
|
|
||||||
|
|
||||||
// Extracting block sizes
|
|
||||||
uint32_t block_count = texBlockInfo.back().block_id + texBlockInfo.back().block_count;
|
|
||||||
std::vector<uint16_t> block_sizes;
|
|
||||||
extract<uint16_t>(m_handle, "block_size", block_count, block_sizes);
|
|
||||||
|
|
||||||
outputFile->_data_sections.resize(sectionCount + 1);
|
|
||||||
|
|
||||||
// Extracting header in section 0
|
|
||||||
const uint32_t header_size = texBlockInfo.front().offset;
|
|
||||||
auto& header_section = outputFile->_data_sections[0];
|
|
||||||
header_section.resize(header_size);
|
|
||||||
|
|
||||||
m_handle.seekg(i_offset + file_header.size);
|
|
||||||
m_handle.read(header_section.data(), header_size);
|
|
||||||
|
|
||||||
// Extracting other sections
|
|
||||||
for (uint32_t i = 0; i < sectionCount; ++i)
|
|
||||||
{
|
|
||||||
auto& data_section = outputFile->_data_sections[i + 1];
|
|
||||||
auto& section_infos = texBlockInfo[i];
|
|
||||||
data_section.reserve(section_infos.uncompressed_size);
|
|
||||||
|
|
||||||
uint32_t current_offset = i_offset + file_header.size + section_infos.offset;
|
|
||||||
for (uint32_t j = 0; j < section_infos.block_count; ++j)
|
|
||||||
{
|
|
||||||
extractBlock(current_offset, data_section);
|
|
||||||
current_offset += block_sizes[section_infos.block_id + j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Invalid entry_type: " + std::to_string(static_cast<uint32_t>(file_header.entry_type)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputFile;
|
return outputFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dat::extractBlock( uint32_t i_offset, std::vector<char>& o_data )
|
void Dat::extractBlock( uint32_t i_offset, std::vector< char >& o_data )
|
||||||
{
|
{
|
||||||
m_handle.seekg(i_offset);
|
m_handle.seekg( i_offset );
|
||||||
|
|
||||||
DatBlockHeader block_header = extract<DatBlockHeader>(m_handle);
|
DatBlockHeader block_header = extract< DatBlockHeader >( m_handle );
|
||||||
|
|
||||||
// Resizing the vector to write directly into it
|
// Resizing the vector to write directly into it
|
||||||
const uint32_t data_size = o_data.size();
|
const uint32_t data_size = o_data.size();
|
||||||
o_data.resize(data_size + block_header.uncompressed_size);
|
o_data.resize( data_size + block_header.uncompressed_size );
|
||||||
|
|
||||||
// 32000 in compressed_size means it is not compressed so take uncompressed_size
|
// 32000 in compressed_size means it is not compressed so take uncompressed_size
|
||||||
if (block_header.compressed_size == 32000)
|
if( block_header.compressed_size == 32000 )
|
||||||
{
|
{
|
||||||
m_handle.read(o_data.data() + data_size, block_header.uncompressed_size);
|
m_handle.read( o_data.data() + data_size, block_header.uncompressed_size );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If it is compressed use zlib
|
// If it is compressed use zlib
|
||||||
// Read the data to be decompressed
|
// Read the data to be decompressed
|
||||||
std::vector<char> temp_buffer(block_header.compressed_size);
|
std::vector< char > temp_buffer( block_header.compressed_size );
|
||||||
m_handle.read(temp_buffer.data(), block_header.compressed_size);
|
m_handle.read( temp_buffer.data(), block_header.compressed_size );
|
||||||
|
|
||||||
utils::zlib::no_header_decompress(reinterpret_cast<uint8_t*>(temp_buffer.data()),
|
utils::zlib::no_header_decompress( reinterpret_cast<uint8_t*>(temp_buffer.data()),
|
||||||
temp_buffer.size(),
|
temp_buffer.size(),
|
||||||
reinterpret_cast<uint8_t*>(o_data.data() + data_size),
|
reinterpret_cast<uint8_t*>(o_data.data() + data_size),
|
||||||
block_header.uncompressed_size);
|
block_header.uncompressed_size );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Dat::getNum() const
|
uint32_t Dat::getNum() const
|
||||||
{
|
{
|
||||||
return m_num;
|
return m_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
47
deps/datReader/Dat.h
vendored
47
deps/datReader/Dat.h
vendored
|
@ -5,41 +5,38 @@
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <experimental/filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
|
||||||
namespace dat
|
|
||||||
{
|
{
|
||||||
|
|
||||||
class File;
|
class File;
|
||||||
|
|
||||||
class Dat : public SqPack
|
class Dat : public SqPack
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Full path to the dat file
|
// 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();
|
virtual ~Dat();
|
||||||
|
|
||||||
// Retrieves a file given the offset in the dat file
|
// Retrieves a file given the offset in the dat file
|
||||||
std::unique_ptr<File> getFile( uint32_t i_offset );
|
std::unique_ptr<File> getFile( uint32_t i_offset );
|
||||||
|
|
||||||
// Appends to the vector the data of this block, it is assumed to be preallocated
|
// Appends to the vector the data of this block, it is assumed to be preallocated
|
||||||
// Is it also assumed that the m_fileMutex is currently locked by this thread before the call
|
// Is it also assumed that the m_fileMutex is currently locked by this thread before the call
|
||||||
void extractBlock( uint32_t i_offset, std::vector<char>& o_data );
|
void extractBlock( uint32_t i_offset, std::vector<char>& o_data );
|
||||||
|
|
||||||
// Returns the dat number
|
// Returns the dat number
|
||||||
uint32_t getNum() const;
|
uint32_t getNum() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// File reading mutex to have only one thread reading the file at a time
|
// File reading mutex to have only one thread reading the file at a time
|
||||||
std::mutex m_fileMutex;
|
std::mutex m_fileMutex;
|
||||||
|
|
||||||
// Dat nb
|
// Dat nb
|
||||||
uint32_t m_num;
|
uint32_t m_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // XIV_DAT_DAT_H
|
#endif // XIV_DAT_DAT_H
|
||||||
|
|
12
deps/datReader/DatCat.cpp
vendored
12
deps/datReader/DatCat.cpp
vendored
|
@ -10,7 +10,7 @@ namespace xiv
|
||||||
namespace dat
|
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_name( name ),
|
||||||
m_catNum( catNum ),
|
m_catNum( catNum ),
|
||||||
m_chunk( -1 )
|
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";
|
std::string prefix = ss.str() + "0000.win32";
|
||||||
|
|
||||||
// Creates the index: XX0000.win32.index
|
// 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 all dat files linked to this index, create it: XX0000.win32.datX
|
||||||
for( uint32_t i = 0; i < getIndex().getDatCount(); ++i )
|
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_name( name ),
|
||||||
m_catNum( catNum ),
|
m_catNum( catNum ),
|
||||||
m_chunk( chunk )
|
m_chunk( chunk )
|
||||||
{
|
{
|
||||||
// Creates the index: XX0000.win32.index
|
// 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 all dat files linked to this index, create it: XX0000.win32.datX
|
||||||
for( uint32_t i = 0; i < getIndex().getDatCount(); ++i )
|
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 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
88
deps/datReader/DatCat.h
vendored
88
deps/datReader/DatCat.h
vendored
|
@ -3,62 +3,66 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <experimental/filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
namespace xiv {
|
namespace xiv::dat
|
||||||
namespace dat {
|
|
||||||
|
|
||||||
class Index;
|
|
||||||
class Dat;
|
|
||||||
class File;
|
|
||||||
|
|
||||||
// A category represents an .index and its associated .datX
|
|
||||||
class Cat
|
|
||||||
{
|
{
|
||||||
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 );
|
|
||||||
|
|
||||||
// basePath: Path to the folder containingthe datfiles
|
class Index;
|
||||||
// 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();
|
|
||||||
|
|
||||||
// Returns .index of the category
|
class Dat;
|
||||||
const Index& getIndex() const;
|
|
||||||
|
|
||||||
// Retrieve a file from the category given its hashes
|
class File;
|
||||||
std::unique_ptr<File> getFile( uint32_t dir_hash, uint32_t filename_hash ) const;
|
|
||||||
|
// A category represents an .index and its associated .datX
|
||||||
|
class Cat
|
||||||
|
{
|
||||||
|
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::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::filesystem::path& basePath, uint32_t catNum, const std::string& name, uint32_t exNum,
|
||||||
|
uint32_t chunk );
|
||||||
|
|
||||||
|
~Cat();
|
||||||
|
|
||||||
|
// Returns .index of the category
|
||||||
|
const Index& getIndex() const;
|
||||||
|
|
||||||
|
// Retrieve a file from the category given its hashes
|
||||||
|
std::unique_ptr< File > getFile( uint32_t dir_hash, uint32_t filename_hash ) const;
|
||||||
|
|
||||||
|
|
||||||
bool doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const;
|
bool doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const;
|
||||||
bool doesDirExist( uint32_t dir_hash ) const;
|
|
||||||
|
bool doesDirExist( uint32_t dir_hash ) const;
|
||||||
|
|
||||||
|
|
||||||
// Returns thename of the category
|
// Returns thename of the category
|
||||||
const std::string& getName() const;
|
const std::string& getName() const;
|
||||||
|
|
||||||
// Returns the number of the category
|
// Returns the number of the category
|
||||||
uint32_t getCatNum() const;
|
uint32_t getCatNum() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const std::string m_name;
|
const std::string m_name;
|
||||||
const uint32_t m_catNum;
|
const uint32_t m_catNum;
|
||||||
const uint32_t m_chunk;
|
const uint32_t m_chunk;
|
||||||
|
|
||||||
// The .index
|
// The .index
|
||||||
std::unique_ptr<Index> m_index;
|
std::unique_ptr< Index > m_index;
|
||||||
|
|
||||||
// The .datXs such as dat nb X => m_dats[X]
|
// The .datXs such as dat nb X => m_dats[X]
|
||||||
std::vector<std::unique_ptr<Dat>> m_dats;
|
std::vector< std::unique_ptr< Dat>> m_dats;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // XIV_DAT_CAT_H
|
#endif // XIV_DAT_CAT_H
|
||||||
|
|
198
deps/datReader/DatCategories/bg/LgbTypes.h
vendored
Normal file
198
deps/datReader/DatCategories/bg/LgbTypes.h
vendored
Normal 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
|
248
deps/datReader/DatCategories/bg/lgb.h
vendored
248
deps/datReader/DatCategories/bg/lgb.h
vendored
|
@ -12,87 +12,33 @@
|
||||||
#include "matrix4.h"
|
#include "matrix4.h"
|
||||||
#include "vec3.h"
|
#include "vec3.h"
|
||||||
#include "sgb.h"
|
#include "sgb.h"
|
||||||
|
#include "LgbTypes.h"
|
||||||
|
|
||||||
// garbage to skip model loading
|
// based on https://github.com/ufx/SaintCoinach/blob/master/SaintCoinach/Graphics/Lgb/
|
||||||
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#
|
|
||||||
struct LGB_FILE;
|
struct LGB_FILE;
|
||||||
struct LGB_FILE_HEADER;
|
struct LGB_FILE_HEADER;
|
||||||
struct LGB_GROUP;
|
struct LGB_GROUP;
|
||||||
struct LGB_GROUP_HEADER;
|
struct LGB_GROUP_HEADER;
|
||||||
|
|
||||||
enum class LgbEntryType :
|
class LgbEntry
|
||||||
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
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
char* m_buf;
|
char* m_buf;
|
||||||
uint32_t m_offset;
|
uint32_t m_offset;
|
||||||
LGB_ENTRY_HEADER header;
|
InstanceObject header;
|
||||||
|
|
||||||
LGB_ENTRY()
|
LgbEntry()
|
||||||
{
|
{
|
||||||
m_buf = nullptr;
|
m_buf = nullptr;
|
||||||
m_offset = 0;
|
m_offset = 0;
|
||||||
memset( &header, 0, sizeof( header ) );
|
memset( &header, 0, sizeof( header ) );
|
||||||
};
|
};
|
||||||
|
|
||||||
LGB_ENTRY( char* buf, uint32_t offset )
|
LgbEntry( char* buf, uint32_t offset )
|
||||||
{
|
{
|
||||||
m_buf = buf;
|
m_buf = buf;
|
||||||
m_offset = offset;
|
m_offset = offset;
|
||||||
header = *reinterpret_cast< LGB_ENTRY_HEADER* >( buf + offset );
|
header = *reinterpret_cast< InstanceObject* >( buf + offset );
|
||||||
};
|
};
|
||||||
|
|
||||||
const LgbEntryType getType() const
|
const LgbEntryType getType() const
|
||||||
|
@ -100,30 +46,16 @@ public:
|
||||||
return header.type;
|
return header.type;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~LGB_ENTRY()
|
virtual ~LgbEntry()
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct LGB_BGPARTS_HEADER :
|
class LGB_BGPARTS_ENTRY : public LgbEntry
|
||||||
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
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LGB_BGPARTS_HEADER header;
|
BgPartsData data;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string modelFileName;
|
std::string modelFileName;
|
||||||
std::string collisionFileName;
|
std::string collisionFileName;
|
||||||
|
@ -132,124 +64,94 @@ public:
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) :
|
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
|
||||||
LGB_ENTRY( buf, offset )
|
|
||||||
{
|
{
|
||||||
header = *reinterpret_cast<LGB_BGPARTS_HEADER*>( buf + offset );
|
data = *reinterpret_cast< BgPartsData* >( buf + offset );
|
||||||
name = std::string( buf + offset + header.nameOffset );
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
modelFileName = std::string( buf + offset + header.modelFileOffset );
|
modelFileName = std::string( buf + offset + data.modelFileOffset );
|
||||||
collisionFileName = std::string( buf + offset + header.collisionFileOffset );
|
collisionFileName = std::string( buf + offset + data.collisionFileOffset );
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LGB_GIMMICK_HEADER :
|
class LGB_GIMMICK_ENTRY : public LgbEntry
|
||||||
public LGB_ENTRY_HEADER
|
|
||||||
{
|
|
||||||
uint32_t gimmickFileOffset;
|
|
||||||
char unknownBytes[100];
|
|
||||||
};
|
|
||||||
|
|
||||||
class LGB_GIMMICK_ENTRY :
|
|
||||||
public LGB_ENTRY
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LGB_GIMMICK_HEADER header;
|
GimmickData data;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string gimmickFileName;
|
std::string gimmickFileName;
|
||||||
|
|
||||||
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) :
|
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
|
||||||
LGB_ENTRY( buf, offset )
|
|
||||||
{
|
{
|
||||||
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>( buf + offset );
|
data = *reinterpret_cast< GimmickData* >( buf + offset );
|
||||||
name = std::string( buf + offset + header.nameOffset );
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
gimmickFileName = std::string( buf + offset + header.gimmickFileOffset );
|
gimmickFileName = std::string( buf + offset + data.gimmickFileOffset );
|
||||||
//std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LGB_ENPC_HEADER :
|
class LGB_ENPC_ENTRY : public LgbEntry
|
||||||
public LGB_ENTRY_HEADER
|
|
||||||
{
|
|
||||||
uint32_t enpcId;
|
|
||||||
uint8_t unknown1[0x24];
|
|
||||||
};
|
|
||||||
|
|
||||||
class LGB_ENPC_ENTRY :
|
|
||||||
public LGB_ENTRY
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LGB_ENPC_HEADER header;
|
ENpcData data;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
LGB_ENPC_ENTRY( char* buf, uint32_t offset ) :
|
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
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LGB_EOBJ_HEADER header;
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) :
|
|
||||||
LGB_ENTRY( buf, offset )
|
|
||||||
{
|
|
||||||
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset );
|
|
||||||
//std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n";
|
|
||||||
name = std::string( buf + offset + header.nameOffset );
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LGB_MAPRANGE_HEADER :
|
class LGB_EOBJ_ENTRY : public LgbEntry
|
||||||
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
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LGB_MAPRANGE_HEADER header;
|
EObjData data;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
LGB_MAPRANGE_ENTRY( char* buf, uint32_t offset ) :
|
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
|
||||||
LGB_ENTRY( buf, offset )
|
|
||||||
{
|
{
|
||||||
header = *reinterpret_cast< LGB_MAPRANGE_HEADER* >( buf + offset );
|
data = *reinterpret_cast< EObjData* >( buf + offset );
|
||||||
name = std::string( buf + offset + header.nameOffset );
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LGB_MAP_RANGE_ENTRY : public LgbEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MapRangeData data;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
LGB_MAP_RANGE_ENTRY( char* buf, uint32_t offset ) : LgbEntry( 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
|
struct LGB_GROUP_HEADER
|
||||||
{
|
{
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
@ -272,15 +174,13 @@ struct LGB_GROUP
|
||||||
LGB_FILE* parent;
|
LGB_FILE* parent;
|
||||||
LGB_GROUP_HEADER header;
|
LGB_GROUP_HEADER header;
|
||||||
std::string name;
|
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 )
|
LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset )
|
||||||
{
|
{
|
||||||
parent = parentStruct;
|
parent = parentStruct;
|
||||||
header = *reinterpret_cast< LGB_GROUP_HEADER* >( buf + offset );
|
header = *reinterpret_cast< LGB_GROUP_HEADER* >( buf + offset );
|
||||||
name = std::string( buf + offset + header.groupNameOffset );
|
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;
|
const auto entriesOffset = offset + header.entriesOffset;
|
||||||
for( auto i = 0; i < header.entryCount; ++i )
|
for( auto i = 0; i < header.entryCount; ++i )
|
||||||
{
|
{
|
||||||
|
@ -288,8 +188,7 @@ struct LGB_GROUP
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto type = *reinterpret_cast<LgbEntryType*>( buf + entryOffset );
|
const auto type = *reinterpret_cast< LgbEntryType* >( buf + entryOffset );
|
||||||
// garbage to skip model loading
|
|
||||||
if( type == LgbEntryType::BgParts )
|
if( type == LgbEntryType::BgParts )
|
||||||
{
|
{
|
||||||
entries.push_back( std::make_shared< LGB_BGPARTS_ENTRY >( buf, entryOffset ) );
|
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 ) );
|
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 )
|
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
|
else
|
||||||
{
|
{
|
||||||
entries.push_back( std::make_shared< LGB_ENTRY >( buf, entryOffset ) );
|
entries.push_back( std::make_shared< LgbEntry >( buf, entryOffset ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch( std::exception& e )
|
catch( std::exception& e )
|
||||||
{
|
{
|
||||||
|
@ -344,8 +245,7 @@ struct LGB_FILE
|
||||||
std::vector< LGB_GROUP > groups;
|
std::vector< LGB_GROUP > groups;
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
LGB_FILE( char* buf, const std::string& name ) :
|
LGB_FILE( char* buf, const std::string& name ) : LGB_FILE( buf )
|
||||||
LGB_FILE( buf )
|
|
||||||
{
|
{
|
||||||
m_name = name;
|
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 )
|
if( strncmp( &header.magic[ 0 ], "LGB1", 4 ) != 0 || strncmp( &header.magic2[ 0 ], "LGP1", 4 ) != 0 )
|
||||||
throw std::runtime_error( "Invalid LGB file!" );
|
throw std::runtime_error( "Invalid LGB file!" );
|
||||||
|
|
||||||
//groups.resize(header.groupCount);
|
|
||||||
|
|
||||||
constexpr auto baseOffset = sizeof( header );
|
constexpr auto baseOffset = sizeof( header );
|
||||||
for( auto i = 0; i < header.groupCount; ++i )
|
for( auto i = 0; i < header.groupCount; ++i )
|
||||||
{
|
{
|
||||||
|
|
12
deps/datReader/DatCategories/bg/sgb.h
vendored
12
deps/datReader/DatCategories/bg/sgb.h
vendored
|
@ -22,15 +22,13 @@ struct SGB_GROUP;
|
||||||
struct SGB_GROUP_HEADER;
|
struct SGB_GROUP_HEADER;
|
||||||
|
|
||||||
|
|
||||||
enum SgbDataType :
|
enum SgbDataType : uint32_t
|
||||||
uint32_t
|
|
||||||
{
|
{
|
||||||
Unknown0008 = 0x0008,
|
Unknown0008 = 0x0008,
|
||||||
Group = 0x0100,
|
Group = 0x0100,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SgbGroupEntryType :
|
enum SgbGroupEntryType : uint32_t
|
||||||
uint32_t
|
|
||||||
{
|
{
|
||||||
Model = 0x01,
|
Model = 0x01,
|
||||||
Gimmick = 0x06,
|
Gimmick = 0x06,
|
||||||
|
@ -124,15 +122,13 @@ struct SGB_ENTRY_HEADER
|
||||||
vec3 scale;
|
vec3 scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SGB_MODEL_HEADER :
|
struct SGB_MODEL_HEADER : public SGB_ENTRY_HEADER
|
||||||
public SGB_ENTRY_HEADER
|
|
||||||
{
|
{
|
||||||
int32_t modelFileOffset;
|
int32_t modelFileOffset;
|
||||||
int32_t collisionFileOffset;
|
int32_t collisionFileOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SGB_MODEL_ENTRY :
|
struct SGB_MODEL_ENTRY : public SGB_GROUP_ENTRY
|
||||||
public SGB_GROUP_ENTRY
|
|
||||||
{
|
{
|
||||||
SGB_MODEL_HEADER header;
|
SGB_MODEL_HEADER header;
|
||||||
SgbGroupEntryType type;
|
SgbGroupEntryType type;
|
||||||
|
|
737
deps/datReader/Exd.cpp
vendored
737
deps/datReader/Exd.cpp
vendored
|
@ -8,373 +8,378 @@
|
||||||
using xiv::utils::bparse::extract;
|
using xiv::utils::bparse::extract;
|
||||||
|
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::exd
|
||||||
{
|
{
|
||||||
namespace exd
|
struct ExdHeader
|
||||||
{
|
{
|
||||||
|
char magic[0x4];
|
||||||
|
uint16_t unknown;
|
||||||
|
uint16_t unknown2;
|
||||||
|
uint32_t index_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExdRecordIndex
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
uint32_t offset;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace xiv::utils::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 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace xiv::exd
|
||||||
|
{
|
||||||
|
Exd::Exd( std::shared_ptr< Exh > i_exh, const std::vector< std::shared_ptr< dat::File>>& i_files )
|
||||||
|
{
|
||||||
|
_exh = i_exh;
|
||||||
|
_files = i_files;
|
||||||
|
|
||||||
|
|
||||||
|
// Iterates over all the files
|
||||||
|
const uint32_t member_count = _exh->get_members().size();
|
||||||
|
for( auto& file_ptr : _files )
|
||||||
|
{
|
||||||
|
// Get a stream
|
||||||
|
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||||
|
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||||
|
|
||||||
|
// Extract the header and skip to the record indices
|
||||||
|
auto exd_header = extract< ExdHeader >( iss );
|
||||||
|
iss.seekg( 0x20 );
|
||||||
|
|
||||||
|
// Preallocate and extract the record_indices
|
||||||
|
const uint32_t record_count = exd_header.index_size / sizeof( ExdRecordIndex );
|
||||||
|
std::vector< ExdRecordIndex > record_indices;
|
||||||
|
record_indices.reserve( record_count );
|
||||||
|
for( uint32_t i = 0; i < record_count; ++i )
|
||||||
|
{
|
||||||
|
auto recordIndex = extract< ExdRecordIndex >( iss );
|
||||||
|
_idCache[ recordIndex.id ] = ExdCacheEntry{ file_ptr, recordIndex.offset };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Exd::~Exd()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector< Field > Exd::get_row( uint32_t id, uint32_t subRow )
|
||||||
|
{
|
||||||
|
|
||||||
|
auto cacheEntryIt = _idCache.find( id );
|
||||||
|
if( cacheEntryIt == _idCache.end() )
|
||||||
|
throw std::runtime_error( "Id not found: " + std::to_string( id ) );
|
||||||
|
|
||||||
|
// Iterates over all the files
|
||||||
|
const uint32_t member_count = _exh->get_members().size();
|
||||||
|
auto& file_ptr = cacheEntryIt->second.file;
|
||||||
|
|
||||||
|
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||||
|
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||||
|
|
||||||
|
// Get the vector fields for the given record and preallocate it
|
||||||
|
auto fields = _data[ id ];
|
||||||
|
fields.reserve( member_count );
|
||||||
|
iss.seekg( cacheEntryIt->second.offset + 6 );
|
||||||
|
|
||||||
|
uint8_t subRows = *reinterpret_cast< uint8_t* >( &dataCpy[ cacheEntryIt->second.offset + 5 ] );
|
||||||
|
|
||||||
|
if( subRow >= subRows )
|
||||||
|
throw std::runtime_error( "Out of bounds sub-row!" );
|
||||||
|
|
||||||
|
int offset = cacheEntryIt->second.offset + 6 + ( subRow * _exh->get_header().data_offset + 2 * ( subRow + 1 ) );
|
||||||
|
|
||||||
|
for( auto& member_entry : _exh->get_exh_members() )
|
||||||
|
{
|
||||||
|
// Seek to the position of the member to extract.
|
||||||
|
// 6 is because we have uint32_t/uint16_t at the start of each record
|
||||||
|
iss.seekg( offset + member_entry.offset );
|
||||||
|
|
||||||
|
// Switch depending on the type to extract
|
||||||
|
switch( member_entry.type )
|
||||||
|
{
|
||||||
|
case DataType::string:
|
||||||
|
// Extract the offset to the actual string
|
||||||
|
// Seek to it then extract the actual string
|
||||||
|
{
|
||||||
|
throw std::runtime_error( "String not implemented for variant 2!" );
|
||||||
|
//auto string_offset = extract<uint32_t>( iss, "string_offset", false );
|
||||||
|
//iss.seekg( cacheEntryIt->second.offset + 6 + _exh->get_header().data_offset + string_offset );
|
||||||
|
//fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::boolean:
|
||||||
|
fields.emplace_back( extract< bool >( iss, "bool" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::int8:
|
||||||
|
fields.emplace_back( extract< int8_t >( iss, "int8_t" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint8:
|
||||||
|
fields.emplace_back( extract< uint8_t >( iss, "uint8_t" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::int16:
|
||||||
|
fields.emplace_back( extract< int16_t >( iss, "int16_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint16:
|
||||||
|
fields.emplace_back( extract< uint16_t >( iss, "uint16_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::int32:
|
||||||
|
fields.emplace_back( extract< int32_t >( iss, "int32_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint32:
|
||||||
|
fields.emplace_back( extract< uint32_t >( iss, "uint32_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::float32:
|
||||||
|
fields.emplace_back( extract< float >( iss, "float", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint64:
|
||||||
|
fields.emplace_back( extract< uint64_t >( iss, "uint64_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
auto type = static_cast< uint16_t >( member_entry.type );
|
||||||
|
if( type < 0x19 || type > 0x20 )
|
||||||
|
throw std::runtime_error( "Unknown DataType: " + std::to_string( type ) );
|
||||||
|
uint64_t val = extract< uint64_t >( iss, "bool" );
|
||||||
|
int32_t shift = type - 0x19;
|
||||||
|
int32_t i = 1 << shift;
|
||||||
|
val &= i;
|
||||||
|
fields.emplace_back( ( val & i ) == i );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fields;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector< Field > Exd::get_row( uint32_t id )
|
||||||
|
{
|
||||||
|
|
||||||
|
auto cacheEntryIt = _idCache.find( id );
|
||||||
|
if( cacheEntryIt == _idCache.end() )
|
||||||
|
throw std::runtime_error( "Id not found: " + std::to_string( id ) );
|
||||||
|
|
||||||
|
// Iterates over all the files
|
||||||
|
const uint32_t member_count = _exh->get_members().size();
|
||||||
|
auto& file_ptr = cacheEntryIt->second.file;
|
||||||
|
|
||||||
|
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||||
|
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||||
|
|
||||||
|
// Get the vector fields for the given record and preallocate it
|
||||||
|
auto fields = _data[ id ];
|
||||||
|
fields.reserve( member_count );
|
||||||
|
iss.seekg( cacheEntryIt->second.offset + 6 );
|
||||||
|
|
||||||
|
uint8_t subRows = *reinterpret_cast< uint8_t* >( &dataCpy[ cacheEntryIt->second.offset + 5 ] );
|
||||||
|
|
||||||
|
for( auto& member_entry : _exh->get_exh_members() )
|
||||||
|
{
|
||||||
|
// Seek to the position of the member to extract.
|
||||||
|
// 6 is because we have uint32_t/uint16_t at the start of each record
|
||||||
|
iss.seekg( cacheEntryIt->second.offset + 6 + member_entry.offset );
|
||||||
|
|
||||||
|
// Switch depending on the type to extract
|
||||||
|
switch( member_entry.type )
|
||||||
|
{
|
||||||
|
case DataType::string:
|
||||||
|
// Extract the offset to the actual string
|
||||||
|
// Seek to it then extract the actual string
|
||||||
|
{
|
||||||
|
auto string_offset = extract< uint32_t >( iss, "string_offset", false );
|
||||||
|
iss.seekg( cacheEntryIt->second.offset + 6 + _exh->get_header().data_offset + string_offset );
|
||||||
|
fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::boolean:
|
||||||
|
fields.emplace_back( extract< bool >( iss, "bool" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::int8:
|
||||||
|
fields.emplace_back( extract< int8_t >( iss, "int8_t" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint8:
|
||||||
|
fields.emplace_back( extract< uint8_t >( iss, "uint8_t" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::int16:
|
||||||
|
fields.emplace_back( extract< int16_t >( iss, "int16_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint16:
|
||||||
|
fields.emplace_back( extract< uint16_t >( iss, "uint16_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::int32:
|
||||||
|
fields.emplace_back( extract< int32_t >( iss, "int32_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint32:
|
||||||
|
fields.emplace_back( extract< uint32_t >( iss, "uint32_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::float32:
|
||||||
|
fields.emplace_back( extract< float >( iss, "float", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint64:
|
||||||
|
fields.emplace_back( extract< uint64_t >( iss, "uint64_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
auto type = static_cast< uint16_t >( member_entry.type );
|
||||||
|
if( type < 0x19 || type > 0x20 )
|
||||||
|
throw std::runtime_error( "Unknown DataType: " + std::to_string( type ) );
|
||||||
|
uint64_t val = extract< uint64_t >( iss, "bool" );
|
||||||
|
int32_t shift = type - 0x19;
|
||||||
|
int32_t i = 1 << shift;
|
||||||
|
val &= i;
|
||||||
|
fields.emplace_back( ( val & i ) == i );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fields;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all rows
|
||||||
|
const std::map< uint32_t, std::vector< Field>>& Exd::get_rows()
|
||||||
|
{
|
||||||
|
// Iterates over all the files
|
||||||
|
const uint32_t member_count = _exh->get_members().size();
|
||||||
|
for( auto& file_ptr : _files )
|
||||||
|
{
|
||||||
|
// Get a stream
|
||||||
|
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||||
|
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||||
|
|
||||||
|
// Extract the header and skip to the record indices
|
||||||
|
auto exd_header = extract< ExdHeader >( iss );
|
||||||
|
iss.seekg( 0x20 );
|
||||||
|
|
||||||
|
// Preallocate and extract the record_indices
|
||||||
|
const uint32_t record_count = exd_header.index_size / sizeof( ExdRecordIndex );
|
||||||
|
std::vector< ExdRecordIndex > record_indices;
|
||||||
|
record_indices.reserve( record_count );
|
||||||
|
for( uint32_t i = 0; i < record_count; ++i )
|
||||||
|
{
|
||||||
|
record_indices.emplace_back( extract< ExdRecordIndex >( iss ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto& record_index : record_indices )
|
||||||
|
{
|
||||||
|
// Get the vector fields for the given record and preallocate it
|
||||||
|
auto& fields = _data[ record_index.id ];
|
||||||
|
fields.reserve( member_count );
|
||||||
|
|
||||||
|
for( auto& member_entry : _exh->get_exh_members() )
|
||||||
|
//for( auto& member_entry : _exh->get_members() )
|
||||||
|
{
|
||||||
|
// Seek to the position of the member to extract.
|
||||||
|
// 6 is because we have uint32_t/uint16_t at the start of each record
|
||||||
|
iss.seekg( record_index.offset + 6 + member_entry.offset );
|
||||||
|
|
||||||
|
// Switch depending on the type to extract
|
||||||
|
switch( member_entry.type )
|
||||||
|
{
|
||||||
|
case DataType::string:
|
||||||
|
// Extract the offset to the actual string
|
||||||
|
// Seek to it then extract the actual string
|
||||||
|
{
|
||||||
|
auto string_offset = extract< uint32_t >( iss, "string_offset", false );
|
||||||
|
iss.seekg( record_index.offset + 6 + _exh->get_header().data_offset + string_offset );
|
||||||
|
fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::boolean:
|
||||||
|
fields.emplace_back( extract< bool >( iss, "bool" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::int8:
|
||||||
|
fields.emplace_back( extract< int8_t >( iss, "int8_t" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint8:
|
||||||
|
fields.emplace_back( extract< uint8_t >( iss, "uint8_t" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::int16:
|
||||||
|
fields.emplace_back( extract< int16_t >( iss, "int16_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint16:
|
||||||
|
fields.emplace_back( extract< uint16_t >( iss, "uint16_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::int32:
|
||||||
|
fields.emplace_back( extract< int32_t >( iss, "int32_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint32:
|
||||||
|
fields.emplace_back( extract< uint32_t >( iss, "uint32_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::float32:
|
||||||
|
fields.emplace_back( extract< float >( iss, "float", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataType::uint64:
|
||||||
|
fields.emplace_back( extract< uint64_t >( iss, "uint64_t", false ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
auto type = static_cast< uint16_t >( member_entry.type );
|
||||||
|
if( type < 0x19 || type > 0x20 )
|
||||||
|
throw std::runtime_error( "Unknown DataType: " + std::to_string( type ) );
|
||||||
|
uint64_t val = extract< uint64_t >( iss, "bool" );
|
||||||
|
int32_t shift = type - 0x19;
|
||||||
|
int32_t i = 1 << shift;
|
||||||
|
val &= i;
|
||||||
|
fields.emplace_back( ( val & i ) == i );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
struct ExdHeader
|
|
||||||
{
|
|
||||||
char magic[0x4];
|
|
||||||
uint16_t unknown;
|
|
||||||
uint16_t unknown2;
|
|
||||||
uint32_t index_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ExdRecordIndex
|
|
||||||
{
|
|
||||||
uint32_t id;
|
|
||||||
uint32_t offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace xiv
|
|
||||||
{
|
|
||||||
namespace utils
|
|
||||||
{
|
|
||||||
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 ); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace xiv
|
|
||||||
{
|
|
||||||
namespace exd
|
|
||||||
{
|
|
||||||
|
|
||||||
Exd::Exd( std::shared_ptr<Exh> i_exh, const std::vector<std::shared_ptr<dat::File>>& i_files )
|
|
||||||
{
|
|
||||||
_exh = i_exh;
|
|
||||||
_files = i_files;
|
|
||||||
|
|
||||||
|
|
||||||
// Iterates over all the files
|
|
||||||
const uint32_t member_count = _exh->get_members().size();
|
|
||||||
for ( auto &file_ptr : _files )
|
|
||||||
{
|
|
||||||
// Get a stream
|
|
||||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
|
||||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
|
||||||
|
|
||||||
// Extract the header and skip to the record indices
|
|
||||||
auto exd_header = extract< ExdHeader >( iss );
|
|
||||||
iss.seekg( 0x20 );
|
|
||||||
|
|
||||||
// Preallocate and extract the record_indices
|
|
||||||
const uint32_t record_count = exd_header.index_size / sizeof( ExdRecordIndex );
|
|
||||||
std::vector< ExdRecordIndex > record_indices;
|
|
||||||
record_indices.reserve( record_count );
|
|
||||||
for ( uint32_t i = 0; i < record_count; ++i )
|
|
||||||
{
|
|
||||||
auto recordIndex = extract< ExdRecordIndex >( iss );
|
|
||||||
_idCache[recordIndex.id] = ExdCacheEntry{file_ptr, recordIndex.offset};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Exd::~Exd()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<Field> Exd::get_row( uint32_t id, uint32_t subRow )
|
|
||||||
{
|
|
||||||
|
|
||||||
auto cacheEntryIt = _idCache.find( id );
|
|
||||||
if( cacheEntryIt == _idCache.end() )
|
|
||||||
throw std::runtime_error( "Id not found: " + std::to_string( id ) );
|
|
||||||
|
|
||||||
// Iterates over all the files
|
|
||||||
const uint32_t member_count = _exh->get_members().size();
|
|
||||||
auto& file_ptr = cacheEntryIt->second.file;
|
|
||||||
|
|
||||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
|
||||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
|
||||||
|
|
||||||
// Get the vector fields for the given record and preallocate it
|
|
||||||
auto fields = _data[id];
|
|
||||||
fields.reserve( member_count );
|
|
||||||
iss.seekg( cacheEntryIt->second.offset + 6 );
|
|
||||||
|
|
||||||
uint8_t subRows = *reinterpret_cast< uint8_t* >( &dataCpy[ cacheEntryIt->second.offset + 5 ] );
|
|
||||||
|
|
||||||
if( subRow >= subRows )
|
|
||||||
throw std::runtime_error( "Out of bounds sub-row!" );
|
|
||||||
|
|
||||||
int offset = cacheEntryIt->second.offset + 6 + ( subRow * _exh->get_header().data_offset + 2 * ( subRow + 1 ) );
|
|
||||||
|
|
||||||
for( auto& member_entry : _exh->get_exh_members() )
|
|
||||||
{
|
|
||||||
// Seek to the position of the member to extract.
|
|
||||||
// 6 is because we have uint32_t/uint16_t at the start of each record
|
|
||||||
iss.seekg( offset + member_entry.offset );
|
|
||||||
|
|
||||||
// Switch depending on the type to extract
|
|
||||||
switch( member_entry.type )
|
|
||||||
{
|
|
||||||
case DataType::string:
|
|
||||||
// Extract the offset to the actual string
|
|
||||||
// Seek to it then extract the actual string
|
|
||||||
{
|
|
||||||
throw std::runtime_error( "String not implemented for variant 2!" );
|
|
||||||
//auto string_offset = extract<uint32_t>( iss, "string_offset", false );
|
|
||||||
//iss.seekg( cacheEntryIt->second.offset + 6 + _exh->get_header().data_offset + string_offset );
|
|
||||||
//fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::boolean:
|
|
||||||
fields.emplace_back( extract<bool>( iss, "bool" ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::int8:
|
|
||||||
fields.emplace_back( extract<int8_t>( iss, "int8_t" ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint8:
|
|
||||||
fields.emplace_back( extract<uint8_t>( iss, "uint8_t" ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::int16:
|
|
||||||
fields.emplace_back( extract<int16_t>( iss, "int16_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint16:
|
|
||||||
fields.emplace_back( extract<uint16_t>( iss, "uint16_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::int32:
|
|
||||||
fields.emplace_back( extract<int32_t>( iss, "int32_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint32:
|
|
||||||
fields.emplace_back( extract<uint32_t>( iss, "uint32_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::float32:
|
|
||||||
fields.emplace_back( extract<float>( iss, "float", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint64:
|
|
||||||
fields.emplace_back( extract<uint64_t>( iss, "uint64_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
auto type = static_cast< uint16_t >( member_entry.type );
|
|
||||||
if( type < 0x19 || type > 0x20 )
|
|
||||||
throw std::runtime_error("Unknown DataType: " + std::to_string( type ));
|
|
||||||
uint64_t val = extract< uint64_t >( iss, "bool" );
|
|
||||||
int32_t shift = type - 0x19;
|
|
||||||
int32_t i = 1 << shift;
|
|
||||||
val &= i;
|
|
||||||
fields.emplace_back( ( val & i ) == i );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fields;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const std::vector<Field> Exd::get_row( uint32_t id )
|
|
||||||
{
|
|
||||||
|
|
||||||
auto cacheEntryIt = _idCache.find( id );
|
|
||||||
if( cacheEntryIt == _idCache.end() )
|
|
||||||
throw std::runtime_error( "Id not found: " + std::to_string( id ) );
|
|
||||||
|
|
||||||
// Iterates over all the files
|
|
||||||
const uint32_t member_count = _exh->get_members().size();
|
|
||||||
auto& file_ptr = cacheEntryIt->second.file;
|
|
||||||
|
|
||||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
|
||||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
|
||||||
|
|
||||||
// Get the vector fields for the given record and preallocate it
|
|
||||||
auto fields = _data[id];
|
|
||||||
fields.reserve( member_count );
|
|
||||||
iss.seekg( cacheEntryIt->second.offset + 6 );
|
|
||||||
|
|
||||||
uint8_t subRows = *reinterpret_cast< uint8_t* >( &dataCpy[ cacheEntryIt->second.offset + 5 ] );
|
|
||||||
|
|
||||||
for( auto& member_entry : _exh->get_exh_members() )
|
|
||||||
{
|
|
||||||
// Seek to the position of the member to extract.
|
|
||||||
// 6 is because we have uint32_t/uint16_t at the start of each record
|
|
||||||
iss.seekg( cacheEntryIt->second.offset + 6 + member_entry.offset );
|
|
||||||
|
|
||||||
// Switch depending on the type to extract
|
|
||||||
switch( member_entry.type )
|
|
||||||
{
|
|
||||||
case DataType::string:
|
|
||||||
// Extract the offset to the actual string
|
|
||||||
// Seek to it then extract the actual string
|
|
||||||
{
|
|
||||||
auto string_offset = extract<uint32_t>( iss, "string_offset", false );
|
|
||||||
iss.seekg( cacheEntryIt->second.offset + 6 + _exh->get_header().data_offset + string_offset );
|
|
||||||
fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::boolean:
|
|
||||||
fields.emplace_back( extract<bool>( iss, "bool" ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::int8:
|
|
||||||
fields.emplace_back( extract<int8_t>( iss, "int8_t" ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint8:
|
|
||||||
fields.emplace_back( extract<uint8_t>( iss, "uint8_t" ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::int16:
|
|
||||||
fields.emplace_back( extract<int16_t>( iss, "int16_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint16:
|
|
||||||
fields.emplace_back( extract<uint16_t>( iss, "uint16_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::int32:
|
|
||||||
fields.emplace_back( extract<int32_t>( iss, "int32_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint32:
|
|
||||||
fields.emplace_back( extract<uint32_t>( iss, "uint32_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::float32:
|
|
||||||
fields.emplace_back( extract<float>( iss, "float", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint64:
|
|
||||||
fields.emplace_back( extract<uint64_t>( iss, "uint64_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
auto type = static_cast< uint16_t >( member_entry.type );
|
|
||||||
if( type < 0x19 || type > 0x20 )
|
|
||||||
throw std::runtime_error("Unknown DataType: " + std::to_string( type ));
|
|
||||||
uint64_t val = extract< uint64_t >( iss, "bool" );
|
|
||||||
int32_t shift = type - 0x19;
|
|
||||||
int32_t i = 1 << shift;
|
|
||||||
val &= i;
|
|
||||||
fields.emplace_back( ( val & i ) == i );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fields;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all rows
|
|
||||||
const std::map<uint32_t, std::vector<Field>>& Exd::get_rows()
|
|
||||||
{
|
|
||||||
// Iterates over all the files
|
|
||||||
const uint32_t member_count = _exh->get_members().size();
|
|
||||||
for( auto& file_ptr : _files )
|
|
||||||
{
|
|
||||||
// Get a stream
|
|
||||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
|
||||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
|
||||||
|
|
||||||
// Extract the header and skip to the record indices
|
|
||||||
auto exd_header = extract<ExdHeader>( iss );
|
|
||||||
iss.seekg( 0x20 );
|
|
||||||
|
|
||||||
// Preallocate and extract the record_indices
|
|
||||||
const uint32_t record_count = exd_header.index_size / sizeof( ExdRecordIndex );
|
|
||||||
std::vector<ExdRecordIndex> record_indices;
|
|
||||||
record_indices.reserve( record_count );
|
|
||||||
for( uint32_t i = 0; i < record_count; ++i )
|
|
||||||
{
|
|
||||||
record_indices.emplace_back( extract<ExdRecordIndex>( iss ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( auto& record_index : record_indices )
|
|
||||||
{
|
|
||||||
// Get the vector fields for the given record and preallocate it
|
|
||||||
auto& fields = _data[record_index.id];
|
|
||||||
fields.reserve( member_count );
|
|
||||||
|
|
||||||
for( auto& member_entry : _exh->get_exh_members() )
|
|
||||||
//for( auto& member_entry : _exh->get_members() )
|
|
||||||
{
|
|
||||||
// Seek to the position of the member to extract.
|
|
||||||
// 6 is because we have uint32_t/uint16_t at the start of each record
|
|
||||||
iss.seekg( record_index.offset + 6 + member_entry.offset );
|
|
||||||
|
|
||||||
// Switch depending on the type to extract
|
|
||||||
switch( member_entry.type )
|
|
||||||
{
|
|
||||||
case DataType::string:
|
|
||||||
// Extract the offset to the actual string
|
|
||||||
// Seek to it then extract the actual string
|
|
||||||
{
|
|
||||||
auto string_offset = extract<uint32_t>( iss, "string_offset", false );
|
|
||||||
iss.seekg( record_index.offset + 6 + _exh->get_header().data_offset + string_offset );
|
|
||||||
fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::boolean:
|
|
||||||
fields.emplace_back( extract<bool>( iss, "bool" ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::int8:
|
|
||||||
fields.emplace_back( extract<int8_t>( iss, "int8_t" ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint8:
|
|
||||||
fields.emplace_back( extract<uint8_t>( iss, "uint8_t" ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::int16:
|
|
||||||
fields.emplace_back( extract<int16_t>( iss, "int16_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint16:
|
|
||||||
fields.emplace_back( extract<uint16_t>( iss, "uint16_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::int32:
|
|
||||||
fields.emplace_back( extract<int32_t>( iss, "int32_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint32:
|
|
||||||
fields.emplace_back( extract<uint32_t>( iss, "uint32_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::float32:
|
|
||||||
fields.emplace_back( extract<float>( iss, "float", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DataType::uint64:
|
|
||||||
fields.emplace_back( extract<uint64_t>( iss, "uint64_t", false ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
auto type = static_cast< uint16_t >( member_entry.type );
|
|
||||||
if( type < 0x19 || type > 0x20 )
|
|
||||||
throw std::runtime_error("Unknown DataType: " + std::to_string( type ));
|
|
||||||
uint64_t val = extract< uint64_t >( iss, "bool" );
|
|
||||||
int32_t shift = type - 0x19;
|
|
||||||
int32_t i = 1 << shift;
|
|
||||||
val &= i;
|
|
||||||
fields.emplace_back( ( val & i ) == i );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
56
deps/datReader/Exd.h
vendored
56
deps/datReader/Exd.h
vendored
|
@ -8,15 +8,13 @@
|
||||||
|
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::exd
|
||||||
{
|
|
||||||
namespace exd
|
|
||||||
{
|
{
|
||||||
|
|
||||||
class Exh;
|
class Exh;
|
||||||
|
|
||||||
// Field type containing all the possible types in the data files
|
// Field type containing all the possible types in the data files
|
||||||
using Field = std::variant<
|
using Field = std::variant<
|
||||||
std::string,
|
std::string,
|
||||||
bool,
|
bool,
|
||||||
int8_t,
|
int8_t,
|
||||||
|
@ -27,40 +25,44 @@ using Field = std::variant<
|
||||||
uint32_t,
|
uint32_t,
|
||||||
float,
|
float,
|
||||||
uint64_t >;
|
uint64_t >;
|
||||||
|
|
||||||
struct ExdCacheEntry
|
|
||||||
{
|
|
||||||
std::shared_ptr<dat::File> file;
|
|
||||||
uint32_t offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Data for a given language
|
struct ExdCacheEntry
|
||||||
class Exd
|
{
|
||||||
{
|
std::shared_ptr< dat::File > file;
|
||||||
public:
|
uint32_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Data for a given language
|
||||||
|
class Exd
|
||||||
|
{
|
||||||
|
public:
|
||||||
// i_exh: the header
|
// i_exh: the header
|
||||||
// i_files: the multiple exd files
|
// 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( std::shared_ptr< Exh > i_exh, const std::vector< std::shared_ptr< dat::File>>& i_files );
|
||||||
|
|
||||||
~Exd();
|
~Exd();
|
||||||
|
|
||||||
// Get a row by its id
|
// Get a row by its id
|
||||||
const std::vector<Field> get_row(uint32_t id);
|
const std::vector< Field > get_row( uint32_t id );
|
||||||
|
|
||||||
// Get a row by its id and sub-row
|
// Get a row by its id and sub-row
|
||||||
const std::vector<Field> get_row(uint32_t id, uint32_t subRow);
|
const std::vector< Field > get_row( uint32_t id, uint32_t subRow );
|
||||||
|
|
||||||
// Get all rows
|
// Get all rows
|
||||||
const std::map<uint32_t, std::vector<Field>>& get_rows();
|
const std::map< uint32_t, std::vector< Field>>& get_rows();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Data indexed by the ID of the row, the vector is field with the same order as exh.members
|
// Data indexed by the ID of the row, the vector is field with the same order as exh.members
|
||||||
std::map<uint32_t, std::vector<Field>> _data;
|
std::map< uint32_t, std::vector< Field>> _data;
|
||||||
std::vector<std::shared_ptr<dat::File>> _files;
|
std::vector< std::shared_ptr< dat::File>> _files;
|
||||||
std::shared_ptr<Exh> _exh;
|
std::shared_ptr< Exh > _exh;
|
||||||
std::map< uint32_t, ExdCacheEntry > _idCache;
|
std::map< uint32_t, ExdCacheEntry > _idCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // XIV_EXD_EXD_H
|
#endif // XIV_EXD_EXD_H
|
||||||
|
|
113
deps/datReader/ExdCat.cpp
vendored
113
deps/datReader/ExdCat.cpp
vendored
|
@ -9,74 +9,73 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// Suffix of the filenames given a language
|
// Suffix of the filenames given a language
|
||||||
std::map<xiv::exd::Language, std::string> language_map =
|
std::map<xiv::exd::Language, std::string> language_map =
|
||||||
{{xiv::exd::Language::none, ""},
|
{
|
||||||
{xiv::exd::Language::ja, "_ja"},
|
{xiv::exd::Language::none, ""},
|
||||||
{xiv::exd::Language::en, "_en"},
|
{xiv::exd::Language::ja, "_ja"},
|
||||||
{xiv::exd::Language::de, "_de"},
|
{xiv::exd::Language::en, "_en"},
|
||||||
{xiv::exd::Language::fr, "_fr"},
|
{xiv::exd::Language::de, "_de"},
|
||||||
{xiv::exd::Language::chs, "_chs"}};
|
{xiv::exd::Language::fr, "_fr"},
|
||||||
|
{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 )
|
||||||
|
{
|
||||||
|
//XIV_INFO(xiv_exd_logger, "Initializing Cat with name: " << i_name);
|
||||||
|
// creates the header .exh
|
||||||
|
{
|
||||||
|
auto header_file = i_game_data.getFile( "exd/" + i_name + ".exh" );
|
||||||
|
_header = std::shared_ptr< Exh >( new Exh( *header_file ) );
|
||||||
|
|
||||||
Cat::Cat(dat::GameData& i_game_data, const std::string& i_name) :
|
}
|
||||||
_name(i_name)
|
|
||||||
|
for( auto language: _header->get_languages() )
|
||||||
|
{
|
||||||
|
// chs not yet in data files
|
||||||
|
if( language == Language::en || language == Language::none )
|
||||||
{
|
{
|
||||||
//XIV_INFO(xiv_exd_logger, "Initializing Cat with name: " << i_name);
|
// Get all the files for a given category/language, in case of multiple range of IDs in separate files (like Quest)
|
||||||
// creates the header .exh
|
std::vector< std::shared_ptr< dat::File>> files;
|
||||||
{
|
for( auto& exd_def: _header->get_exd_defs() )
|
||||||
auto header_file = i_game_data.getFile("exd/" + i_name + ".exh");
|
{
|
||||||
_header = std::shared_ptr< Exh >( new Exh( *header_file ) );
|
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
|
||||||
for(auto language: _header->get_languages())
|
_data[ language ] = std::make_unique< Exd >( _header, files );
|
||||||
{
|
|
||||||
// chs not yet in data files
|
|
||||||
if (language == Language::en || language == Language::none)
|
|
||||||
{
|
|
||||||
// Get all the files for a given category/language, in case of multiple range of IDs in separate files (like Quest)
|
|
||||||
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") );
|
|
||||||
}
|
|
||||||
// Instantiate the data for this language
|
|
||||||
_data[language] = std::unique_ptr<Exd>(new Exd(_header, files));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Cat::~Cat()
|
Cat::~Cat()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& Cat::get_name() const
|
const std::string& Cat::get_name() const
|
||||||
{
|
{
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Exh& Cat::get_header() const
|
const Exh& Cat::get_header() const
|
||||||
{
|
{
|
||||||
return *_header;
|
return *_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Exd& Cat::get_data_ln(Language i_language) const
|
const Exd& Cat::get_data_ln( Language i_language ) const
|
||||||
{
|
{
|
||||||
auto ln_it = _data.find(i_language);
|
auto ln_it = _data.find( i_language );
|
||||||
if (ln_it == _data.end())
|
if( ln_it == _data.end() )
|
||||||
{
|
{
|
||||||
throw std::runtime_error("No data for language: " + std::to_string(uint16_t(i_language)));
|
throw std::runtime_error( "No data for language: " + std::to_string( uint16_t( i_language ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return *(ln_it->second);
|
return *( ln_it->second );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
2
deps/datReader/ExdCat.h
vendored
2
deps/datReader/ExdCat.h
vendored
|
@ -4,7 +4,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <experimental/filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
#include "bparse.h"
|
#include "bparse.h"
|
||||||
#include "Exd.h"
|
#include "Exd.h"
|
||||||
|
|
126
deps/datReader/ExdData.cpp
vendored
126
deps/datReader/ExdData.cpp
vendored
|
@ -7,50 +7,47 @@
|
||||||
|
|
||||||
#include "ExdCat.h"
|
#include "ExdCat.h"
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::exd {
|
||||||
{
|
|
||||||
namespace exd
|
ExdData::ExdData( dat::GameData& i_game_data ) try :
|
||||||
|
_game_data( i_game_data )
|
||||||
{
|
{
|
||||||
|
//XIV_INFO(xiv_exd_logger, "Initializing ExdData");
|
||||||
|
|
||||||
ExdData::ExdData(dat::GameData& i_game_data) try :
|
// Fetch the root.exl and get a stream from it
|
||||||
_game_data(i_game_data)
|
auto root_exl = i_game_data.getFile( "exd/root.exl" );
|
||||||
{
|
std::vector< char > dataCpy = root_exl->get_data_sections().front();
|
||||||
//XIV_INFO(xiv_exd_logger, "Initializing ExdData");
|
xiv::utils::stream::vectorwrapbuf< char > databuf( dataCpy );
|
||||||
|
std::istream stream( &databuf );
|
||||||
|
|
||||||
// Fetch the root.exl and get a stream from it
|
// Iterates over the lines while skipping the first one
|
||||||
auto root_exl = i_game_data.getFile("exd/root.exl");
|
std::string line;
|
||||||
std::vector< char > dataCpy = root_exl->get_data_sections().front();
|
std::getline( stream, line ); // extract first line EXLT,2
|
||||||
xiv::utils::stream::vectorwrapbuf<char> databuf(dataCpy);
|
std::getline( stream, line );
|
||||||
std::istream stream(&databuf);
|
|
||||||
|
|
||||||
// Iterates over the lines while skipping the first one
|
// Until the EOF
|
||||||
std::string line;
|
while( !line.empty() )
|
||||||
std::getline(stream, line); // extract first line EXLT,2
|
{
|
||||||
std::getline(stream, line);
|
// Format is cat_name,XX
|
||||||
|
// XX being an internal identifier
|
||||||
|
// Get only the cat_name
|
||||||
|
auto sep = line.find( ',' );
|
||||||
|
auto category = line.substr( 0, sep );
|
||||||
|
|
||||||
// Until the EOF
|
// Add to the list of category name
|
||||||
while (!line.empty())
|
// creates the empty category in the cats map
|
||||||
{
|
// instantiate the creation mutex for this category
|
||||||
// Format is cat_name,XX
|
_cat_names.push_back( category );
|
||||||
// XX being an internal identifier
|
_cats[ category ] = std::unique_ptr< Cat >();
|
||||||
// Get only the cat_name
|
_cat_creation_mutexes[ category ] = std::make_unique< std::mutex >();
|
||||||
auto sep = line.find(',');
|
|
||||||
auto category = line.substr(0, sep);
|
|
||||||
|
|
||||||
// Add to the list of category name
|
std::getline( stream, line );
|
||||||
// creates the empty category in the cats map
|
}
|
||||||
// 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());
|
|
||||||
|
|
||||||
std::getline(stream, line);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(std::exception& e)
|
catch( std::exception& e )
|
||||||
{
|
{
|
||||||
// In case of failure here, client is supposed to catch the exception because it is not recoverable on our side
|
// In case of failure here, client is supposed to catch the exception because it is not recoverable on our side
|
||||||
throw std::runtime_error( "ExdData initialization failed: " + std::string( e.what() ) );
|
throw std::runtime_error( "ExdData initialization failed: " + std::string( e.what() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
ExdData::~ExdData()
|
ExdData::~ExdData()
|
||||||
|
@ -58,43 +55,42 @@ ExdData::~ExdData()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string>& ExdData::get_cat_names() const
|
const std::vector< std::string >& ExdData::get_cat_names() const
|
||||||
{
|
{
|
||||||
return _cat_names;
|
return _cat_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Cat& ExdData::get_category(const std::string& i_cat_name)
|
const Cat& ExdData::get_category( const std::string& i_cat_name )
|
||||||
{
|
{
|
||||||
// Get the category from its name
|
// Get the category from its name
|
||||||
auto cat_it = _cats.find(i_cat_name);
|
auto cat_it = _cats.find( i_cat_name );
|
||||||
if (cat_it == _cats.end())
|
if( cat_it == _cats.end() )
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Category not found: " + i_cat_name);
|
throw std::runtime_error( "Category not found: " + i_cat_name );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cat_it->second)
|
if( cat_it->second )
|
||||||
{
|
{
|
||||||
// If valid return it
|
// If valid return it
|
||||||
return *(cat_it->second);
|
return *( cat_it->second );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If not, create it and return it
|
// If not, create it and return it
|
||||||
create_category(i_cat_name);
|
create_category( i_cat_name );
|
||||||
return *(_cats[i_cat_name]);
|
return *( _cats[ i_cat_name ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExdData::create_category(const std::string& i_cat_name)
|
void ExdData::create_category( const std::string& i_cat_name )
|
||||||
{
|
{
|
||||||
// Lock mutex in this scope
|
// Lock mutex in this scope
|
||||||
std::lock_guard<std::mutex> lock(*(_cat_creation_mutexes[i_cat_name]));
|
std::lock_guard< std::mutex > lock( *( _cat_creation_mutexes[ i_cat_name ] ) );
|
||||||
// Maybe after unlocking it has already been created, so check (most likely if it blocked)
|
// Maybe after unlocking it has already been created, so check (most likely if it blocked)
|
||||||
if (!_cats[i_cat_name])
|
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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
4
deps/datReader/ExdData.h
vendored
4
deps/datReader/ExdData.h
vendored
|
@ -5,7 +5,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <experimental/filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ namespace xiv
|
||||||
const Cat& get_category(const std::string& i_cat_name);
|
const Cat& get_category(const std::string& i_cat_name);
|
||||||
|
|
||||||
// Export in csv in base flder i_ouput_path
|
// 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:
|
protected:
|
||||||
// Lazy instantiation of category
|
// Lazy instantiation of category
|
||||||
|
|
74
deps/datReader/Exh.cpp
vendored
74
deps/datReader/Exh.cpp
vendored
|
@ -7,71 +7,69 @@
|
||||||
|
|
||||||
using xiv::utils::bparse::extract;
|
using xiv::utils::bparse::extract;
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::exd
|
||||||
{
|
|
||||||
namespace exd
|
|
||||||
{
|
|
||||||
Exh::Exh(const dat::File& i_file)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Exh::Exh( const dat::File& i_file )
|
||||||
|
{
|
||||||
// Get a stream from the file
|
// Get a stream from the file
|
||||||
std::vector< char > dataCpy = i_file.get_data_sections().front();
|
std::vector< char > dataCpy = i_file.get_data_sections().front();
|
||||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||||
|
|
||||||
// Extract header and skip to member definitions
|
// Extract header and skip to member definitions
|
||||||
_header = extract<ExhHeader>(iss);
|
_header = extract< ExhHeader >( iss );
|
||||||
iss.seekg(0x20);
|
iss.seekg( 0x20 );
|
||||||
|
|
||||||
// Extract all the members and feed the _members map
|
// Extract all the members and feed the _members map
|
||||||
for (auto i = 0; i < _header.field_count; ++i)
|
for( auto i = 0; i < _header.field_count; ++i )
|
||||||
{
|
{
|
||||||
auto member = extract<ExhMember>(iss);
|
auto member = extract< ExhMember >( iss );
|
||||||
_members[member.offset] = member;
|
_members[ member.offset ] = member;
|
||||||
_exh_defs.push_back( member );
|
_exh_defs.push_back( member );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract all the exd_defs
|
// Extract all the exd_defs
|
||||||
_exd_defs.reserve(_header.exd_count);
|
_exd_defs.reserve( _header.exd_count );
|
||||||
for (auto i = 0; i < _header.exd_count; ++i)
|
for( auto i = 0; i < _header.exd_count; ++i )
|
||||||
{
|
{
|
||||||
_exd_defs.emplace_back(extract<ExhExdDef>(iss));
|
_exd_defs.emplace_back( extract< ExhExdDef >( iss ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract all the languages
|
// Extract all the languages
|
||||||
_languages.reserve(_header.language_count);
|
_languages.reserve( _header.language_count );
|
||||||
for (auto i = 0; i < _header.language_count; ++i)
|
for( auto i = 0; i < _header.language_count; ++i )
|
||||||
{
|
{
|
||||||
_languages.emplace_back(Language(extract<uint16_t>(iss, "language")));
|
_languages.emplace_back( Language( extract< uint16_t >( iss, "language" ) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Exh::~Exh()
|
Exh::~Exh()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const ExhHeader& Exh::get_header() const
|
const ExhHeader& Exh::get_header() const
|
||||||
{
|
{
|
||||||
return _header;
|
return _header;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<ExhExdDef>& Exh::get_exd_defs() const
|
const std::vector< ExhExdDef >& Exh::get_exd_defs() const
|
||||||
{
|
{
|
||||||
return _exd_defs;
|
return _exd_defs;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<Language>& Exh::get_languages() const
|
const std::vector< Language >& Exh::get_languages() const
|
||||||
{
|
{
|
||||||
return _languages;
|
return _languages;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<uint32_t, ExhMember>& Exh::get_members() const
|
const std::map< uint32_t, ExhMember >& Exh::get_members() const
|
||||||
{
|
{
|
||||||
return _members;
|
return _members;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<ExhMember>& Exh::get_exh_members() const
|
const std::vector< ExhMember >& Exh::get_exh_members() const
|
||||||
{
|
{
|
||||||
return _exh_defs;
|
return _exh_defs;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
190
deps/datReader/Exh.h
vendored
190
deps/datReader/Exh.h
vendored
|
@ -5,99 +5,131 @@
|
||||||
|
|
||||||
#include "bparse.h"
|
#include "bparse.h"
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::exd
|
||||||
{
|
{
|
||||||
namespace exd
|
enum class DataType :
|
||||||
{
|
uint16_t
|
||||||
enum class DataType : uint16_t
|
{
|
||||||
{
|
string = 0,
|
||||||
string = 0,
|
boolean = 1,
|
||||||
boolean = 1,
|
int8 = 2,
|
||||||
int8 = 2,
|
uint8 = 3,
|
||||||
uint8 = 3,
|
int16 = 4,
|
||||||
int16 = 4,
|
uint16 = 5,
|
||||||
uint16 = 5,
|
int32 = 6,
|
||||||
int32 = 6,
|
uint32 = 7,
|
||||||
uint32 = 7,
|
float32 = 9,
|
||||||
float32 = 9,
|
uint64 = 11,
|
||||||
uint64 = 11,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct ExhHeader
|
struct ExhHeader
|
||||||
{
|
{
|
||||||
char magic[0x4];
|
char magic[0x4];
|
||||||
uint16_t unknown;
|
uint16_t unknown;
|
||||||
uint16_t data_offset;
|
uint16_t data_offset;
|
||||||
uint16_t field_count;
|
uint16_t field_count;
|
||||||
uint16_t exd_count;
|
uint16_t exd_count;
|
||||||
uint16_t language_count;
|
uint16_t language_count;
|
||||||
uint16_t unknown1;
|
uint16_t unknown1;
|
||||||
uint8_t u2;
|
uint8_t u2;
|
||||||
uint8_t variant;
|
uint8_t variant;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExhMember
|
struct ExhMember
|
||||||
{
|
{
|
||||||
DataType type;
|
DataType type;
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExhExdDef
|
struct ExhExdDef
|
||||||
{
|
{
|
||||||
uint32_t start_id;
|
uint32_t start_id;
|
||||||
uint32_t count_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 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
|
||||||
{
|
{
|
||||||
namespace dat
|
class File;
|
||||||
{
|
}
|
||||||
class File;
|
|
||||||
}
|
|
||||||
namespace exd
|
|
||||||
{
|
|
||||||
|
|
||||||
enum Language : uint16_t;
|
namespace exd
|
||||||
|
{
|
||||||
|
|
||||||
// Header file for exd data
|
enum Language :
|
||||||
class Exh
|
uint16_t;
|
||||||
{
|
|
||||||
public:
|
|
||||||
// The header file
|
|
||||||
Exh( const dat::File& i_file );
|
|
||||||
~Exh();
|
|
||||||
|
|
||||||
const ExhHeader& get_header() const;
|
// Header file for exd data
|
||||||
const std::vector<ExhExdDef>& get_exd_defs() const;
|
class Exh
|
||||||
const std::vector<Language>& get_languages() const;
|
{
|
||||||
const std::map<uint32_t, ExhMember>& get_members() const;
|
public:
|
||||||
const std::vector<ExhMember>& get_exh_members() const;
|
// The header file
|
||||||
|
Exh( const dat::File& i_file );
|
||||||
|
|
||||||
protected:
|
~Exh();
|
||||||
ExhHeader _header;
|
|
||||||
// Members of the datastruct ordered(indexed) by offset
|
|
||||||
std::map<uint32_t, ExhMember> _members;
|
|
||||||
std::vector<ExhMember> _exh_defs;
|
|
||||||
std::vector<ExhExdDef> _exd_defs;
|
|
||||||
std::vector<Language> _languages;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
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:
|
||||||
|
ExhHeader _header;
|
||||||
|
// Members of the datastruct ordered(indexed) by offset
|
||||||
|
std::map< uint32_t, ExhMember > _members;
|
||||||
|
std::vector< ExhMember > _exh_defs;
|
||||||
|
std::vector< ExhExdDef > _exd_defs;
|
||||||
|
std::vector< Language > _languages;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // XIV_EXD_EXH_H
|
#endif // XIV_EXD_EXH_H
|
||||||
|
|
59
deps/datReader/File.cpp
vendored
59
deps/datReader/File.cpp
vendored
|
@ -2,44 +2,41 @@
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
|
||||||
namespace dat
|
|
||||||
{
|
{
|
||||||
|
|
||||||
File::File() :
|
File::File() :
|
||||||
_type(FileType::empty)
|
_type( FileType::empty )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
File::~File()
|
File::~File()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FileType File::get_type() const
|
FileType File::get_type() const
|
||||||
{
|
{
|
||||||
return _type;
|
return _type;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::vector<char>>& File::get_data_sections() const
|
const std::vector< std::vector< char>>& File::get_data_sections() const
|
||||||
{
|
{
|
||||||
return _data_sections;
|
return _data_sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<char>>& File::access_data_sections()
|
std::vector< std::vector< char>>& File::access_data_sections()
|
||||||
{
|
{
|
||||||
return _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 );
|
std::ofstream ofs( i_path.string(), std::ios_base::binary | std::ios_base::out );
|
||||||
for( auto& data_section : _data_sections )
|
for( auto& data_section : _data_sections )
|
||||||
{
|
{
|
||||||
ofs.write( data_section.data(), data_section.size() );
|
ofs.write( data_section.data(), data_section.size() );
|
||||||
}
|
}
|
||||||
ofs.close();
|
ofs.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
64
deps/datReader/File.h
vendored
64
deps/datReader/File.h
vendored
|
@ -3,54 +3,46 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <experimental/filesystem>
|
#include <filesystem>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "bparse.h"
|
#include "bparse.h"
|
||||||
|
|
||||||
|
namespace xiv::dat
|
||||||
namespace xiv
|
|
||||||
{
|
{
|
||||||
namespace dat
|
enum class FileType :
|
||||||
{
|
uint32_t
|
||||||
enum class FileType : uint32_t
|
{
|
||||||
{
|
empty = 1,
|
||||||
empty = 1,
|
standard = 2,
|
||||||
standard = 2,
|
model = 3,
|
||||||
model = 3,
|
texture = 4,
|
||||||
texture = 4,
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace xiv
|
class Dat;
|
||||||
{
|
|
||||||
namespace dat
|
|
||||||
{
|
|
||||||
|
|
||||||
class Dat;
|
// Basic file from the dats
|
||||||
|
class File
|
||||||
|
{
|
||||||
|
friend class Dat;
|
||||||
|
|
||||||
// Basic file from the dats
|
public:
|
||||||
class File
|
File();
|
||||||
{
|
|
||||||
friend class Dat;
|
|
||||||
public:
|
|
||||||
File();
|
|
||||||
~File();
|
|
||||||
|
|
||||||
FileType get_type() const;
|
~File();
|
||||||
|
|
||||||
// Getters functions for the data in the file
|
FileType get_type() const;
|
||||||
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;
|
// Getters functions for the data in the file
|
||||||
|
const std::vector< std::vector< char>>& get_data_sections() const;
|
||||||
|
|
||||||
protected:
|
std::vector< std::vector< char>>& access_data_sections();
|
||||||
FileType _type;
|
|
||||||
std::vector<std::vector<char>> _data_sections;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
void exportToFile( const std::filesystem::path& i_path ) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FileType _type;
|
||||||
|
std::vector< std::vector< char>> _data_sections;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // XIV_DAT_FILE_H
|
#endif // XIV_DAT_FILE_H
|
||||||
|
|
453
deps/datReader/GameData.cpp
vendored
453
deps/datReader/GameData.cpp
vendored
|
@ -11,312 +11,315 @@
|
||||||
#include "DatCat.h"
|
#include "DatCat.h"
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
// Relation between category number and category name
|
||||||
// Relation between category number and category name
|
// These names are taken straight from the exe, it helps resolve dispatching when getting files by path
|
||||||
// These names are taken straight from the exe, it helps resolve dispatching when getting files by path
|
|
||||||
|
|
||||||
std::unordered_map< std::string, uint32_t > categoryNameToIdMap =
|
std::unordered_map< std::string, uint32_t > categoryNameToIdMap =
|
||||||
{{"common", 0x00},
|
{ { "common", 0x00 },
|
||||||
{"bgcommon", 0x01},
|
{ "bgcommon", 0x01 },
|
||||||
{"bg", 0x02},
|
{ "bg", 0x02 },
|
||||||
{"cut", 0x03},
|
{ "cut", 0x03 },
|
||||||
{"chara", 0x04},
|
{ "chara", 0x04 },
|
||||||
{"shader", 0x05},
|
{ "shader", 0x05 },
|
||||||
{"ui", 0x06},
|
{ "ui", 0x06 },
|
||||||
{"sound", 0x07},
|
{ "sound", 0x07 },
|
||||||
{"vfx", 0x08},
|
{ "vfx", 0x08 },
|
||||||
{"ui_script", 0x09},
|
{ "ui_script", 0x09 },
|
||||||
{"exd", 0x0A},
|
{ "exd", 0x0A },
|
||||||
{"game_script", 0x0B},
|
{ "game_script", 0x0B },
|
||||||
{"music", 0x0C}
|
{ "music", 0x0C }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map< uint32_t, std::string > categoryIdToNameMap =
|
std::unordered_map< uint32_t, std::string > categoryIdToNameMap =
|
||||||
{{0x00, "common"},
|
{ { 0x00, "common" },
|
||||||
{0x01, "bgcommon"},
|
{ 0x01, "bgcommon" },
|
||||||
{0x02, "bg"},
|
{ 0x02, "bg" },
|
||||||
{0x03, "cut"},
|
{ 0x03, "cut" },
|
||||||
{0x04, "chara"},
|
{ 0x04, "chara" },
|
||||||
{0x05, "shader"},
|
{ 0x05, "shader" },
|
||||||
{0x06, "ui"},
|
{ 0x06, "ui" },
|
||||||
{0x07, "sound"},
|
{ 0x07, "sound" },
|
||||||
{0x08, "vfx"},
|
{ 0x08, "vfx" },
|
||||||
{0x09, "ui_script"},
|
{ 0x09, "ui_script" },
|
||||||
{0x0A, "exd"},
|
{ 0x0A, "exd" },
|
||||||
{0x0B, "game_script"},
|
{ 0x0B, "game_script" },
|
||||||
{0x0C, "music"}};
|
{ 0x0C, "music" } };
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
|
||||||
namespace dat
|
|
||||||
{
|
{
|
||||||
|
GameData::GameData( const std::filesystem::path& path ) try :
|
||||||
|
m_path( path )
|
||||||
|
{
|
||||||
|
int maxExLevel = 0;
|
||||||
|
|
||||||
GameData::GameData(const std::experimental::filesystem::path& path) try :
|
// msvc has retarded stdlib implementation
|
||||||
m_path(path)
|
#ifdef _WIN32
|
||||||
{
|
static constexpr auto sep = "\\";
|
||||||
int maxExLevel = 0;
|
#else
|
||||||
|
static constexpr auto sep = std::filesystem::path::preferred_separator;
|
||||||
|
#endif
|
||||||
|
|
||||||
// msvc has retarded stdlib implementation
|
// Determine which expansions are available
|
||||||
#ifdef _WIN32
|
while( std::filesystem::exists( std::filesystem::path(
|
||||||
static constexpr auto sep = "\\";
|
m_path.string() + sep + "ex" + std::to_string( maxExLevel + 1 ) + sep + "ex" + std::to_string( maxExLevel + 1 ) +
|
||||||
#else
|
".ver" ) ) )
|
||||||
static constexpr auto sep = std::experimental::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" ) ) )
|
|
||||||
{
|
|
||||||
maxExLevel++;
|
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 )
|
// Iterate over the files in path
|
||||||
{
|
for( auto it = std::filesystem::directory_iterator( m_path.string() + "//ffxiv" );
|
||||||
|
it != std::filesystem::directory_iterator(); ++it )
|
||||||
|
{
|
||||||
// Get the filename of the current element
|
// Get the filename of the current element
|
||||||
auto filename = it->path().filename().string();
|
auto filename = it->path().filename().string();
|
||||||
|
|
||||||
// If it contains ".win32.index" this is most likely a hit for a category
|
// If it contains ".win32.index" this is most likely a hit for a category
|
||||||
if( filename.find( ".win32.index" ) != std::string::npos && filename.find( ".win32.index2" ) == std::string::npos )
|
if( filename.find( ".win32.index" ) != std::string::npos && filename.find( ".win32.index2" ) == std::string::npos )
|
||||||
{
|
{
|
||||||
// Format of indexes is XX0000.win32.index, so fetch the hex number for category number
|
// Format of indexes is XX0000.win32.index, so fetch the hex number for category number
|
||||||
std::istringstream iss( filename.substr( 0, 2 ) );
|
std::istringstream iss( filename.substr( 0, 2 ) );
|
||||||
uint32_t cat_nb;
|
uint32_t cat_nb;
|
||||||
iss >> std::hex >> cat_nb;
|
iss >> std::hex >> cat_nb;
|
||||||
|
|
||||||
|
|
||||||
// Add to the list of category number
|
// Add to the list of category number
|
||||||
// creates the empty category in the cats map
|
// creates the empty category in the cats map
|
||||||
// instantiate the creation mutex for this category
|
// instantiate the creation mutex for this category
|
||||||
m_catNums.push_back( cat_nb );
|
m_catNums.push_back( cat_nb );
|
||||||
m_cats[cat_nb] = std::unique_ptr<Cat>();
|
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
|
// Check for expansion
|
||||||
for( int exNum = 1; exNum <= maxExLevel; exNum++ )
|
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::filesystem::exists( m_path.string() + sep +
|
||||||
int chunkCount = 0;
|
buildDatStr( "ex" + std::to_string( exNum ), cat_nb, exNum, chunkTest, "win32",
|
||||||
|
"index" ) ) )
|
||||||
for(int chunkTest = 0; chunkTest < 256; chunkTest++ )
|
{
|
||||||
{
|
m_exCats[ cat_nb ].exNumToChunkMap[ exNum ].chunkToCatMap[ chunkTest ] = std::unique_ptr< Cat >();
|
||||||
if( std::experimental::filesystem::exists( m_path.string() + sep + buildDatStr( "ex" + std::to_string( exNum ), cat_nb, exNum, chunkTest, "win32", "index" ) ) )
|
chunkCount++;
|
||||||
{
|
}
|
||||||
m_exCats[cat_nb].exNumToChunkMap[exNum].chunkToCatMap[chunkTest] = std::unique_ptr<Cat>();
|
|
||||||
chunkCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch( std::exception& e )
|
catch( std::exception& e )
|
||||||
{
|
{
|
||||||
// In case of failure here, client is supposed to catch the exception because it is not recoverable on our side
|
// In case of failure here, client is supposed to catch the exception because it is not recoverable on our side
|
||||||
throw std::runtime_error( "GameData initialization failed: " + std::string( e.what() ) );
|
throw std::runtime_error( "GameData initialization failed: " + std::string( e.what() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
GameData::~GameData()
|
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() );
|
char dat[1024];
|
||||||
return std::string( dat );
|
sprintf( dat, "%s/%02x%02x%02x.%s.%s", folder.c_str(), cat, exNum, chunk, platform.c_str(), type.c_str() );
|
||||||
}
|
return std::string( dat );
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<uint32_t>& GameData::getCatNumbers() const
|
const std::vector< uint32_t >& GameData::getCatNumbers() const
|
||||||
{
|
{
|
||||||
return m_catNums;
|
return m_catNums;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<File> GameData::getFile(const std::string& path)
|
std::unique_ptr< File > GameData::getFile( const std::string& path )
|
||||||
{
|
{
|
||||||
// Get the hashes, the category from the path then call the getFile of the category
|
// Get the hashes, the category from the path then call the getFile of the category
|
||||||
uint32_t dirHash;
|
uint32_t dirHash;
|
||||||
uint32_t filenameHash;
|
uint32_t filenameHash;
|
||||||
getHashes( path, dirHash, filenameHash );
|
getHashes( path, dirHash, filenameHash );
|
||||||
|
|
||||||
return getCategoryFromPath( path ).getFile( dirHash, filenameHash );
|
return getCategoryFromPath( path ).getFile( dirHash, filenameHash );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameData::doesFileExist(const std::string& path)
|
bool GameData::doesFileExist( const std::string& path )
|
||||||
{
|
{
|
||||||
uint32_t dirHash;
|
uint32_t dirHash;
|
||||||
uint32_t filenameHash;
|
uint32_t filenameHash;
|
||||||
getHashes( path, dirHash, filenameHash );
|
getHashes( path, dirHash, filenameHash );
|
||||||
|
|
||||||
return getCategoryFromPath( path ).doesFileExist( dirHash, filenameHash );
|
return getCategoryFromPath( path ).doesFileExist( dirHash, filenameHash );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameData::doesDirExist(const std::string& i_path)
|
bool GameData::doesDirExist( const std::string& i_path )
|
||||||
{
|
{
|
||||||
uint32_t dirHash;
|
uint32_t dirHash;
|
||||||
uint32_t filenameHash;
|
uint32_t filenameHash;
|
||||||
getHashes( i_path, dirHash, filenameHash );
|
getHashes( i_path, dirHash, filenameHash );
|
||||||
|
|
||||||
return getCategoryFromPath( i_path ).doesDirExist( dirHash );
|
return getCategoryFromPath( i_path ).doesDirExist( dirHash );
|
||||||
}
|
}
|
||||||
|
|
||||||
const Cat& GameData::getCategory(uint32_t catNum)
|
const Cat& GameData::getCategory( uint32_t catNum )
|
||||||
{
|
{
|
||||||
// Check that the category number exists
|
// Check that the category number exists
|
||||||
auto catIt = m_cats.find( catNum );
|
auto catIt = m_cats.find( catNum );
|
||||||
if( catIt == m_cats.end() )
|
if( catIt == m_cats.end() )
|
||||||
{
|
{
|
||||||
throw std::runtime_error( "Category not found: " + std::to_string( catNum ) );
|
throw std::runtime_error( "Category not found: " + std::to_string( catNum ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it exists and already instantiated return it
|
// If it exists and already instantiated return it
|
||||||
if( catIt->second )
|
if( catIt->second )
|
||||||
{
|
{
|
||||||
return *( catIt->second );
|
return *( catIt->second );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Else create it and return it
|
// Else create it and return it
|
||||||
createCategory( catNum );
|
createCategory( catNum );
|
||||||
return *( m_cats[catNum] );
|
return *( m_cats[ catNum ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Cat& GameData::getCategory(const std::string& catName)
|
const Cat& GameData::getCategory( const std::string& catName )
|
||||||
{
|
{
|
||||||
// Find the category number from the name
|
// Find the category number from the name
|
||||||
auto categoryNameToIdMapIt = ::categoryNameToIdMap.find( catName );
|
auto categoryNameToIdMapIt = ::categoryNameToIdMap.find( catName );
|
||||||
if( categoryNameToIdMapIt == ::categoryNameToIdMap.end() )
|
if( categoryNameToIdMapIt == ::categoryNameToIdMap.end() )
|
||||||
{
|
{
|
||||||
throw std::runtime_error( "Category not found: " + catName );
|
throw std::runtime_error( "Category not found: " + catName );
|
||||||
}
|
}
|
||||||
|
|
||||||
// From the category number return the category
|
// From the category number return the category
|
||||||
return getCategory( categoryNameToIdMapIt->second );
|
return getCategory( categoryNameToIdMapIt->second );
|
||||||
}
|
}
|
||||||
|
|
||||||
const Cat& GameData::getExCategory( const std::string& catName, uint32_t exNum, const std::string& path )
|
const Cat& GameData::getExCategory( const std::string& catName, uint32_t exNum, const std::string& path )
|
||||||
{
|
{
|
||||||
// Find the category number from the name
|
// Find the category number from the name
|
||||||
auto categoryMapIt = ::categoryNameToIdMap.find( catName );
|
auto categoryMapIt = ::categoryNameToIdMap.find( catName );
|
||||||
if( categoryMapIt == ::categoryNameToIdMap.end() )
|
if( categoryMapIt == ::categoryNameToIdMap.end() )
|
||||||
{
|
{
|
||||||
throw std::runtime_error( "Category not found: " + catName );
|
throw std::runtime_error( "Category not found: " + catName );
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t dirHash;
|
uint32_t dirHash;
|
||||||
uint32_t filenameHash;
|
uint32_t filenameHash;
|
||||||
getHashes( path, dirHash, filenameHash );
|
getHashes( path, dirHash, filenameHash );
|
||||||
|
|
||||||
for( auto const& chunk : m_exCats[categoryMapIt->second].exNumToChunkMap[exNum].chunkToCatMap )
|
for( auto const& chunk : m_exCats[ categoryMapIt->second ].exNumToChunkMap[ exNum ].chunkToCatMap )
|
||||||
{
|
{
|
||||||
if( !chunk.second )
|
if( !chunk.second )
|
||||||
createExCategory( categoryMapIt->second );
|
createExCategory( categoryMapIt->second );
|
||||||
|
|
||||||
if( chunk.second->doesFileExist( dirHash, filenameHash ) )
|
if( chunk.second->doesFileExist( dirHash, filenameHash ) )
|
||||||
{
|
{
|
||||||
return *( chunk.second );
|
return *( chunk.second );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error( "Chunk not found for path: " + path );
|
throw std::runtime_error( "Chunk not found for path: " + path );
|
||||||
}
|
}
|
||||||
|
|
||||||
const Cat& GameData::getCategoryFromPath(const std::string& path)
|
const Cat& GameData::getCategoryFromPath( const std::string& path )
|
||||||
{
|
{
|
||||||
// Find the first / in the string, paths are in the format CAT_NAME/..../.../../....
|
// Find the first / in the string, paths are in the format CAT_NAME/..../.../../....
|
||||||
auto firstSlashPos = path.find( '/' );
|
auto firstSlashPos = path.find( '/' );
|
||||||
if( firstSlashPos == std::string::npos )
|
if( firstSlashPos == std::string::npos )
|
||||||
{
|
{
|
||||||
throw std::runtime_error( "Path does not have a / char: " + path );
|
throw std::runtime_error( "Path does not have a / char: " + path );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( path.substr( firstSlashPos + 1, 2) == "ex" )
|
if( path.substr( firstSlashPos + 1, 2 ) == "ex" )
|
||||||
{
|
{
|
||||||
return getExCategory( path.substr( 0, firstSlashPos ), std::stoi( path.substr( firstSlashPos + 3, 1 ) ), path );
|
return getExCategory( path.substr( 0, firstSlashPos ), std::stoi( path.substr( firstSlashPos + 3, 1 ) ), path );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// From the sub string found beforethe first / get the category
|
// From the sub string found beforethe first / get the category
|
||||||
return getCategory( path.substr( 0, firstSlashPos ) );
|
return getCategory( path.substr( 0, firstSlashPos ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameData::getHashes(const std::string& path, uint32_t& dirHash, uint32_t& filenameHash) const
|
void GameData::getHashes( const std::string& path, uint32_t& dirHash, uint32_t& filenameHash ) const
|
||||||
{
|
{
|
||||||
// Convert the path to lowercase before getting the hashes
|
// Convert the path to lowercase before getting the hashes
|
||||||
std::string pathLower;
|
std::string pathLower;
|
||||||
pathLower.resize( path.size() );
|
pathLower.resize( path.size() );
|
||||||
std::transform( path.begin(), path.end(), pathLower.begin(), ::tolower );
|
std::transform( path.begin(), path.end(), pathLower.begin(), ::tolower );
|
||||||
|
|
||||||
// Find last / to separate dir from filename
|
// Find last / to separate dir from filename
|
||||||
auto lastSlashPos = pathLower.rfind( '/' );
|
auto lastSlashPos = pathLower.rfind( '/' );
|
||||||
if( lastSlashPos == std::string::npos )
|
if( lastSlashPos == std::string::npos )
|
||||||
{
|
{
|
||||||
throw std::runtime_error( "Path does not have a / char: " + path );
|
throw std::runtime_error( "Path does not have a / char: " + path );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dirPart = pathLower.substr( 0, lastSlashPos );
|
std::string dirPart = pathLower.substr( 0, lastSlashPos );
|
||||||
std::string filenamePart = pathLower.substr( lastSlashPos + 1 );
|
std::string filenamePart = pathLower.substr( lastSlashPos + 1 );
|
||||||
|
|
||||||
// Get the crc32 values from zlib, to compensate the final XOR 0xFFFFFFFF that isnot done in the exe we just reXOR
|
// Get the crc32 values from zlib, to compensate the final XOR 0xFFFFFFFF that isnot done in the exe we just reXOR
|
||||||
dirHash = crc32( 0, reinterpret_cast<const uint8_t*>( dirPart.data() ), dirPart.size() ) ^ 0xFFFFFFFF;
|
dirHash = crc32( 0, reinterpret_cast<const uint8_t*>( dirPart.data() ), dirPart.size() ) ^ 0xFFFFFFFF;
|
||||||
filenameHash = crc32( 0, reinterpret_cast<const uint8_t*>( filenamePart.data() ), filenamePart.size() ) ^ 0xFFFFFFFF;
|
filenameHash = crc32( 0, reinterpret_cast<const uint8_t*>( filenamePart.data() ), filenamePart.size() ) ^ 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameData::createCategory(uint32_t catNum)
|
void GameData::createCategory( uint32_t catNum )
|
||||||
{
|
{
|
||||||
// Lock mutex in this scope
|
// Lock mutex in this scope
|
||||||
std::lock_guard<std::mutex> lock( *( m_catCreationMutexes[catNum] ) );
|
std::lock_guard< std::mutex > lock( *( m_catCreationMutexes[ catNum ] ) );
|
||||||
// Maybe after unlocking it has already been created, so check (most likely if it blocked)
|
// Maybe after unlocking it has already been created, so check (most likely if it blocked)
|
||||||
if( !m_cats[catNum] )
|
if( !m_cats[ catNum ] )
|
||||||
{
|
{
|
||||||
// Get the category name if we have it
|
// Get the category name if we have it
|
||||||
std::string catName;
|
std::string catName;
|
||||||
auto categoryMapIt = ::categoryIdToNameMap.find( catNum );
|
auto categoryMapIt = ::categoryIdToNameMap.find( catNum );
|
||||||
if( categoryMapIt != ::categoryIdToNameMap.end() )
|
if( categoryMapIt != ::categoryIdToNameMap.end() )
|
||||||
{
|
{
|
||||||
catName = categoryMapIt->second;
|
catName = categoryMapIt->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually creates the category
|
// 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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameData::createExCategory( uint32_t catNum )
|
void GameData::createExCategory( uint32_t catNum )
|
||||||
{
|
{
|
||||||
// Maybe after unlocking it has already been created, so check (most likely if it blocked)
|
// Maybe after unlocking it has already been created, so check (most likely if it blocked)
|
||||||
if( !m_exCats[catNum].exNumToChunkMap[1].chunkToCatMap[0] )
|
if( !m_exCats[ catNum ].exNumToChunkMap[ 1 ].chunkToCatMap[ 0 ] )
|
||||||
{
|
{
|
||||||
// Get the category name if we have it
|
// Get the category name if we have it
|
||||||
std::string catName;
|
std::string catName;
|
||||||
auto categoryMapIt = ::categoryIdToNameMap.find( catNum );
|
auto categoryMapIt = ::categoryIdToNameMap.find( catNum );
|
||||||
if( categoryMapIt != ::categoryIdToNameMap.end() )
|
if( categoryMapIt != ::categoryIdToNameMap.end() )
|
||||||
{
|
{
|
||||||
catName = categoryMapIt->second;
|
catName = categoryMapIt->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( auto const& ex : m_exCats[catNum].exNumToChunkMap )
|
for( auto const& ex : m_exCats[ catNum ].exNumToChunkMap )
|
||||||
{
|
{
|
||||||
for( auto const& chunk : m_exCats[catNum].exNumToChunkMap[ex.first].chunkToCatMap )
|
for( auto const& chunk : m_exCats[ catNum ].exNumToChunkMap[ ex.first ].chunkToCatMap )
|
||||||
{
|
{
|
||||||
// Actually creates the category
|
// 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 ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
116
deps/datReader/GameData.h
vendored
116
deps/datReader/GameData.h
vendored
|
@ -5,80 +5,88 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <experimental/filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
|
||||||
namespace dat
|
|
||||||
{
|
{
|
||||||
|
|
||||||
class Cat;
|
class Cat;
|
||||||
class File;
|
|
||||||
|
|
||||||
// Interface to all the datfiles - Main entry point
|
class File;
|
||||||
// All the paths to files/dirs inside the dats are case-insensitive
|
|
||||||
class GameData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// This should be the path in which the .index/.datX files are located
|
|
||||||
GameData( const std::experimental::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 );
|
// Interface to all the datfiles - Main entry point
|
||||||
|
// All the paths to files/dirs inside the dats are case-insensitive
|
||||||
|
class GameData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// This should be the path in which the .index/.datX files are located
|
||||||
|
GameData( const std::filesystem::path& path );
|
||||||
|
|
||||||
// Returns all the scanned category number available in the path
|
~GameData();
|
||||||
const std::vector<uint32_t>& getCatNumbers() const;
|
|
||||||
|
|
||||||
// Return a specific category by its number (see getCatNumbers() for loops)
|
static const std::string
|
||||||
const Cat& getCategory( uint32_t catNum );
|
buildDatStr( const std::string folder, const int cat, const int exNum, const int chunk, const std::string platform,
|
||||||
// Return a specific category by it's name (e.g.: "exd"/"game_script"/ etc...)
|
const std::string type );
|
||||||
const Cat& getCategory( const std::string& catName );
|
|
||||||
|
|
||||||
const Cat& getExCategory( const std::string& catName, uint32_t exNum, const std::string& path );
|
// Returns all the scanned category number available in the path
|
||||||
|
const std::vector< uint32_t >& getCatNumbers() const;
|
||||||
|
|
||||||
// Retrieve a file from the dats given its filename
|
// Return a specific category by its number (see getCatNumbers() for loops)
|
||||||
std::unique_ptr<File> getFile( const std::string& path );
|
const Cat& getCategory( uint32_t catNum );
|
||||||
|
|
||||||
// Checks that a file exists
|
// Return a specific category by it's name (e.g.: "exd"/"game_script"/ etc...)
|
||||||
bool doesFileExist( const std::string& path );
|
const Cat& getCategory( const std::string& catName );
|
||||||
|
|
||||||
// Checks that a dir exists, there must be a trailing / in the path
|
const Cat& getExCategory( const std::string& catName, uint32_t exNum, const std::string& path );
|
||||||
// Note that it won't work for dirs that don't contain any file
|
|
||||||
// e.g.: - "ui/icon/" will return False
|
|
||||||
// - "ui/icon/000000/" will return True
|
|
||||||
bool doesDirExist( const std::string& path );
|
|
||||||
|
|
||||||
protected:
|
// Retrieve a file from the dats given its filename
|
||||||
// Return a specific category given a path (calls const Cat& getCategory(const std::string& catName))
|
std::unique_ptr< File > getFile( const std::string& path );
|
||||||
const Cat& getCategoryFromPath( const std::string& path );
|
|
||||||
|
|
||||||
// From a full path, returns the dirHash and the filenameHash
|
// Checks that a file exists
|
||||||
void getHashes( const std::string& path, uint32_t& dirHash, uint32_t& filenameHash ) const;
|
bool doesFileExist( const std::string& path );
|
||||||
|
|
||||||
// Lazy instantiation of category
|
// Checks that a dir exists, there must be a trailing / in the path
|
||||||
void createCategory( uint32_t catNum );
|
// Note that it won't work for dirs that don't contain any file
|
||||||
|
// e.g.: - "ui/icon/" will return False
|
||||||
|
// - "ui/icon/000000/" will return True
|
||||||
|
bool doesDirExist( const std::string& path );
|
||||||
|
|
||||||
void createExCategory( uint32_t catNum );
|
protected:
|
||||||
|
// Return a specific category given a path (calls const Cat& getCategory(const std::string& catName))
|
||||||
|
const Cat& getCategoryFromPath( const std::string& path );
|
||||||
|
|
||||||
// Path given to constructor, pointing to the folder with the .index/.datX files
|
// From a full path, returns the dirHash and the filenameHash
|
||||||
const std::experimental::filesystem::path m_path;
|
void getHashes( const std::string& path, uint32_t& dirHash, uint32_t& filenameHash ) const;
|
||||||
|
|
||||||
// Stored categories, indexed by their number, categories are instantiated and parsed individually when they are needed
|
// Lazy instantiation of category
|
||||||
std::unordered_map<uint32_t, std::unique_ptr<Cat>> m_cats;
|
void createCategory( uint32_t catNum );
|
||||||
|
|
||||||
// List of all the categories numbers, is equal to m_cats.keys()
|
void createExCategory( uint32_t catNum );
|
||||||
std::vector<uint32_t> m_catNums;
|
|
||||||
|
|
||||||
// Map of all EX categories and their chunks, "CatNum - (ExNum - (ChunkNum - Cat))"
|
// Path given to constructor, pointing to the folder with the .index/.datX files
|
||||||
// Map of all EX categories and their chunks, "CatNum - (ExNum - (ChunkNum - Cat))"
|
const std::filesystem::path m_path;
|
||||||
using ChunkToCatMap = struct { std::unordered_map< uint32_t, std::unique_ptr< Cat > > chunkToCatMap; };
|
|
||||||
using ExNumToChunkMap = struct { std::unordered_map< uint32_t, ChunkToCatMap > exNumToChunkMap; };
|
// Stored categories, indexed by their number, categories are instantiated and parsed individually when they are needed
|
||||||
using CatNumToExNumMap = std::unordered_map< uint32_t, ExNumToChunkMap >;
|
std::unordered_map< uint32_t, std::unique_ptr< Cat>> m_cats;
|
||||||
CatNumToExNumMap m_exCats;
|
|
||||||
std::unordered_map<uint32_t, std::unique_ptr<std::mutex>> m_catCreationMutexes;
|
// List of all the categories numbers, is equal to m_cats.keys()
|
||||||
};
|
std::vector< uint32_t > m_catNums;
|
||||||
|
|
||||||
|
// 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 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
|
#endif // XIV_DAT_GAMEDATA_H
|
||||||
|
|
230
deps/datReader/Index.cpp
vendored
230
deps/datReader/Index.cpp
vendored
|
@ -2,166 +2,154 @@
|
||||||
|
|
||||||
#include "bparse.h"
|
#include "bparse.h"
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
{
|
||||||
namespace dat
|
struct IndexBlockRecord
|
||||||
{
|
{
|
||||||
struct IndexBlockRecord
|
uint32_t offset;
|
||||||
{
|
uint32_t size;
|
||||||
uint32_t offset;
|
SqPackBlockHash blockHash;
|
||||||
uint32_t size;
|
};
|
||||||
SqPackBlockHash blockHash;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IndexHashTableEntry
|
struct IndexHashTableEntry
|
||||||
{
|
{
|
||||||
uint32_t filenameHash;
|
uint32_t filenameHash;
|
||||||
uint32_t dirHash;
|
uint32_t dirHash;
|
||||||
uint32_t datOffset;
|
uint32_t datOffset;
|
||||||
uint32_t padding;
|
uint32_t padding;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::utils::bparse
|
||||||
{
|
{
|
||||||
namespace utils
|
template<>
|
||||||
{
|
inline void reorder< xiv::dat::IndexBlockRecord >( xiv::dat::IndexBlockRecord& i_struct )
|
||||||
namespace bparse
|
{
|
||||||
{
|
xiv::utils::bparse::reorder( i_struct.offset );
|
||||||
template <>
|
xiv::utils::bparse::reorder( i_struct.size );
|
||||||
inline void reorder<xiv::dat::IndexBlockRecord>(xiv::dat::IndexBlockRecord& i_struct)
|
xiv::utils::bparse::reorder( i_struct.blockHash );
|
||||||
{
|
}
|
||||||
xiv::utils::bparse::reorder(i_struct.offset);
|
|
||||||
xiv::utils::bparse::reorder(i_struct.size);
|
|
||||||
xiv::utils::bparse::reorder(i_struct.blockHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template<>
|
||||||
inline void reorder<xiv::dat::IndexHashTableEntry>(xiv::dat::IndexHashTableEntry& i_struct)
|
inline void reorder< xiv::dat::IndexHashTableEntry >( xiv::dat::IndexHashTableEntry& i_struct )
|
||||||
{
|
{
|
||||||
xiv::utils::bparse::reorder(i_struct.filenameHash);
|
xiv::utils::bparse::reorder( i_struct.filenameHash );
|
||||||
xiv::utils::bparse::reorder(i_struct.dirHash);
|
xiv::utils::bparse::reorder( i_struct.dirHash );
|
||||||
xiv::utils::bparse::reorder(i_struct.datOffset);
|
xiv::utils::bparse::reorder( i_struct.datOffset );
|
||||||
xiv::utils::bparse::reorder(i_struct.padding);
|
xiv::utils::bparse::reorder( i_struct.padding );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using xiv::utils::bparse::extract;
|
using xiv::utils::bparse::extract;
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
|
||||||
namespace dat
|
|
||||||
{
|
{
|
||||||
|
|
||||||
Index::Index(const std::experimental::filesystem::path& path) :
|
Index::Index( const std::filesystem::path& path ) :
|
||||||
SqPack( path )
|
SqPack( path )
|
||||||
{
|
{
|
||||||
if( !m_handle )
|
if( !m_handle )
|
||||||
throw new std::runtime_error( "Failed to load Index at " + path.string() );
|
throw new std::runtime_error( "Failed to load Index at " + path.string() );
|
||||||
|
|
||||||
// Hash Table record
|
// Hash Table record
|
||||||
auto hashTableBlockRecord = extract<IndexBlockRecord>( m_handle );
|
auto hashTableBlockRecord = extract< IndexBlockRecord >( m_handle );
|
||||||
isIndexBlockValid( hashTableBlockRecord );
|
isIndexBlockValid( hashTableBlockRecord );
|
||||||
|
|
||||||
// Save the posin the stream to go back to it later on
|
// Save the posin the stream to go back to it later on
|
||||||
auto pos = m_handle.tellg();
|
auto pos = m_handle.tellg();
|
||||||
|
|
||||||
// Seek to the pos of the hash table in the file
|
// Seek to the pos of the hash table in the file
|
||||||
m_handle.seekg( hashTableBlockRecord.offset );
|
m_handle.seekg( hashTableBlockRecord.offset );
|
||||||
|
|
||||||
// Preallocate and extract the index_hash_table_entries
|
// Preallocate and extract the index_hash_table_entries
|
||||||
std::vector<IndexHashTableEntry> indexHashTableEntries;
|
std::vector< IndexHashTableEntry > indexHashTableEntries;
|
||||||
extract<IndexHashTableEntry>( m_handle, hashTableBlockRecord.size / sizeof( IndexHashTableEntry ),
|
extract< IndexHashTableEntry >( m_handle, hashTableBlockRecord.size / sizeof( IndexHashTableEntry ),
|
||||||
indexHashTableEntries );
|
indexHashTableEntries );
|
||||||
|
|
||||||
// Feed the correct entry in the HashTable for each index_hash_table_entry
|
// Feed the correct entry in the HashTable for each index_hash_table_entry
|
||||||
for( auto& indexHashTableEntry : indexHashTableEntries )
|
for( auto& indexHashTableEntry : indexHashTableEntries )
|
||||||
{
|
{
|
||||||
auto& hashTableEntry = m_hashTable[indexHashTableEntry.dirHash][indexHashTableEntry.filenameHash];
|
auto& hashTableEntry = m_hashTable[ indexHashTableEntry.dirHash ][ indexHashTableEntry.filenameHash ];
|
||||||
// The dat number is found in the offset, last four bits
|
// The dat number is found in the offset, last four bits
|
||||||
hashTableEntry.datNum = ( indexHashTableEntry.datOffset & 0xF ) / 0x2;
|
hashTableEntry.datNum = ( indexHashTableEntry.datOffset & 0xF ) / 0x2;
|
||||||
// The offset in the dat file, needs to strip the dat number indicator
|
// 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.dirHash = indexHashTableEntry.dirHash;
|
||||||
hashTableEntry.filenameHash = indexHashTableEntry.filenameHash;
|
hashTableEntry.filenameHash = indexHashTableEntry.filenameHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Come back to where we were before reading the HashTable
|
// Come back to where we were before reading the HashTable
|
||||||
m_handle.seekg( pos );
|
m_handle.seekg( pos );
|
||||||
|
|
||||||
// Dat Count
|
// Dat Count
|
||||||
m_datCount = extract<uint32_t>( m_handle, "dat_count" );
|
m_datCount = extract< uint32_t >( m_handle, "dat_count" );
|
||||||
|
|
||||||
// Free List
|
// Free List
|
||||||
isIndexBlockValid( extract<IndexBlockRecord>( m_handle ) );
|
isIndexBlockValid( extract< IndexBlockRecord >( m_handle ) );
|
||||||
|
|
||||||
// Dir Hash Table
|
// Dir Hash Table
|
||||||
isIndexBlockValid( extract<IndexBlockRecord>( m_handle ) );
|
isIndexBlockValid( extract< IndexBlockRecord >( m_handle ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::~Index()
|
Index::~Index()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Index::getDatCount() const
|
uint32_t Index::getDatCount() const
|
||||||
{
|
{
|
||||||
return m_datCount;
|
return m_datCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Index::HashTable& Index::getHashTable() const
|
const Index::HashTable& Index::getHashTable() const
|
||||||
{
|
{
|
||||||
return m_hashTable;
|
return m_hashTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Index::doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const
|
bool Index::doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const
|
||||||
{
|
{
|
||||||
auto dir_it = getHashTable().find( dir_hash );
|
auto dir_it = getHashTable().find( dir_hash );
|
||||||
if( dir_it != getHashTable().end() )
|
if( dir_it != getHashTable().end() )
|
||||||
{
|
{
|
||||||
return ( dir_it->second.find( filename_hash ) != dir_it->second.end() );
|
return ( dir_it->second.find( filename_hash ) != dir_it->second.end() );
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Index::doesDirExist( uint32_t dir_hash ) const
|
bool Index::doesDirExist( uint32_t dir_hash ) const
|
||||||
{
|
{
|
||||||
return ( getHashTable().find( dir_hash ) != getHashTable().end() );
|
return ( getHashTable().find( dir_hash ) != getHashTable().end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
const Index::DirHashTable& Index::getDirHashTable( uint32_t dir_hash ) const
|
const Index::DirHashTable& Index::getDirHashTable( uint32_t dir_hash ) const
|
||||||
{
|
{
|
||||||
auto dir_it = getHashTable().find( dir_hash );
|
auto dir_it = getHashTable().find( dir_hash );
|
||||||
if( dir_it == getHashTable().end() )
|
if( dir_it == getHashTable().end() )
|
||||||
{
|
{
|
||||||
throw std::runtime_error( "dirHash not found" );
|
throw std::runtime_error( "dirHash not found" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return dir_it->second;
|
return dir_it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Index::HashTableEntry& Index::getHashTableEntry( uint32_t dir_hash, uint32_t filename_hash ) const
|
const Index::HashTableEntry& Index::getHashTableEntry( uint32_t dir_hash, uint32_t filename_hash ) const
|
||||||
{
|
{
|
||||||
auto& dirHashTable = getDirHashTable( dir_hash );
|
auto& dirHashTable = getDirHashTable( dir_hash );
|
||||||
auto file_it = dirHashTable.find( filename_hash );
|
auto file_it = dirHashTable.find( filename_hash );
|
||||||
if( file_it == dirHashTable.end() )
|
if( file_it == dirHashTable.end() )
|
||||||
{
|
{
|
||||||
throw std::runtime_error( "filenameHash not found" );
|
throw std::runtime_error( "filenameHash not found" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return file_it->second;
|
return file_it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Index::isIndexBlockValid( const IndexBlockRecord& i_index_block_record )
|
void Index::isIndexBlockValid( const IndexBlockRecord& i_index_block_record )
|
||||||
{
|
{
|
||||||
isBlockValid( i_index_block_record.offset, i_index_block_record.size, i_index_block_record.blockHash );
|
isBlockValid( i_index_block_record.offset, i_index_block_record.size, i_index_block_record.blockHash );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
74
deps/datReader/Index.h
vendored
74
deps/datReader/Index.h
vendored
|
@ -5,55 +5,59 @@
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <experimental/filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
namespace xiv {
|
namespace xiv::dat
|
||||||
namespace dat {
|
|
||||||
|
|
||||||
struct IndexBlockRecord;
|
|
||||||
|
|
||||||
class Index : public SqPack
|
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
// Full path to the index file
|
|
||||||
Index( const std::experimental::filesystem::path& i_path );
|
|
||||||
virtual ~Index();
|
|
||||||
|
|
||||||
// An entry in the hash table, representing a file in a given dat
|
struct IndexBlockRecord;
|
||||||
struct HashTableEntry
|
|
||||||
{
|
class Index :
|
||||||
|
public SqPack
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Full path to the index file
|
||||||
|
Index( const std::filesystem::path& i_path );
|
||||||
|
|
||||||
|
virtual ~Index();
|
||||||
|
|
||||||
|
// An entry in the hash table, representing a file in a given dat
|
||||||
|
struct HashTableEntry
|
||||||
|
{
|
||||||
uint32_t datNum;
|
uint32_t datNum;
|
||||||
uint32_t dirHash;
|
uint32_t dirHash;
|
||||||
uint32_t filenameHash;
|
uint32_t filenameHash;
|
||||||
uint32_t datOffset;
|
uint32_t datOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
// HashTable has dir hashes -> filename hashes -> HashTableEntry
|
// HashTable has dir hashes -> filename hashes -> HashTableEntry
|
||||||
using DirHashTable = std::unordered_map< uint32_t, HashTableEntry >;
|
using DirHashTable = std::unordered_map< uint32_t, HashTableEntry >;
|
||||||
using HashTable = std::unordered_map< uint32_t, DirHashTable >;
|
using HashTable = std::unordered_map< uint32_t, DirHashTable >;
|
||||||
|
|
||||||
// Get the number of dat files the index is linked to
|
// Get the number of dat files the index is linked to
|
||||||
uint32_t getDatCount() const;
|
uint32_t getDatCount() const;
|
||||||
|
|
||||||
bool doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const;
|
bool doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const;
|
||||||
bool doesDirExist( uint32_t dir_hash ) const;
|
|
||||||
|
|
||||||
// Returns the whole HashTable
|
bool doesDirExist( uint32_t dir_hash ) const;
|
||||||
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;
|
|
||||||
|
|
||||||
protected:
|
// Returns the whole HashTable
|
||||||
// Checks that the block is valid with regards to its hash
|
const HashTable& getHashTable() const;
|
||||||
void isIndexBlockValid( const IndexBlockRecord& i_index_block_record );
|
|
||||||
|
|
||||||
uint32_t m_datCount;
|
// Returns the hash table for a specific dir
|
||||||
HashTable m_hashTable;
|
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;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Checks that the block is valid with regards to its hash
|
||||||
|
void isIndexBlockValid( const IndexBlockRecord& i_index_block_record );
|
||||||
|
|
||||||
|
uint32_t m_datCount;
|
||||||
|
HashTable m_hashTable;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // XIV_DAT_INDEX_H
|
#endif // XIV_DAT_INDEX_H
|
||||||
|
|
122
deps/datReader/SqPack.cpp
vendored
122
deps/datReader/SqPack.cpp
vendored
|
@ -1,76 +1,78 @@
|
||||||
#include "SqPack.h"
|
#include "SqPack.h"
|
||||||
|
|
||||||
namespace xiv {
|
namespace xiv::dat {
|
||||||
namespace dat {
|
enum PlatformId :
|
||||||
struct SqPackHeader
|
uint8_t
|
||||||
{
|
{
|
||||||
char magic[0x8];
|
Win32,
|
||||||
uint32_t zero;
|
PS3,
|
||||||
uint32_t size;
|
PS4
|
||||||
uint32_t version;
|
};
|
||||||
uint32_t type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SqPackIndexHeader
|
struct SqPackHeader
|
||||||
{
|
{
|
||||||
uint32_t size;
|
char magic[0x8];
|
||||||
uint32_t type;
|
PlatformId platformId;
|
||||||
};
|
uint8_t padding0[3];
|
||||||
}
|
uint32_t size;
|
||||||
}
|
uint32_t version;
|
||||||
namespace xiv {
|
uint32_t type;
|
||||||
namespace utils {
|
};
|
||||||
namespace bparse {
|
|
||||||
template <>
|
|
||||||
inline void reorder<xiv::dat::SqPackHeader>(xiv::dat::SqPackHeader& i_struct)
|
|
||||||
{
|
|
||||||
for (int32_t i = 0; i < 0x8; ++i)
|
|
||||||
{
|
|
||||||
xiv::utils::bparse::reorder(i_struct.magic[i]);
|
|
||||||
}
|
|
||||||
xiv::utils::bparse::reorder(i_struct.zero);
|
|
||||||
xiv::utils::bparse::reorder(i_struct.size);
|
|
||||||
xiv::utils::bparse::reorder(i_struct.version);
|
|
||||||
xiv::utils::bparse::reorder(i_struct.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
struct SqPackIndexHeader
|
||||||
inline void reorder<xiv::dat::SqPackIndexHeader>(xiv::dat::SqPackIndexHeader& i_struct)
|
{
|
||||||
{
|
uint32_t size;
|
||||||
xiv::utils::bparse::reorder(i_struct.size);
|
uint32_t type;
|
||||||
xiv::utils::bparse::reorder(i_struct.type);
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace xiv::utils:: bparse
|
||||||
|
{
|
||||||
|
template<>
|
||||||
|
inline void reorder< xiv::dat::SqPackHeader >( xiv::dat::SqPackHeader& i_struct )
|
||||||
|
{
|
||||||
|
for( int32_t i = 0; i < 0x8; ++i )
|
||||||
|
{
|
||||||
|
xiv::utils::bparse::reorder( i_struct.magic[ i ] );
|
||||||
|
}
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void reorder< xiv::dat::SqPackIndexHeader >( xiv::dat::SqPackIndexHeader& i_struct )
|
||||||
|
{
|
||||||
|
xiv::utils::bparse::reorder( i_struct.size );
|
||||||
|
xiv::utils::bparse::reorder( i_struct.type );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
using xiv::utils::bparse::extract;
|
using xiv::utils::bparse::extract;
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
|
||||||
namespace dat
|
|
||||||
{
|
{
|
||||||
|
|
||||||
SqPack::SqPack( const std::experimental::filesystem::path& path ) :
|
// Open the file
|
||||||
// Open the file
|
SqPack::SqPack( const std::filesystem::path& path ) :
|
||||||
m_handle( path.string(), std::ios_base::in | std::ios_base::binary )
|
m_handle( path.string(), std::ios_base::in | std::ios_base::binary )
|
||||||
{
|
{
|
||||||
// Extract the header
|
// Extract the header
|
||||||
extract<SqPackHeader>( m_handle );
|
extract< SqPackHeader >( m_handle );
|
||||||
|
|
||||||
// Skip until the IndexHeader the extract it
|
// Skip until the IndexHeader the extract it
|
||||||
m_handle.seekg( 0x400 );
|
m_handle.seekg( 0x400 );
|
||||||
extract<SqPackIndexHeader>( m_handle );
|
extract< SqPackIndexHeader >( m_handle );
|
||||||
}
|
}
|
||||||
|
|
||||||
SqPack::~SqPack()
|
SqPack::~SqPack()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SqPack::isBlockValid( uint32_t i_offset, uint32_t i_size, const SqPackBlockHash& i_block_hash )
|
void SqPack::isBlockValid( uint32_t i_offset, uint32_t i_size, const SqPackBlockHash& i_block_hash )
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
80
deps/datReader/SqPack.h
vendored
80
deps/datReader/SqPack.h
vendored
|
@ -3,64 +3,56 @@
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include <experimental/filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
#include "bparse.h"
|
#include "bparse.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
{
|
||||||
namespace dat
|
struct SqPackBlockHash
|
||||||
{
|
{
|
||||||
|
uint8_t hash[0x14];
|
||||||
struct SqPackBlockHash
|
uint32_t padding[0xB];
|
||||||
{
|
};
|
||||||
uint8_t hash[0x14];
|
|
||||||
uint32_t padding[0xB];
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
namespace xiv {
|
|
||||||
namespace utils {
|
namespace xiv::utils::bparse
|
||||||
namespace bparse {
|
{
|
||||||
template <> inline void reorder<xiv::dat::SqPackBlockHash>( xiv::dat::SqPackBlockHash& i_struct )
|
template<>
|
||||||
{
|
inline void reorder< xiv::dat::SqPackBlockHash >( xiv::dat::SqPackBlockHash& i_struct )
|
||||||
for( auto i = 0; i < 0x14; ++i )
|
{
|
||||||
{
|
for( auto i = 0; i < 0x14; ++i )
|
||||||
xiv::utils::bparse::reorder( i_struct.hash[i] );
|
{
|
||||||
}
|
xiv::utils::bparse::reorder( i_struct.hash[ i ] );
|
||||||
for( auto i = 0; i < 0xB; ++i )
|
}
|
||||||
{
|
for( auto i = 0; i < 0xB; ++i )
|
||||||
xiv::utils::bparse::reorder( i_struct.padding[i] );
|
{
|
||||||
}
|
xiv::utils::bparse::reorder( i_struct.padding[ i ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::dat
|
||||||
{
|
|
||||||
namespace dat
|
|
||||||
{
|
{
|
||||||
|
|
||||||
class SqPack
|
class SqPack
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Full path to the sqpack file
|
// Full path to the sqpack file
|
||||||
SqPack( const std::experimental::filesystem::path& i_path );
|
SqPack( const std::filesystem::path& i_path );
|
||||||
virtual ~SqPack();
|
|
||||||
|
|
||||||
protected:
|
virtual ~SqPack();
|
||||||
// Checks that a given block is valid iven its hash
|
|
||||||
void isBlockValid( uint32_t i_offset, uint32_t i_size, const SqPackBlockHash& i_block_hash );
|
|
||||||
|
|
||||||
// File handle
|
protected:
|
||||||
std::ifstream m_handle;
|
// Checks that a given block is valid iven its hash
|
||||||
};
|
void isBlockValid( uint32_t i_offset, uint32_t i_size, const SqPackBlockHash& i_block_hash );
|
||||||
|
|
||||||
|
// File handle
|
||||||
|
std::ifstream m_handle;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // XIV_DAT_SQPACK_H
|
#endif // XIV_DAT_SQPACK_H
|
||||||
|
|
152
deps/datReader/bparse.h
vendored
152
deps/datReader/bparse.h
vendored
|
@ -6,98 +6,96 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::utils::bparse
|
||||||
{
|
|
||||||
namespace utils
|
|
||||||
{
|
|
||||||
namespace bparse
|
|
||||||
{
|
{
|
||||||
|
|
||||||
// Internal macro for byteswapping
|
// Internal macro for byteswapping
|
||||||
template <int N>
|
template< int N >
|
||||||
void byteswap_impl(char (&bytes)[N])
|
void byteswap_impl( char (& bytes)[N] )
|
||||||
{
|
{
|
||||||
for( auto p = std::begin( bytes ), end = std::end( bytes ) - 1; p < end; ++p, --end )
|
for( auto p = std::begin( bytes ), end = std::end( bytes ) - 1; p < end; ++p, --end )
|
||||||
{
|
{
|
||||||
std::swap( *p, *end );
|
std::swap( *p, *end );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// byteswapping any type (no pointers to array)
|
// byteswapping any type (no pointers to array)
|
||||||
template <typename T>
|
template< typename T >
|
||||||
T byteswap(T value)
|
T byteswap( T value )
|
||||||
{
|
{
|
||||||
byteswap_impl(*reinterpret_cast<char (*)[sizeof(T)]>(&value));
|
byteswap_impl( *reinterpret_cast<char ( * )[sizeof( T )]>(&value) );
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a struct from a stream
|
// Read a struct from a stream
|
||||||
template <typename StructType>
|
template< typename StructType >
|
||||||
void read(std::istream& i_stream, StructType& i_struct)
|
void read( std::istream& i_stream, StructType& i_struct )
|
||||||
{
|
{
|
||||||
static_assert( std::is_pod<StructType>::value, "StructType must be a POD to be able to use read." );
|
static_assert( std::is_pod< StructType >::value, "StructType must be a POD to be able to use read." );
|
||||||
i_stream.read( reinterpret_cast<char*>( &i_struct ), sizeof( StructType ) );
|
i_stream.read( reinterpret_cast<char*>( &i_struct ), sizeof( StructType ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// By default a type does not need reordering
|
// 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
|
// "Overload" for passed struct as arg
|
||||||
template <typename StructType>
|
template< typename StructType >
|
||||||
void extract(std::istream& i_stream, StructType& o_struct)
|
void extract( std::istream& i_stream, StructType& o_struct )
|
||||||
{
|
{
|
||||||
read( i_stream, o_struct );
|
read( i_stream, o_struct );
|
||||||
reorder( o_struct );
|
reorder( o_struct );
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should not copy because of RVO
|
// This should not copy because of RVO
|
||||||
// Extract a struct from a stream and log it
|
// Extract a struct from a stream and log it
|
||||||
template <typename StructType>
|
template< typename StructType >
|
||||||
StructType extract( std::istream& i_stream )
|
StructType extract( std::istream& i_stream )
|
||||||
{
|
{
|
||||||
StructType temp_struct;
|
StructType temp_struct;
|
||||||
extract<StructType>( i_stream, temp_struct );
|
extract< StructType >( i_stream, temp_struct );
|
||||||
return temp_struct;
|
return temp_struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename StructType>
|
template< typename StructType >
|
||||||
void extract(std::istream& i_stream, uint32_t i_size, std::vector<StructType>& o_structs )
|
void extract( std::istream& i_stream, uint32_t i_size, std::vector< StructType >& o_structs )
|
||||||
{
|
{
|
||||||
o_structs.reserve( i_size );
|
o_structs.reserve( i_size );
|
||||||
for( uint32_t i = 0; i < i_size; ++i )
|
for( uint32_t i = 0; i < i_size; ++i )
|
||||||
{
|
{
|
||||||
o_structs.emplace_back( extract<StructType>( i_stream ) );
|
o_structs.emplace_back( extract< StructType >( i_stream ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For simple (integral) types just provide name and endianness directly
|
// For simple (integral) types just provide name and endianness directly
|
||||||
template <typename StructType>
|
template< typename StructType >
|
||||||
StructType extract(std::istream& i_stream, const std::string& i_name, bool i_is_le = true)
|
StructType extract( std::istream& i_stream, const std::string& i_name, bool i_is_le = true )
|
||||||
{
|
{
|
||||||
StructType temp_struct;
|
StructType temp_struct;
|
||||||
read( i_stream, temp_struct );
|
read( i_stream, temp_struct );
|
||||||
if( !i_is_le )
|
if( !i_is_le )
|
||||||
{
|
{
|
||||||
temp_struct = byteswap( temp_struct );
|
temp_struct = byteswap( temp_struct );
|
||||||
}
|
}
|
||||||
return temp_struct;
|
return temp_struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename StructType>
|
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 )
|
o_structs.reserve( i_size );
|
||||||
{
|
for( uint32_t i = 0; i < i_size; ++i )
|
||||||
o_structs.emplace_back( extract<StructType>( i_stream, i_name ) );
|
{
|
||||||
}
|
o_structs.emplace_back( extract< StructType >( i_stream, i_name ) );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For cstrings
|
// For cstrings
|
||||||
std::string extract_cstring( std::istream& i_stream, const std::string& i_name );
|
std::string extract_cstring( std::istream& i_stream, const std::string& i_name );
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // XIV_UTILS_BPARSE_H
|
#endif // XIV_UTILS_BPARSE_H
|
||||||
|
|
8
deps/datReader/conv.cpp
vendored
8
deps/datReader/conv.cpp
vendored
|
@ -1,8 +1,8 @@
|
||||||
#include "conv.h"
|
#include "conv.h"
|
||||||
|
|
||||||
namespace xiv {
|
namespace xiv::utils::conv
|
||||||
namespace utils {
|
{
|
||||||
namespace conv {
|
|
||||||
float half2float( const uint16_t i_value )
|
float half2float( const uint16_t i_value )
|
||||||
{
|
{
|
||||||
uint32_t t1;
|
uint32_t t1;
|
||||||
|
@ -30,6 +30,4 @@ namespace conv {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
8
deps/datReader/conv.h
vendored
8
deps/datReader/conv.h
vendored
|
@ -5,13 +5,11 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace xiv {
|
namespace xiv::utils::conv
|
||||||
namespace utils {
|
{
|
||||||
namespace conv {
|
|
||||||
float half2float( const uint16_t i_value );
|
float half2float( const uint16_t i_value );
|
||||||
|
|
||||||
float ubyte2float( const uint8_t i_value );
|
float ubyte2float( const uint8_t i_value );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // XIV_UTILS_CONV_H
|
#endif // XIV_UTILS_CONV_H
|
||||||
|
|
169
deps/datReader/crc32.cpp
vendored
169
deps/datReader/crc32.cpp
vendored
|
@ -65,116 +65,111 @@ namespace internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::utils::crc32
|
||||||
{
|
|
||||||
namespace utils
|
|
||||||
{
|
|
||||||
namespace crc32
|
|
||||||
{
|
{
|
||||||
|
|
||||||
uint32_t compute(const std::string& i_input, uint32_t init_crc)
|
uint32_t compute( const std::string& i_input, uint32_t init_crc )
|
||||||
{
|
{
|
||||||
// Classical crc stuff
|
// Classical crc stuff
|
||||||
auto& crc_table = internal::get_crc_table();
|
auto& crc_table = internal::get_crc_table();
|
||||||
auto crc = init_crc;
|
auto crc = init_crc;
|
||||||
for(std::size_t i = 0; i < i_input.size(); ++i)
|
for( std::size_t i = 0; i < i_input.size(); ++i )
|
||||||
{
|
{
|
||||||
crc = crc_table[(crc ^ i_input[i]) & 0xFF] ^ (crc >> 8);
|
crc = crc_table[ ( crc ^ i_input[ i ] ) & 0xFF ] ^ ( crc >> 8 );
|
||||||
}
|
}
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rev_compute(const std::string& i_input, uint32_t init_crc)
|
uint32_t rev_compute( const std::string& i_input, uint32_t init_crc )
|
||||||
{
|
{
|
||||||
auto& rev_crc_table = internal::get_rev_crc_table();
|
auto& rev_crc_table = internal::get_rev_crc_table();
|
||||||
auto crc = init_crc;
|
auto crc = init_crc;
|
||||||
const auto input_size = i_input.size();
|
const auto input_size = i_input.size();
|
||||||
// Reverse crc
|
// Reverse crc
|
||||||
for(auto i = input_size; i > 0; --i)
|
for( auto i = input_size; i > 0; --i )
|
||||||
{
|
{
|
||||||
crc = rev_crc_table[crc >> 24] ^ ((crc << 8) & 0xFFFFFF00) ^ i_input[input_size - i - 1];
|
crc = rev_crc_table[ crc >> 24 ] ^ ( ( crc << 8 ) & 0xFFFFFF00 ) ^ i_input[ input_size - i - 1 ];
|
||||||
}
|
}
|
||||||
// Compute the 4 bytes needed for this init_crc
|
// Compute the 4 bytes needed for this init_crc
|
||||||
for (auto i = 0; i < 4; ++i)
|
for( auto i = 0; i < 4; ++i )
|
||||||
{
|
{
|
||||||
crc = rev_crc_table[crc >> 24] ^ ((crc << 8) & 0xFFFFFF00);
|
crc = rev_crc_table[ crc >> 24 ] ^ ( ( crc << 8 ) & 0xFFFFFF00 );
|
||||||
}
|
}
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_hashes_1(std::string& i_format, const uint32_t i_first_index, std::vector<uint32_t>& o_hashes)
|
void generate_hashes_1( std::string& i_format, const uint32_t i_first_index, std::vector< uint32_t >& o_hashes )
|
||||||
{
|
{
|
||||||
char* str = const_cast<char*>(i_format.data());
|
char* str = const_cast<char*>(i_format.data());
|
||||||
const uint32_t str_size = i_format.size();
|
const uint32_t str_size = i_format.size();
|
||||||
|
|
||||||
o_hashes.resize(10000);
|
o_hashes.resize( 10000 );
|
||||||
|
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
for (char a = '0'; a <= '9'; ++a)
|
for( char a = '0'; a <= '9'; ++a )
|
||||||
{
|
{
|
||||||
str[i_first_index] = a;
|
str[ i_first_index ] = a;
|
||||||
for (char b = '0'; b <= '9'; ++b)
|
for( char b = '0'; b <= '9'; ++b )
|
||||||
{
|
{
|
||||||
str[i_first_index + 1] = b;
|
str[ i_first_index + 1 ] = b;
|
||||||
for (char c = '0'; c <= '9'; ++c)
|
for( char c = '0'; c <= '9'; ++c )
|
||||||
{
|
{
|
||||||
str[i_first_index + 2] = c;
|
str[ i_first_index + 2 ] = c;
|
||||||
for (char d = '0'; d <= '9'; ++d)
|
for( char d = '0'; d <= '9'; ++d )
|
||||||
{
|
{
|
||||||
str[i_first_index + 3] = d;
|
str[ i_first_index + 3 ] = d;
|
||||||
o_hashes[i] = ::crc32(0, reinterpret_cast<uint8_t*>(&(str[0])), str_size) ^ 0xFFFFFFFF;
|
o_hashes[ i ] = ::crc32( 0, reinterpret_cast<uint8_t*>(&( str[ 0 ] )), str_size ) ^ 0xFFFFFFFF;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
char* str = const_cast<char*>(i_format.data());
|
||||||
|
const uint32_t str_size = i_format.size();
|
||||||
|
|
||||||
o_hashes.resize(100000000);
|
o_hashes.resize( 100000000 );
|
||||||
|
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
for (char a = '0'; a <= '9'; ++a)
|
for( char a = '0'; a <= '9'; ++a )
|
||||||
{
|
{
|
||||||
str[i_first_index] = a;
|
str[ i_first_index ] = a;
|
||||||
for (char b = '0'; b <= '9'; ++b)
|
for( char b = '0'; b <= '9'; ++b )
|
||||||
{
|
{
|
||||||
str[i_first_index + 1] = b;
|
str[ i_first_index + 1 ] = b;
|
||||||
for (char c = '0'; c <= '9'; ++c)
|
for( char c = '0'; c <= '9'; ++c )
|
||||||
{
|
{
|
||||||
str[i_first_index + 2] = c;
|
str[ i_first_index + 2 ] = c;
|
||||||
for (char d = '0'; d <= '9'; ++d)
|
for( char d = '0'; d <= '9'; ++d )
|
||||||
{
|
{
|
||||||
str[i_first_index + 3] = d;
|
str[ i_first_index + 3 ] = d;
|
||||||
for (char e = '0'; e <= '9'; ++e)
|
for( char e = '0'; e <= '9'; ++e )
|
||||||
{
|
{
|
||||||
str[i_second_index] = e;
|
str[ i_second_index ] = e;
|
||||||
for (char f = '0'; f <= '9'; ++f)
|
for( char f = '0'; f <= '9'; ++f )
|
||||||
{
|
{
|
||||||
str[i_second_index + 1] = f;
|
str[ i_second_index + 1 ] = f;
|
||||||
for (char g = '0'; g <= '9'; ++g)
|
for( char g = '0'; g <= '9'; ++g )
|
||||||
{
|
{
|
||||||
str[i_second_index + 2] = g;
|
str[ i_second_index + 2 ] = g;
|
||||||
for (char h = '0'; h <= '9'; ++h)
|
for( char h = '0'; h <= '9'; ++h )
|
||||||
{
|
{
|
||||||
str[i_second_index + 3] = h;
|
str[ i_second_index + 3 ] = h;
|
||||||
o_hashes[i] = ::crc32(0, reinterpret_cast<uint8_t*>(&(str[0])), str_size) ^ 0xFFFFFFFF;
|
o_hashes[ i ] = ::crc32( 0, reinterpret_cast<uint8_t*>(&( str[ 0 ] )), str_size ) ^ 0xFFFFFFFF;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
11
deps/datReader/crc32.h
vendored
11
deps/datReader/crc32.h
vendored
|
@ -5,9 +5,8 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace xiv {
|
namespace xiv::utils::crc32
|
||||||
namespace utils {
|
{
|
||||||
namespace crc32 {
|
|
||||||
|
|
||||||
// Normal crc32 computation from a given intial crc value, use zlib.crc32 instead, the final XOR 0xFFFFFFFF is not done
|
// 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 );
|
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 );
|
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_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
|
#endif // XIV_UTILS_CRC32_H
|
||||||
|
|
8
deps/datReader/stream.cpp
vendored
8
deps/datReader/stream.cpp
vendored
|
@ -4,13 +4,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::utils::stream
|
||||||
{
|
|
||||||
namespace utils
|
|
||||||
{
|
|
||||||
namespace stream
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
24
deps/datReader/stream.h
vendored
24
deps/datReader/stream.h
vendored
|
@ -5,23 +5,17 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::utils::stream
|
||||||
{
|
{
|
||||||
namespace utils
|
template< typename CharT, typename TraitsT = std::char_traits< CharT > >
|
||||||
{
|
class vectorwrapbuf :
|
||||||
namespace stream
|
public std::basic_streambuf< CharT, TraitsT >
|
||||||
{
|
{
|
||||||
template<typename CharT, typename TraitsT = std::char_traits<CharT> >
|
public:
|
||||||
class vectorwrapbuf : public std::basic_streambuf<CharT, TraitsT>
|
vectorwrapbuf( std::vector< CharT >& vec )
|
||||||
{
|
|
||||||
public:
|
|
||||||
vectorwrapbuf(std::vector<CharT> &vec)
|
|
||||||
{
|
{
|
||||||
this->setg(vec.data(), vec.data(), vec.data() + vec.size());
|
this->setg( vec.data(), vec.data(), vec.data() + vec.size() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // XIV_UTILS_STREAM_H
|
#endif // XIV_UTILS_STREAM_H
|
||||||
|
|
48
deps/datReader/zlib.cpp
vendored
48
deps/datReader/zlib.cpp
vendored
|
@ -4,32 +4,28 @@
|
||||||
#include <zlib/zlib.h>
|
#include <zlib/zlib.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::utils::zlib
|
||||||
{
|
|
||||||
namespace utils
|
|
||||||
{
|
|
||||||
namespace zlib
|
|
||||||
{
|
{
|
||||||
|
|
||||||
void compress(const std::vector<char>& in, std::vector<char>& out)
|
void compress( const std::vector< char >& in, std::vector< char >& out )
|
||||||
{
|
{
|
||||||
// Fetching upper bound for out size
|
// Fetching upper bound for out size
|
||||||
auto out_size = compressBound(in.size());
|
auto out_size = compressBound( in.size() );
|
||||||
out.resize(out_size);
|
out.resize( out_size );
|
||||||
|
|
||||||
auto ret = compress2(reinterpret_cast<uint8_t*>(out.data()), &out_size,
|
auto ret = compress2( reinterpret_cast<uint8_t*>(out.data()), &out_size,
|
||||||
reinterpret_cast<const uint8_t*>(in.data()), in.size(), Z_BEST_COMPRESSION);
|
reinterpret_cast<const uint8_t*>(in.data()), in.size(), Z_BEST_COMPRESSION );
|
||||||
|
|
||||||
if (ret != Z_OK)
|
if( ret != Z_OK )
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Error at zlib uncompress: " + std::to_string(ret));
|
throw std::runtime_error( "Error at zlib uncompress: " + std::to_string( ret ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
out.resize(out_size);
|
out.resize( out_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
void no_header_decompress(uint8_t* in, uint32_t in_size, uint8_t* out, uint32_t out_size)
|
void no_header_decompress( uint8_t* in, uint32_t in_size, uint8_t* out, uint32_t out_size )
|
||||||
{
|
{
|
||||||
z_stream strm;
|
z_stream strm;
|
||||||
strm.zalloc = Z_NULL;
|
strm.zalloc = Z_NULL;
|
||||||
strm.zfree = Z_NULL;
|
strm.zfree = Z_NULL;
|
||||||
|
@ -38,10 +34,10 @@ void no_header_decompress(uint8_t* in, uint32_t in_size, uint8_t* out, uint32_t
|
||||||
strm.next_in = Z_NULL;
|
strm.next_in = Z_NULL;
|
||||||
|
|
||||||
// Init with -15 because we do not have header in this compressed data
|
// Init with -15 because we do not have header in this compressed data
|
||||||
auto ret = inflateInit2(&strm, -15);
|
auto ret = inflateInit2( &strm, -15 );
|
||||||
if (ret != Z_OK)
|
if( ret != Z_OK )
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Error at zlib init: " + std::to_string(ret));
|
throw std::runtime_error( "Error at zlib init: " + std::to_string( ret ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set pointers to the right addresses
|
// Set pointers to the right addresses
|
||||||
|
@ -50,16 +46,14 @@ void no_header_decompress(uint8_t* in, uint32_t in_size, uint8_t* out, uint32_t
|
||||||
strm.next_out = out;
|
strm.next_out = out;
|
||||||
|
|
||||||
// Effectively decompress data
|
// Effectively decompress data
|
||||||
ret = inflate(&strm, Z_NO_FLUSH);
|
ret = inflate( &strm, Z_NO_FLUSH );
|
||||||
if (ret != Z_STREAM_END)
|
if( ret != Z_STREAM_END )
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Error at zlib inflate: " + std::to_string(ret));
|
throw std::runtime_error( "Error at zlib inflate: " + std::to_string( ret ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
inflateEnd(&strm);
|
inflateEnd( &strm );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
13
deps/datReader/zlib.h
vendored
13
deps/datReader/zlib.h
vendored
|
@ -4,18 +4,13 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace xiv
|
namespace xiv::utils::zlib
|
||||||
{
|
|
||||||
namespace utils
|
|
||||||
{
|
|
||||||
namespace zlib
|
|
||||||
{
|
{
|
||||||
|
|
||||||
void compress(const std::vector<char>& in, std::vector<char>& out);
|
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);
|
|
||||||
|
void no_header_decompress( uint8_t* in, uint32_t in_size, uint8_t* out, uint32_t out_size );
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // XIV_UTILS_ZLIB_H
|
#endif // XIV_UTILS_ZLIB_H
|
||||||
|
|
1
deps/ffxiv-actions
vendored
Submodule
1
deps/ffxiv-actions
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit dde9b5bbfc7c0197de0b0b49b982a0ee9fe761ab
|
4
deps/mysqlConnector/Connection.cpp
vendored
4
deps/mysqlConnector/Connection.cpp
vendored
|
@ -4,6 +4,10 @@
|
||||||
#include "PreparedStatement.h"
|
#include "PreparedStatement.h"
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// fixes compile error when compiling with vs2019
|
||||||
|
#include <stdexcept>
|
||||||
|
#endif
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
Mysql::Connection::Connection( std::shared_ptr< MySqlBase > pBase,
|
Mysql::Connection::Connection( std::shared_ptr< MySqlBase > pBase,
|
||||||
|
|
2
deps/mysqlConnector/Connection.h
vendored
2
deps/mysqlConnector/Connection.h
vendored
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "MysqlCommon.h"
|
#include "MysqlCommon.h"
|
||||||
|
|
||||||
typedef struct st_mysql MYSQL;
|
typedef struct st_mysql MYSQL;
|
||||||
|
|
11
deps/stackwalker/CMakeLists.txt
vendored
11
deps/stackwalker/CMakeLists.txt
vendored
|
@ -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()
|
|
1469
deps/stackwalker/StackWalker.cpp
vendored
1469
deps/stackwalker/StackWalker.cpp
vendored
File diff suppressed because it is too large
Load diff
255
deps/stackwalker/StackWalker.h
vendored
255
deps/stackwalker/StackWalker.h
vendored
|
@ -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__
|
|
6
deps/watchdog/Watchdog.h
vendored
6
deps/watchdog/Watchdog.h
vendored
|
@ -31,8 +31,8 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <experimental/filesystem>
|
#include <filesystem>
|
||||||
namespace ci { namespace fs = std::experimental::filesystem; }
|
namespace ci { namespace fs = std::filesystem; }
|
||||||
|
|
||||||
//! Exception for when Watchdog can't locate a file or parse the wildcard
|
//! Exception for when Watchdog can't locate a file or parse the wildcard
|
||||||
class WatchedFileSystemExc : public std::exception {
|
class WatchedFileSystemExc : public std::exception {
|
||||||
|
@ -319,7 +319,7 @@ protected:
|
||||||
std::string mFilter;
|
std::string mFilter;
|
||||||
std::function<void(const ci::fs::path&)> mCallback;
|
std::function<void(const ci::fs::path&)> mCallback;
|
||||||
std::function<void(const std::vector<ci::fs::path>&)> mListCallback;
|
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;
|
std::mutex mMutex;
|
||||||
|
|
|
@ -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
|
@ -400,13 +400,6 @@ CREATE TABLE `dbupdate` (
|
||||||
PRIMARY KEY(`name`)
|
PRIMARY KEY(`name`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) 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` (
|
CREATE TABLE `house` (
|
||||||
`HouseId` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
`HouseId` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
`LandSetId` int(10) UNSIGNED DEFAULT NULL,
|
`LandSetId` int(10) UNSIGNED DEFAULT NULL,
|
||||||
|
@ -602,3 +595,8 @@ CREATE TABLE `charamonsternote` (
|
||||||
`UPDATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP,
|
`UPDATE_DATE` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY(`CharacterId`)
|
PRIMARY KEY(`CharacterId`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
CREATE TABLE `__Migration` (
|
||||||
|
`MigrationName` VARCHAR(250) NOT NULL,
|
||||||
|
PRIMARY KEY (`MigrationName`)
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
|
|
@ -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
|
|
|
@ -1,14 +0,0 @@
|
||||||
#include "LoginSession.h"
|
|
||||||
|
|
||||||
namespace Sapphire {
|
|
||||||
LoginSession::LoginSession( void )
|
|
||||||
{
|
|
||||||
//setSocket(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoginSession::~LoginSession( void )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
|
|
@ -1,29 +1,24 @@
|
||||||
#include "PlayerMinimal.h"
|
#include "PlayerMinimal.h"
|
||||||
|
|
||||||
#include <Util/Util.h>
|
|
||||||
#include <Common.h>
|
#include <Common.h>
|
||||||
#include <Exd/ExdDataGenerated.h>
|
#include <Exd/ExdDataGenerated.h>
|
||||||
|
|
||||||
#include <Database/DatabaseDef.h>
|
#include <Database/DatabaseDef.h>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
extern Sapphire::Data::ExdDataGenerated g_exdDataGen;
|
extern Sapphire::Data::ExdDataGenerated g_exdDataGen;
|
||||||
|
|
||||||
namespace Sapphire {
|
namespace Sapphire::Api {
|
||||||
|
|
||||||
using namespace Common;
|
using namespace Common;
|
||||||
|
|
||||||
// player constructor
|
// player constructor
|
||||||
PlayerMinimal::PlayerMinimal( void ) :
|
PlayerMinimal::PlayerMinimal() :
|
||||||
m_id( 0 )
|
m_id( 0 )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// deconstructor
|
|
||||||
PlayerMinimal::~PlayerMinimal( void )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// load player from the db
|
// 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 PlayerMinimal::getInfoJson()
|
||||||
{
|
{
|
||||||
std::string charDetails = "{\"content\":[\"" + std::string( getName() ) + "\"," +
|
auto payload = nlohmann::json();
|
||||||
"[\"0\",\"0\",\"0\",\"0\",\"" + std::to_string( m_classLevel ) +
|
auto& c = payload["content"];
|
||||||
"\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\"],"
|
|
||||||
"\"0\",\"0\",\"0\",\"" +
|
// DisplayName
|
||||||
std::to_string( getBirthMonth() ) +
|
c.push_back( getName() );
|
||||||
"\",\"" + std::to_string( getBirthDay() ) +
|
|
||||||
"\",\"" + std::to_string( getGuardianDeity() ) +
|
// class levels
|
||||||
"\",\"" + std::to_string( m_class ) +
|
auto levelsArray = nlohmann::json();
|
||||||
"\",\"0\",\"" + std::to_string( getZoneId() ) +
|
for( int i = 0; i < Common::CLASSJOB_SLOTS; ++i )
|
||||||
"\",\"0\"," +
|
{
|
||||||
"[" + getLookString() + "]," +
|
// these must be strings
|
||||||
"\"" + std::to_string( m_modelMainWeapon ) + "\",\"" + std::to_string( m_modelSubWeapon ) + "\"," +
|
levelsArray.push_back( std::to_string( m_classMap[ i ] ) );
|
||||||
"[" + getModelString() + "]," +
|
}
|
||||||
"\"1\",\"0\",\"0\",\"0\",\"" + std::to_string( m_equipDisplayFlags ) +
|
|
||||||
"\",\"0\",\"\",\"0\",\"0\"]," +
|
// ClassLv
|
||||||
"\"classname\":\"ClientSelectData\",\"classid\":116}";
|
c.push_back( levelsArray );
|
||||||
return charDetails;
|
|
||||||
|
// 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()
|
uint8_t PlayerMinimal::getClassLevel()
|
||||||
|
@ -150,30 +182,6 @@ uint8_t PlayerMinimal::getClassLevel()
|
||||||
return static_cast< uint8_t >( m_classMap[ classJobIndex ] );
|
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()
|
void PlayerMinimal::saveAsNew()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -2,18 +2,19 @@
|
||||||
#define _PLAYERMINIMAL_H
|
#define _PLAYERMINIMAL_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
#include <string.h>
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace Sapphire
|
namespace Sapphire::Api
|
||||||
{
|
{
|
||||||
|
|
||||||
class PlayerMinimal
|
class PlayerMinimal
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PlayerMinimal( void );
|
PlayerMinimal();
|
||||||
|
|
||||||
~PlayerMinimal( void );
|
~PlayerMinimal() = default;
|
||||||
|
|
||||||
// write player to the database
|
// write player to the database
|
||||||
void write();
|
void write();
|
||||||
|
@ -23,14 +24,8 @@ namespace Sapphire
|
||||||
|
|
||||||
void saveAsNew();
|
void saveAsNew();
|
||||||
|
|
||||||
std::string getLookString();
|
|
||||||
|
|
||||||
std::string getInfoJson();
|
std::string getInfoJson();
|
||||||
|
|
||||||
std::string getModelString();
|
|
||||||
|
|
||||||
std::string getClassString();
|
|
||||||
|
|
||||||
uint8_t getClassLevel();
|
uint8_t getClassLevel();
|
||||||
|
|
||||||
// return the id of the actor
|
// return the id of the actor
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "SapphireAPI.h"
|
#include "SapphireApi.h"
|
||||||
#include <Crypt/base64.h>
|
#include <Crypt/base64.h>
|
||||||
#include "Session.h"
|
#include "Session.h"
|
||||||
#include "PlayerMinimal.h"
|
#include "PlayerMinimal.h"
|
||||||
|
@ -10,7 +10,9 @@
|
||||||
|
|
||||||
#include <Database/DatabaseDef.h>
|
#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 =
|
std::string query =
|
||||||
"SELECT account_id FROM accounts WHERE account_name = '" + username + "' AND account_pass = '" + pass + "';";
|
"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
|
// create session for the new sessionid and store to sessionlist
|
||||||
auto pSession = std::make_shared< Session >();
|
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
|
// get account from login name
|
||||||
auto pQR = g_charaDb.query( "SELECT account_id FROM accounts WHERE account_name = '" + username + "';" );
|
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 std::string& infoJson,
|
||||||
const uint32_t gmRank )
|
const uint32_t gmRank )
|
||||||
{
|
{
|
||||||
Sapphire::PlayerMinimal newPlayer;
|
Api::PlayerMinimal newPlayer;
|
||||||
|
|
||||||
newPlayer.setAccountId( accountId );
|
newPlayer.setAccountId( accountId );
|
||||||
newPlayer.setId( getNextCharId() );
|
newPlayer.setId( getNextCharId() );
|
||||||
|
@ -169,7 +171,7 @@ int Sapphire::Network::SapphireAPI::createCharacter( const uint32_t accountId, c
|
||||||
return newPlayer.getAccountId();
|
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;
|
PlayerMinimal deletePlayer;
|
||||||
auto charList = getCharList( accountId );
|
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 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 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 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 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 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 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 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 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 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(
|
auto pQR = g_charaDb.query(
|
||||||
"SELECT CharacterId, ContentId FROM charainfo WHERE AccountId = " + std::to_string( accountId ) + ";" );
|
"SELECT CharacterId, ContentId FROM charainfo WHERE AccountId = " + std::to_string( accountId ) + ";" );
|
||||||
|
|
||||||
while( pQR->next() )
|
while( pQR->next() )
|
||||||
{
|
{
|
||||||
Sapphire::PlayerMinimal player;
|
Api::PlayerMinimal player;
|
||||||
|
|
||||||
uint32_t charId = pQR->getUInt( 1 );
|
uint32_t charId = pQR->getUInt( 1 );
|
||||||
|
|
||||||
|
@ -220,7 +224,7 @@ std::vector< Sapphire::PlayerMinimal > Sapphire::Network::SapphireAPI::getCharLi
|
||||||
return charList;
|
return charList;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sapphire::Network::SapphireAPI::checkNameTaken( std::string name )
|
bool SapphireApi::checkNameTaken( std::string name )
|
||||||
{
|
{
|
||||||
|
|
||||||
g_charaDb.escapeString( name );
|
g_charaDb.escapeString( name );
|
||||||
|
@ -234,7 +238,7 @@ bool Sapphire::Network::SapphireAPI::checkNameTaken( std::string name )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Sapphire::Network::SapphireAPI::getNextCharId()
|
uint32_t SapphireApi::getNextCharId()
|
||||||
{
|
{
|
||||||
uint32_t charId = 0;
|
uint32_t charId = 0;
|
||||||
|
|
||||||
|
@ -250,7 +254,7 @@ uint32_t Sapphire::Network::SapphireAPI::getNextCharId()
|
||||||
return charId;
|
return charId;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Sapphire::Network::SapphireAPI::getNextContentId()
|
uint64_t SapphireApi::getNextContentId()
|
||||||
{
|
{
|
||||||
uint64_t contentId = 0;
|
uint64_t contentId = 0;
|
||||||
|
|
||||||
|
@ -266,7 +270,7 @@ uint64_t Sapphire::Network::SapphireAPI::getNextContentId()
|
||||||
return contentId;
|
return contentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sapphire::Network::SapphireAPI::checkSession( const std::string& sId )
|
int SapphireApi::checkSession( const std::string& sId )
|
||||||
{
|
{
|
||||||
auto it = m_sessionMap.find( 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 );
|
auto it = m_sessionMap.find( sId );
|
||||||
|
|
|
@ -7,19 +7,15 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "PlayerMinimal.h"
|
#include "PlayerMinimal.h"
|
||||||
|
|
||||||
namespace Sapphire
|
namespace Sapphire::Api
|
||||||
{
|
{
|
||||||
class Session;
|
class Session;
|
||||||
}
|
|
||||||
|
|
||||||
namespace Sapphire::Network
|
class SapphireApi
|
||||||
{
|
|
||||||
|
|
||||||
class SapphireAPI
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SapphireAPI() = default;
|
SapphireApi() = default;
|
||||||
~SapphireAPI() = default;
|
~SapphireApi() = default;
|
||||||
|
|
||||||
using SessionMap = std::map< std::string, std::shared_ptr< Session > >;
|
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 );
|
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 );
|
bool checkNameTaken( std::string name );
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Session.h"
|
#include "Session.h"
|
||||||
|
|
||||||
namespace Sapphire {
|
using namespace Sapphire::Api;
|
||||||
|
|
||||||
Session::Session()
|
Session::Session()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -35,4 +36,3 @@ void Session::setAccountId( uint32_t id )
|
||||||
{
|
{
|
||||||
m_accountId = id;
|
m_accountId = id;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
namespace Sapphire
|
namespace Sapphire::Api
|
||||||
{
|
{
|
||||||
|
|
||||||
class Session
|
class Session
|
||||||
|
|
|
@ -22,25 +22,23 @@
|
||||||
//Added for the default_resource example
|
//Added for the default_resource example
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <experimental/filesystem>
|
#include <filesystem>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <Framework.h>
|
|
||||||
#include <Logging/Logger.h>
|
#include <Logging/Logger.h>
|
||||||
|
|
||||||
#include "Forwards.h"
|
#include "SapphireApi.h"
|
||||||
#include "SapphireAPI.h"
|
|
||||||
|
|
||||||
#include <Util/CrashHandler.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::Db::DbWorkerPool< Sapphire::Db::ZoneDbConnection > g_charaDb;
|
||||||
Sapphire::Data::ExdDataGenerated g_exdDataGen;
|
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 std;
|
||||||
using namespace Sapphire;
|
using namespace Sapphire;
|
||||||
|
@ -59,7 +57,7 @@ Sapphire::Common::Config::ApiConfig m_config;
|
||||||
|
|
||||||
void reloadConfig()
|
void reloadConfig()
|
||||||
{
|
{
|
||||||
auto pConfig = std::make_shared< Sapphire::ConfigMgr >();
|
auto pConfig = std::make_shared< Sapphire::Common::ConfigMgr >();
|
||||||
|
|
||||||
Logger::info( "Loading config " + configPath );
|
Logger::info( "Loading config " + configPath );
|
||||||
|
|
||||||
|
@ -106,7 +104,7 @@ bool loadSettings( int32_t argc, char* argv[] )
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
arg = Sapphire::Util::toLowerCopy( std::string( args[ i ] ) );
|
arg = Common::Util::toLowerCopy( std::string( args[ i ] ) );
|
||||||
val = std::string( args[ i + 1 ] );
|
val = std::string( args[ i + 1 ] );
|
||||||
|
|
||||||
// trim '-' from start of arg
|
// 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 name = json["name"];
|
||||||
std::string infoJson = json["infoJson"];
|
std::string infoJson = json["infoJson"];
|
||||||
|
|
||||||
std::string finalJson = Sapphire::Util::base64Decode( infoJson );
|
std::string finalJson = Common::Util::base64Decode( infoJson );
|
||||||
|
|
||||||
// reloadConfig();
|
// reloadConfig();
|
||||||
|
|
||||||
|
@ -672,8 +670,9 @@ void defaultGet( shared_ptr< HttpServer::Response > response, shared_ptr< HttpSe
|
||||||
print_request_info( request );
|
print_request_info( request );
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto web_root_path = fs::canonical( "web" );
|
auto web_root_path = fs::current_path() / "web";
|
||||||
auto path = fs::canonical( web_root_path / request->path );
|
auto path = web_root_path / request->path;
|
||||||
|
|
||||||
//Check if path is within web_root_path
|
//Check if path is within web_root_path
|
||||||
if( distance( web_root_path.begin(), web_root_path.end() ) > distance( path.begin(), path.end() ) ||
|
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() ) )
|
!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& )
|
catch( const exception& )
|
||||||
{
|
{
|
||||||
string content = "Path not found: " + request->path;
|
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 );
|
Logger::setLogLevel( m_config.global.general.logLevel );
|
||||||
|
|
||||||
server.resource[ "^/ZoneName/([0-9]+)$" ][ "GET" ] = &getZoneName;
|
server.resource[ "^ZoneName/([0-9]+)$" ][ "GET" ] = &getZoneName;
|
||||||
server.resource[ "^/sapphire-api/lobby/createAccount" ][ "POST" ] = &createAccount;
|
server.resource[ "^sapphire-api/lobby/createAccount" ][ "POST" ] = &createAccount;
|
||||||
server.resource[ "^/sapphire-api/lobby/login" ][ "POST" ] = &login;
|
server.resource[ "^sapphire-api/lobby/login" ][ "POST" ] = &login;
|
||||||
server.resource[ "^/sapphire-api/lobby/deleteCharacter" ][ "POST" ] = &deleteCharacter;
|
server.resource[ "^sapphire-api/lobby/deleteCharacter" ][ "POST" ] = &deleteCharacter;
|
||||||
server.resource[ "^/sapphire-api/lobby/createCharacter" ][ "POST" ] = &createCharacter;
|
server.resource[ "^sapphire-api/lobby/createCharacter" ][ "POST" ] = &createCharacter;
|
||||||
server.resource[ "^/sapphire-api/lobby/insertSession" ][ "POST" ] = &insertSession;
|
server.resource[ "^sapphire-api/lobby/insertSession" ][ "POST" ] = &insertSession;
|
||||||
server.resource[ "^/sapphire-api/lobby/checkNameTaken" ][ "POST" ] = &checkNameTaken;
|
server.resource[ "^sapphire-api/lobby/checkNameTaken" ][ "POST" ] = &checkNameTaken;
|
||||||
server.resource[ "^/sapphire-api/lobby/checkSession" ][ "POST" ] = &checkSession;
|
server.resource[ "^sapphire-api/lobby/checkSession" ][ "POST" ] = &checkSession;
|
||||||
server.resource[ "^/sapphire-api/lobby/getNextCharId" ][ "POST" ] = &getNextCharId;
|
server.resource[ "^sapphire-api/lobby/getNextCharId" ][ "POST" ] = &getNextCharId;
|
||||||
server.resource[ "^/sapphire-api/lobby/getNextContentId" ][ "POST" ] = &getNextContentId;
|
server.resource[ "^sapphire-api/lobby/getNextContentId" ][ "POST" ] = &getNextContentId;
|
||||||
server.resource[ "^/sapphire-api/lobby/getCharacterList" ][ "POST" ] = &getCharacterList;
|
server.resource[ "^sapphire-api/lobby/getCharacterList" ][ "POST" ] = &getCharacterList;
|
||||||
server.resource[ "^(/frontier-api/ffxivsupport/view/get_init)(.*)" ][ "GET" ] = &get_init;
|
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[ "^(frontier-api/ffxivsupport/information/get_headline_all)(.*)" ][ "GET" ] = &get_headline_all;
|
||||||
|
|
||||||
server.default_resource[ "GET" ] = &defaultGet;
|
server.default_resource[ "GET" ] = &defaultGet;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
class case_insensitive_equals {
|
class case_insensitive_equals {
|
||||||
public:
|
public:
|
||||||
bool operator()(const std::string &key1, const std::string &key2) const {
|
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 {
|
class case_insensitive_hash {
|
||||||
|
@ -27,7 +27,7 @@ public:
|
||||||
{
|
{
|
||||||
std::size_t seed=0;
|
std::size_t seed=0;
|
||||||
for( auto &c : key )
|
for( auto &c : key )
|
||||||
Sapphire::Util::hashCombine< char >( seed, std::tolower( c ) );
|
Sapphire::Common::Util::hashCombine< char >( seed, std::tolower( c ) );
|
||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -304,7 +304,7 @@ namespace SimpleWeb {
|
||||||
size_t path_end;
|
size_t path_end;
|
||||||
if((path_end=line.find(' ', method_end+1))!=std::string::npos) {
|
if((path_end=line.find(' ', method_end+1))!=std::string::npos) {
|
||||||
request->method=line.substr(0, method_end);
|
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;
|
size_t protocol_end;
|
||||||
if((protocol_end=line.find('/', path_end+1))!=std::string::npos) {
|
if((protocol_end=line.find('/', path_end+1))!=std::string::npos) {
|
||||||
|
@ -388,7 +388,7 @@ namespace SimpleWeb {
|
||||||
|
|
||||||
auto range=request->header.equal_range("Connection");
|
auto range=request->header.equal_range("Connection");
|
||||||
for(auto it=range.first;it!=range.second;it++) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if(http_version>1.05)
|
if(http_version>1.05)
|
||||||
|
|
|
@ -26,10 +26,6 @@ if( UNIX )
|
||||||
PUBLIC
|
PUBLIC
|
||||||
pthread
|
pthread
|
||||||
stdc++fs )
|
stdc++fs )
|
||||||
else()
|
|
||||||
target_link_libraries( common
|
|
||||||
PUBLIC
|
|
||||||
stackwalker )
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories( common
|
target_include_directories( common
|
||||||
|
|
|
@ -21,6 +21,14 @@ namespace Sapphire::Common
|
||||||
const int32_t INVALID_GAME_OBJECT_ID = 0xE0000000;
|
const int32_t INVALID_GAME_OBJECT_ID = 0xE0000000;
|
||||||
const uint64_t INVALID_GAME_OBJECT_ID64 = 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.
|
* @brief The maximum length (in ms) of a combo before it is canceled/voided.
|
||||||
*
|
*
|
||||||
|
@ -41,13 +49,13 @@ namespace Sapphire::Common
|
||||||
uint8_t plot;
|
uint8_t plot;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum InventoryOperation : uint8_t
|
enum InventoryOperation : uint16_t
|
||||||
{
|
{
|
||||||
Discard = 0x07,
|
Discard = 0x013C,
|
||||||
Move = 0x08,
|
Move = 0x013D,
|
||||||
Swap = 0x09,
|
Swap = 0x013E,
|
||||||
Merge = 0x0C,
|
Split = 0x013F,
|
||||||
Split = 0x0A
|
Merge = 0x0141,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ClientLanguage : uint8_t
|
enum ClientLanguage : uint8_t
|
||||||
|
@ -151,44 +159,46 @@ namespace Sapphire::Common
|
||||||
ModelRing2 = 9
|
ModelRing2 = 9
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EquipSlotCategory : uint8_t
|
enum class EquipSlotCategory : uint8_t
|
||||||
{
|
{
|
||||||
Unequippable = 0,
|
|
||||||
|
|
||||||
// main slots
|
// main slots
|
||||||
|
|
||||||
CharaMainHand = 1,
|
CharaMainHand = 0,
|
||||||
CharaOffHand = 2,
|
CharaOffHand = 1,
|
||||||
CharaHead = 3,
|
CharaHead = 2,
|
||||||
CharaBody = 4,
|
CharaBody = 3,
|
||||||
CharaHands = 5,
|
CharaHands = 4,
|
||||||
CharaWaist = 6,
|
CharaWaist = 5,
|
||||||
CharaLegs = 7,
|
CharaLegs = 6,
|
||||||
CharaFeet = 8,
|
CharaFeet = 7,
|
||||||
CharaEars = 9,
|
CharaEars = 8,
|
||||||
CharaNeck = 10,
|
CharaNeck = 9,
|
||||||
CharaWrist = 11,
|
CharaWrist = 10,
|
||||||
CharaRing = 12,
|
CharaRing = 11,
|
||||||
CharaSoulCrystal = 17,
|
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 */
|
/*! Cannot equip gear to offhand slot */
|
||||||
MainTwoHandedWeapon = 13,
|
//MainTwoHandedWeapon = 13,
|
||||||
/*! Can be equipped in either main or offhand slot */
|
/*! Can be equipped in either main or offhand slot */
|
||||||
MainOrOffHand = 14, // unused
|
//MainOrOffHand = 14, // unused
|
||||||
/*! Cannot equip gear to head */
|
/*! Cannot equip gear to head */
|
||||||
BodyDisallowHead = 15,
|
//BodyDisallowHead = 15,
|
||||||
/*! Cannot equip gear to hands, legs and feet slots */
|
/*! Cannot equip gear to hands, legs and feet slots */
|
||||||
BodyDisallowHandsLegsFeet = 16,
|
//BodyDisallowHandsLegsFeet = 16,
|
||||||
/*! Cannot equip gear to feet slot */
|
/*! Cannot equip gear to feet slot */
|
||||||
LegsDisallowFeet = 18,
|
//LegsDisallowFeet = 18,
|
||||||
/*! Cannot equp gear to head, hands, legs, feet slots */
|
/*! Cannot equp gear to head, hands, legs, feet slots */
|
||||||
BodyDisallowAll = 19,
|
//BodyDisallowAll = 19,
|
||||||
/*! Cannot equip gear to hands slot */
|
/*! Cannot equip gear to hands slot */
|
||||||
BodyDisallowHands = 20,
|
//BodyDisallowHands = 20,
|
||||||
/*! Cannot equip gear to legs & feet slots */
|
/*! Cannot equip gear to legs & feet slots */
|
||||||
BodyDisallowLegsFeet = 21,
|
//BodyDisallowLegsFeet = 21,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum InventoryType : uint16_t
|
enum InventoryType : uint16_t
|
||||||
|
@ -204,10 +214,12 @@ namespace Sapphire::Common
|
||||||
Currency = 2000,
|
Currency = 2000,
|
||||||
Crystal = 2001,
|
Crystal = 2001,
|
||||||
//UNKNOWN_0 = 2003,
|
//UNKNOWN_0 = 2003,
|
||||||
KeyItem = 2004,
|
KeyItem = 2004,
|
||||||
HandIn = 2005,
|
HandIn = 2005,
|
||||||
DamagedGear = 2007,
|
DamagedGear = 2007,
|
||||||
//UNKNOWN_1 = 2008,
|
//UNKNOWN_1 = 2008,
|
||||||
|
// Temporary inventory that is used for the "trade" window
|
||||||
|
TradeInventory = 2009,
|
||||||
|
|
||||||
ArmoryOff = 3200,
|
ArmoryOff = 3200,
|
||||||
ArmoryHead = 3201,
|
ArmoryHead = 3201,
|
||||||
|
@ -216,13 +228,19 @@ namespace Sapphire::Common
|
||||||
ArmoryWaist = 3204,
|
ArmoryWaist = 3204,
|
||||||
ArmoryLegs = 3205,
|
ArmoryLegs = 3205,
|
||||||
ArmoryFeet = 3206,
|
ArmoryFeet = 3206,
|
||||||
ArmoryNeck = 3207,
|
ArmoryEar = 3207,
|
||||||
ArmoryEar = 3208,
|
ArmoryNeck = 3208,
|
||||||
ArmoryWrist = 3209,
|
ArmoryWrist = 3209,
|
||||||
ArmoryRing = 3300,
|
ArmoryRing = 3300,
|
||||||
|
|
||||||
ArmorySoulCrystal = 3400,
|
ArmorySoulCrystal = 3400,
|
||||||
ArmoryMain = 3500,
|
ArmoryMain = 3500,
|
||||||
|
|
||||||
|
SaddleBag0 = 4000,
|
||||||
|
SaddleBag1 = 4001,
|
||||||
|
// These are the ones you get when paying for premium companion app
|
||||||
|
PremiumSaddleBag0 = 4100,
|
||||||
|
PremiumSaddleBag1 = 4101,
|
||||||
|
|
||||||
RetainerBag0 = 10000,
|
RetainerBag0 = 10000,
|
||||||
RetainerBag1 = 10001,
|
RetainerBag1 = 10001,
|
||||||
|
@ -396,7 +414,7 @@ namespace Sapphire::Common
|
||||||
struct StatusEffect
|
struct StatusEffect
|
||||||
{
|
{
|
||||||
uint16_t effect_id;
|
uint16_t effect_id;
|
||||||
uint16_t unknown1;
|
uint16_t param;
|
||||||
float duration;
|
float duration;
|
||||||
uint32_t sourceActorId;
|
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
|
enum struct ActionAspect : uint8_t
|
||||||
{
|
{
|
||||||
None = 0, // Doesn't imply unaspected
|
None = 0, // Doesn't imply unaspected
|
||||||
|
@ -565,19 +607,27 @@ namespace Sapphire::Common
|
||||||
None = 0, // ?
|
None = 0, // ?
|
||||||
MagicPoints = 3,
|
MagicPoints = 3,
|
||||||
TacticsPoints = 5,
|
TacticsPoints = 5,
|
||||||
// WARGauge = 22,
|
StatusEffect = 10,
|
||||||
// DRKGauge = 25,
|
WARGauge = 22,
|
||||||
// AetherflowStack = 30,
|
DRKGauge = 25,
|
||||||
// Status = 32,
|
// AetherflowStack = 30,
|
||||||
// PLDGauge = 41,
|
// Status = 32,
|
||||||
// RDMGaugeBoth = 74,
|
SAMKenki = 39,
|
||||||
//// RDMGaugeBlack = 75, // not right?
|
SAMSen = 40,
|
||||||
// DRGGauge3Eyes = 76,
|
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,
|
Unknown_0 = 0,
|
||||||
Slashing = 1,
|
Slashing = 1,
|
||||||
Piercing = 2,
|
Piercing = 2,
|
||||||
|
@ -606,28 +656,41 @@ namespace Sapphire::Common
|
||||||
TpLoss = 12,
|
TpLoss = 12,
|
||||||
TpGain = 13,
|
TpGain = 13,
|
||||||
GpGain = 14,
|
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.
|
* @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 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
|
* @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,
|
Knockback = 33,
|
||||||
Mount = 38,
|
Mount = 40, // shifted one down from 5.18
|
||||||
VFX = 59, // links to VFX sheet
|
VFX = 59, // links to VFX sheet
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ActionHitSeverityType : uint8_t
|
enum class ActionHitSeverityType : uint8_t
|
||||||
{
|
{
|
||||||
NormalDamage = 0,
|
NormalDamage = 0,
|
||||||
CritHeal = 0,
|
NormalHeal = 0,
|
||||||
CritDamage = 1,
|
CritDamage = 1,
|
||||||
NormalHeal = 1,
|
CritHeal = 1,
|
||||||
DirectHitDamage = 2,
|
DirectHitDamage = 2,
|
||||||
CritDirectHitDamage = 3
|
CritDirectHitDamage = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ActionEffectResultFlag : uint8_t
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Absorbed = 0x04,
|
||||||
|
ExtendedValue = 0x40,
|
||||||
|
EffectOnSource = 0x80,
|
||||||
|
Reflected = 0xA0,
|
||||||
|
};
|
||||||
|
|
||||||
enum ItemActionType : uint16_t
|
enum ItemActionType : uint16_t
|
||||||
{
|
{
|
||||||
ItemActionVFX = 852,
|
ItemActionVFX = 852,
|
||||||
|
@ -644,15 +707,15 @@ namespace Sapphire::Common
|
||||||
struct EffectEntry
|
struct EffectEntry
|
||||||
{
|
{
|
||||||
Common::ActionEffectType effectType;
|
Common::ActionEffectType effectType;
|
||||||
Common::ActionHitSeverityType hitSeverity;
|
uint8_t param0;
|
||||||
uint8_t param;
|
uint8_t param1;
|
||||||
/*!
|
/*!
|
||||||
* @brief Shows an additional percentage in the battle log
|
* @brief Shows an additional percentage in the battle log
|
||||||
*
|
*
|
||||||
* Has no effect on what is shown and stored in value
|
* Has no effect on what is shown and stored in value
|
||||||
*/
|
*/
|
||||||
int8_t bonusPercent;
|
uint8_t param2;
|
||||||
uint8_t valueMultiplier; // This multiplies whatever value is in the 'value' param by 10. Possibly a workaround for big numbers
|
uint8_t extendedValueHighestByte;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
int16_t value;
|
int16_t value;
|
||||||
};
|
};
|
||||||
|
@ -968,8 +1031,6 @@ namespace Sapphire::Common
|
||||||
|
|
||||||
enum LevelTableEntry : uint8_t
|
enum LevelTableEntry : uint8_t
|
||||||
{
|
{
|
||||||
PIE,
|
|
||||||
MP,
|
|
||||||
MAIN,
|
MAIN,
|
||||||
SUB,
|
SUB,
|
||||||
DIV,
|
DIV,
|
||||||
|
@ -982,7 +1043,225 @@ namespace Sapphire::Common
|
||||||
{
|
{
|
||||||
SingleTarget = 1,
|
SingleTarget = 1,
|
||||||
CircularAOE = 2,
|
CircularAOE = 2,
|
||||||
|
Type3 = 3, // another single target? no idea how to call it
|
||||||
RectangularAOE = 4,
|
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 >;
|
using PlayerStateFlagList = std::vector< PlayerStateFlag >;
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
/* This file has been automatically generated.
|
/* This file has been automatically generated.
|
||||||
Changes will be lost upon regeneration.
|
Changes will be lost upon regeneration.
|
||||||
To change the content edit tools/exd_common_gen */
|
To change the content edit tools/exd_common_gen */
|
||||||
namespace Sapphire {
|
namespace Sapphire::Common {
|
||||||
namespace Common {
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
//ActionCategory.exd
|
//ActionCategory.exd
|
||||||
|
@ -173,6 +172,8 @@ enum class ClassJob : uint8_t
|
||||||
Samurai = 34,
|
Samurai = 34,
|
||||||
Redmage = 35,
|
Redmage = 35,
|
||||||
Bluemage = 36,
|
Bluemage = 36,
|
||||||
|
Gunbreaker = 37,
|
||||||
|
Dancer = 38,
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -199,14 +200,10 @@ enum class ContentType : uint8_t
|
||||||
DisciplesoftheHand = 17,
|
DisciplesoftheHand = 17,
|
||||||
RetainerVentures = 18,
|
RetainerVentures = 18,
|
||||||
GoldSaucer = 19,
|
GoldSaucer = 19,
|
||||||
one = 20,
|
|
||||||
DeepDungeons = 21,
|
DeepDungeons = 21,
|
||||||
two = 22,
|
|
||||||
three = 23,
|
|
||||||
WondrousTails = 24,
|
WondrousTails = 24,
|
||||||
CustomDeliveries = 25,
|
CustomDeliveries = 25,
|
||||||
Eureka = 26,
|
Eureka = 26,
|
||||||
four = 27,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -217,7 +214,6 @@ enum class EmoteCategory : uint8_t
|
||||||
General = 1,
|
General = 1,
|
||||||
Special = 2,
|
Special = 2,
|
||||||
Expressions = 3,
|
Expressions = 3,
|
||||||
one = 4,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -227,7 +223,7 @@ enum class ExVersion : uint8_t
|
||||||
ARealmReborn = 0,
|
ARealmReborn = 0,
|
||||||
Heavensward = 1,
|
Heavensward = 1,
|
||||||
Stormblood = 2,
|
Stormblood = 2,
|
||||||
three = 3,
|
Shadowbringers = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -369,6 +365,8 @@ enum class ItemUICategory : uint8_t
|
||||||
SubmersibleBow = 103,
|
SubmersibleBow = 103,
|
||||||
SubmersibleBridge = 104,
|
SubmersibleBridge = 104,
|
||||||
BlueMagesArm = 105,
|
BlueMagesArm = 105,
|
||||||
|
GunbreakersArm = 106,
|
||||||
|
DancersArm = 107,
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -393,7 +391,7 @@ enum class ItemSearchCategory : uint8_t
|
||||||
ConjurersArms = 15,
|
ConjurersArms = 15,
|
||||||
ArcanistsArms = 16,
|
ArcanistsArms = 16,
|
||||||
Shields = 17,
|
Shields = 17,
|
||||||
ThrowingWeapons = 18,
|
DancersArms = 18,
|
||||||
CarpentersTools = 19,
|
CarpentersTools = 19,
|
||||||
BlacksmithsTools = 20,
|
BlacksmithsTools = 20,
|
||||||
ArmorersTools = 21,
|
ArmorersTools = 21,
|
||||||
|
@ -454,13 +452,15 @@ enum class ItemSearchCategory : uint8_t
|
||||||
DarkKnightsArms = 76,
|
DarkKnightsArms = 76,
|
||||||
MachinistsArms = 77,
|
MachinistsArms = 77,
|
||||||
AstrologiansArms = 78,
|
AstrologiansArms = 78,
|
||||||
Airship_SubmersibleComponents = 79,
|
AirshipSubmersibleComponents = 79,
|
||||||
OrchestrionComponents = 80,
|
OrchestrionComponents = 80,
|
||||||
GardeningItems = 81,
|
GardeningItems = 81,
|
||||||
Paintings = 82,
|
Paintings = 82,
|
||||||
SamuraisArms = 83,
|
SamuraisArms = 83,
|
||||||
RedMagesArms = 84,
|
RedMagesArms = 84,
|
||||||
ScholarsArms = 85,
|
ScholarsArms = 85,
|
||||||
|
GunbreakersArms = 86,
|
||||||
|
ThrowingWeapons = 87,
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -527,6 +527,8 @@ enum class Race : uint8_t
|
||||||
Miqote = 4,
|
Miqote = 4,
|
||||||
Roegadyn = 5,
|
Roegadyn = 5,
|
||||||
AuRa = 6,
|
AuRa = 6,
|
||||||
|
Hrothgar = 7,
|
||||||
|
Viera = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -546,6 +548,10 @@ enum class Tribe : uint8_t
|
||||||
Hellsguard = 10,
|
Hellsguard = 10,
|
||||||
Raen = 11,
|
Raen = 11,
|
||||||
Xaela = 12,
|
Xaela = 12,
|
||||||
|
Helions = 13,
|
||||||
|
TheLost = 14,
|
||||||
|
Rava = 15,
|
||||||
|
Veena = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -558,6 +564,7 @@ enum class Town : uint8_t
|
||||||
Uldah = 3,
|
Uldah = 3,
|
||||||
Ishgard = 4,
|
Ishgard = 4,
|
||||||
Kugane = 7,
|
Kugane = 7,
|
||||||
|
TheCrystarium = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -680,7 +687,21 @@ enum class Weather : uint8_t
|
||||||
TrueBlue = 113,
|
TrueBlue = 113,
|
||||||
TrueBlue1 = 114,
|
TrueBlue1 = 114,
|
||||||
TrueBlue2 = 115,
|
TrueBlue2 = 115,
|
||||||
|
UmbralTurbulence = 116,
|
||||||
TrueBlue3 = 117,
|
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,
|
Library = 14,
|
||||||
PhotoStudio = 15,
|
PhotoStudio = 15,
|
||||||
HauntedHouse = 16,
|
HauntedHouse = 16,
|
||||||
|
Atelier = 17,
|
||||||
|
Bathhouse = 18,
|
||||||
|
Garden = 19,
|
||||||
|
FarEastern = 20,
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
#include "ConfigMgr.h"
|
#include "ConfigMgr.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <filesystem>
|
||||||
#include <experimental/filesystem>
|
|
||||||
|
|
||||||
namespace fs = std::experimental::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
using namespace Sapphire;
|
||||||
|
using namespace Sapphire::Common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads an ini file and parses it
|
* Loads an ini file and parses it
|
||||||
* @param configName the name of ini file relative to m_configFolderRoot to load alongside global.ini
|
* @param configName the name of ini file relative to m_configFolderRoot to load alongside global.ini
|
||||||
* @return true if loading was successful
|
* @return true if loading was successful
|
||||||
*/
|
*/
|
||||||
bool Sapphire::ConfigMgr::loadConfig( const std::string& configName )
|
bool ConfigMgr::loadConfig( const std::string& configName )
|
||||||
{
|
{
|
||||||
// get global config
|
// get global config
|
||||||
auto configFile = fs::path( fs::path( m_configFolderRoot ) / configName );
|
auto configFile = fs::path( fs::path( m_configFolderRoot ) / configName );
|
||||||
|
@ -29,7 +31,7 @@ bool Sapphire::ConfigMgr::loadConfig( const std::string& configName )
|
||||||
return true;
|
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 );
|
auto configFile = fs::path( fs::path( m_configFolderRoot ) / configName );
|
||||||
|
|
||||||
|
@ -71,7 +73,7 @@ bool Sapphire::ConfigMgr::loadGlobalConfig( Common::Config::GlobalConfig& config
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sapphire::ConfigMgr::copyDefaultConfig( const std::string& configName )
|
bool ConfigMgr::copyDefaultConfig( const std::string& configName )
|
||||||
{
|
{
|
||||||
fs::path configPath( m_configFolderRoot );
|
fs::path configPath( m_configFolderRoot );
|
||||||
configPath /= configName;
|
configPath /= configName;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "ConfigDef.h"
|
#include "ConfigDef.h"
|
||||||
|
|
||||||
namespace Sapphire
|
namespace Sapphire::Common
|
||||||
{
|
{
|
||||||
class ConfigMgr
|
class ConfigMgr
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,7 +41,7 @@ static inline bool is_base64( uint8_t c )
|
||||||
return ( isalnum( c ) || ( c == '+' ) || ( 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;
|
std::string ret;
|
||||||
int32_t i = 0;
|
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 in_len = encoded_string.size();
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace Sapphire::Util
|
namespace Sapphire::Common::Util
|
||||||
{
|
{
|
||||||
std::string base64Encode( uint8_t const*, uint32_t len );
|
std::string base64Encode( uint8_t const*, uint32_t len );
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
(b)[(i) + 3] = (uint8_t) ( (n) >> 24 ); \
|
(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[ 0 ] = 0;
|
||||||
ctx->total[ 1 ] = 0;
|
ctx->total[ 1 ] = 0;
|
||||||
|
@ -48,7 +48,7 @@ void Sapphire::Util::md5_starts( md5_context* ctx )
|
||||||
ctx->state[ 3 ] = 0x10325476;
|
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;
|
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;
|
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;
|
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
|
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 last, padn;
|
||||||
uint32_t high, low;
|
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
|
* 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_context ctx;
|
||||||
md5_starts( &ctx );
|
md5_starts( &ctx );
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace Sapphire::Util
|
namespace Sapphire::Common::Util
|
||||||
{
|
{
|
||||||
using md5_context = struct
|
using md5_context = struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef SAPPHIRE_DBCOMMON_H
|
#ifndef SAPPHIRE_DBCOMMON_H
|
||||||
#define SAPPHIRE_DBCOMMON_H
|
#define SAPPHIRE_DBCOMMON_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace Sapphire::Db
|
namespace Sapphire::Db
|
||||||
{
|
{
|
||||||
struct ConnectionInfo
|
struct ConnectionInfo
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "Logging/Logger.h"
|
#include "Logging/Logger.h"
|
||||||
|
|
||||||
#include "PreparedStatement.h"
|
#include "PreparedStatement.h"
|
||||||
#include "Framework.h"
|
|
||||||
|
|
||||||
Sapphire::Db::DbConnection::DbConnection( ConnectionInfo& connInfo ) :
|
Sapphire::Db::DbConnection::DbConnection( ConnectionInfo& connInfo ) :
|
||||||
m_reconnecting( false ),
|
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 ) :
|
Sapphire::Db::ConnectionInfo& connInfo ) :
|
||||||
m_reconnecting( false ),
|
m_reconnecting( false ),
|
||||||
m_prepareError( false ),
|
m_prepareError( false ),
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace Sapphire::Db
|
||||||
DbConnection( ConnectionInfo& connInfo );
|
DbConnection( ConnectionInfo& connInfo );
|
||||||
|
|
||||||
// Constructor for asynchronous connections.
|
// 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();
|
virtual ~DbConnection();
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ namespace Sapphire::Db
|
||||||
bool m_prepareError;
|
bool m_prepareError;
|
||||||
|
|
||||||
private:
|
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< DbWorker > m_worker;
|
||||||
std::shared_ptr< Mysql::Connection > m_pConnection;
|
std::shared_ptr< Mysql::Connection > m_pConnection;
|
||||||
ConnectionInfo& m_connectionInfo;
|
ConnectionInfo& m_connectionInfo;
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
#include "Operation.h"
|
#include "Operation.h"
|
||||||
#include "Util/LockedWaitQueue.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 )
|
DbConnection* pConn )
|
||||||
{
|
{
|
||||||
m_pConn = pConn;
|
m_pConn = pConn;
|
||||||
|
|
|
@ -14,12 +14,12 @@ namespace Sapphire::Db
|
||||||
class DbWorker
|
class DbWorker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DbWorker( LockedWaitQueue< std::shared_ptr< Operation > >* newQueue, DbConnection* connection );
|
DbWorker( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* newQueue, DbConnection* connection );
|
||||||
|
|
||||||
~DbWorker();
|
~DbWorker();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LockedWaitQueue< std::shared_ptr< Operation > >* m_queue;
|
Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* m_queue;
|
||||||
DbConnection* m_pConn;
|
DbConnection* m_pConn;
|
||||||
|
|
||||||
void workerThread();
|
void workerThread();
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "StatementTask.h"
|
#include "StatementTask.h"
|
||||||
#include "Operation.h"
|
#include "Operation.h"
|
||||||
#include "ZoneDbConnection.h"
|
#include "ZoneDbConnection.h"
|
||||||
#include "Framework.h"
|
|
||||||
|
|
||||||
#include "Logging/Logger.h"
|
#include "Logging/Logger.h"
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
@ -21,7 +20,7 @@ class PingOperation : public Sapphire::Db::Operation
|
||||||
|
|
||||||
template< class T >
|
template< class T >
|
||||||
Sapphire::Db::DbWorkerPool< T >::DbWorkerPool() :
|
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_asyncThreads( 0 ),
|
||||||
m_synchThreads( 0 )
|
m_synchThreads( 0 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace Sapphire::Db
|
||||||
|
|
||||||
const std::string& getDatabaseName() const;
|
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;
|
std::array< std::vector< std::shared_ptr< T > >, IDX_SIZE > m_connections;
|
||||||
ConnectionInfo m_connectionInfo;
|
ConnectionInfo m_connectionInfo;
|
||||||
uint8_t m_asyncThreads;
|
uint8_t m_asyncThreads;
|
||||||
|
|
|
@ -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 ) :
|
ConnectionInfo& connInfo ) :
|
||||||
DbConnection( q, connInfo )
|
DbConnection( q, connInfo )
|
||||||
{
|
{
|
||||||
|
@ -22,18 +22,20 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
|
||||||
m_stmts.resize( MAX_STATEMENTS );
|
m_stmts.resize( MAX_STATEMENTS );
|
||||||
|
|
||||||
/// CHARA
|
/// CHARA
|
||||||
prepareStatement( CHARA_SEL, "SELECT ContentId, Name, Hp, Mp, Tp, Gp, Mode, Mount, InvincibleGM, Voice, "
|
prepareStatement( CHARA_SEL,
|
||||||
"Customize, ModelMainWeapon, ModelSubWeapon, ModelSystemWeapon, "
|
"SELECT ContentId, Name, Hp, Mp, Tp, Gp, Mode, Mount, InvincibleGM, Voice, "
|
||||||
"ModelEquip, EmoteModeType, FirstLoginTime, Language, IsNewGame, "
|
"Customize, ModelMainWeapon, ModelSubWeapon, ModelSystemWeapon, "
|
||||||
"IsNewAdventurer, TerritoryType, TerritoryId, PosX, PosY, PosZ, PosR, "
|
"ModelEquip, EmoteModeType, FirstLoginTime, Language, IsNewGame, "
|
||||||
"OTerritoryType, OTerritoryId, OPosX, OPosY, OPosZ, OPosR, GuardianDeity, "
|
"IsNewAdventurer, TerritoryType, TerritoryId, PosX, PosY, PosZ, PosR, "
|
||||||
"BirthDay, BirthMonth, Class, Status, TotalPlayTime, FirstClass, HomePoint, "
|
"OTerritoryType, OTerritoryId, OPosX, OPosY, OPosZ, OPosR, GuardianDeity, "
|
||||||
"FavoritePoint, RestPoint, StartTown, ActiveTitle, TitleList, Achievement, "
|
"BirthDay, BirthMonth, Class, Status, TotalPlayTime, FirstClass, HomePoint, "
|
||||||
"Aetheryte, HowTo, Minions, Mounts, Orchestrion, EquippedMannequin, ConfigFlags, "
|
"FavoritePoint, RestPoint, StartTown, ActiveTitle, TitleList, Achievement, "
|
||||||
"QuestCompleteFlags, OpeningSequence, QuestTracking, GrandCompany, "
|
"Aetheryte, HowTo, Minions, Mounts, Orchestrion, EquippedMannequin, ConfigFlags, "
|
||||||
"GrandCompanyRank, Discovery, GMRank, EquipDisplayFlags, Unlocks, CFPenaltyUntil, "
|
"QuestCompleteFlags, OpeningSequence, QuestTracking, GrandCompany, "
|
||||||
"Pose "
|
"GrandCompanyRank, Discovery, GMRank, EquipDisplayFlags, Unlocks, CFPenaltyUntil, "
|
||||||
"FROM charainfo WHERE CharacterId = ?;", CONNECTION_SYNC );
|
"Pose "
|
||||||
|
"FROM charainfo WHERE CharacterId = ?;",
|
||||||
|
CONNECTION_SYNC );
|
||||||
|
|
||||||
|
|
||||||
prepareStatement( CHARA_UP,
|
prepareStatement( CHARA_UP,
|
||||||
|
@ -47,19 +49,23 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
|
||||||
"ActiveTitle = ?, TitleList = ?, Achievement = ?, Aetheryte = ?, HowTo = ?, Minions = ?, Mounts = ?, Orchestrion = ?, "
|
"ActiveTitle = ?, TitleList = ?, Achievement = ?, Aetheryte = ?, HowTo = ?, Minions = ?, Mounts = ?, Orchestrion = ?, "
|
||||||
"EquippedMannequin = ?, ConfigFlags = ?, QuestCompleteFlags = ?, OpeningSequence = ?, "
|
"EquippedMannequin = ?, ConfigFlags = ?, QuestCompleteFlags = ?, OpeningSequence = ?, "
|
||||||
"QuestTracking = ?, GrandCompany = ?, GrandCompanyRank = ?, Discovery = ?, GMRank = ?, EquipDisplayFlags = ?, Unlocks = ?, "
|
"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,
|
||||||
"Class, ContentId, BirthDay, BirthMonth, EquipDisplayFlags "
|
"SELECT Name, Customize, ModelMainWeapon, ModelSubWeapon, ModelEquip, TerritoryType, GuardianDeity, "
|
||||||
"FROM charainfo WHERE CharacterId = ?;", CONNECTION_SYNC );
|
"Class, ContentId, BirthDay, BirthMonth, EquipDisplayFlags "
|
||||||
|
"FROM charainfo WHERE CharacterId = ?;",
|
||||||
|
CONNECTION_SYNC );
|
||||||
|
|
||||||
prepareStatement( CHARA_INS, "INSERT INTO charainfo (AccountId, CharacterId, ContentId, Name, Hp, Mp, "
|
prepareStatement( CHARA_INS,
|
||||||
"Customize, Voice, IsNewGame, TerritoryType, PosX, PosY, PosZ, PosR, ModelEquip, "
|
"INSERT INTO charainfo (AccountId, CharacterId, ContentId, Name, Hp, Mp, "
|
||||||
"IsNewAdventurer, GuardianDeity, Birthday, BirthMonth, Class, Status, FirstClass, "
|
"Customize, Voice, IsNewGame, TerritoryType, PosX, PosY, PosZ, PosR, ModelEquip, "
|
||||||
"HomePoint, StartTown, Discovery, HowTo, QuestCompleteFlags, Unlocks, QuestTracking, "
|
"IsNewAdventurer, GuardianDeity, Birthday, BirthMonth, Class, Status, FirstClass, "
|
||||||
"Aetheryte, GMRank, Mounts, Orchestrion, UPDATE_DATE ) "
|
"HomePoint, StartTown, Discovery, HowTo, QuestCompleteFlags, Unlocks, QuestTracking, "
|
||||||
"VALUES ( ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW() );",
|
"Aetheryte, GMRank, Mounts, Orchestrion, UPDATE_DATE ) "
|
||||||
|
"VALUES ( ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW() );",
|
||||||
CONNECTION_SYNC );
|
CONNECTION_SYNC );
|
||||||
|
|
||||||
prepareStatement( CHARA_UP_NAME, "UPDATE charainfo SET Name = ? WHERE CharacterId = ?;", CONNECTION_ASYNC );
|
prepareStatement( CHARA_UP_NAME, "UPDATE charainfo SET Name = ? WHERE CharacterId = ?;", CONNECTION_ASYNC );
|
||||||
|
|
|
@ -112,7 +112,7 @@ namespace Sapphire::Db
|
||||||
|
|
||||||
ZoneDbConnection( ConnectionInfo& connInfo );
|
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();
|
~ZoneDbConnection();
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -5,12 +5,16 @@
|
||||||
|
|
||||||
namespace Sapphire
|
namespace Sapphire
|
||||||
{
|
{
|
||||||
class ConfigMgr;
|
|
||||||
class Framework;
|
class Framework;
|
||||||
using ConfigMgrPtr = std::shared_ptr< ConfigMgr >;
|
|
||||||
using FrameworkPtr = std::shared_ptr< Framework >;
|
using FrameworkPtr = std::shared_ptr< Framework >;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Sapphire::Common
|
||||||
|
{
|
||||||
|
class ConfigMgr;
|
||||||
|
using ConfigMgrPtr = std::shared_ptr< ConfigMgr >;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Sapphire::Network
|
namespace Sapphire::Network
|
||||||
{
|
{
|
||||||
class Hive;
|
class Hive;
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#include "Framework.h"
|
|
||||||
#include "Logging/Logger.h"
|
|
|
@ -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
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "Logger.h"
|
#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/spdlog.h>
|
||||||
#include <spdlog/async.h>
|
#include <spdlog/async.h>
|
||||||
|
@ -8,9 +8,9 @@
|
||||||
#include <spdlog/sinks/daily_file_sink.h>
|
#include <spdlog/sinks/daily_file_sink.h>
|
||||||
|
|
||||||
// #include <iostream>
|
// #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 )
|
void Sapphire::Logger::init( const std::string& logPath )
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
#include "Acceptor.h"
|
#include "Acceptor.h"
|
||||||
#include "Connection.h"
|
#include "Connection.h"
|
||||||
|
|
||||||
Sapphire::Network::Acceptor::Acceptor( HivePtr hive ) :
|
|
||||||
|
using namespace Sapphire;
|
||||||
|
|
||||||
|
Network::Acceptor::Acceptor( HivePtr hive ) :
|
||||||
m_hive( hive ),
|
m_hive( hive ),
|
||||||
m_acceptor( hive->getService() ),
|
m_acceptor( hive->getService() ),
|
||||||
m_io_strand( 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;
|
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 v1 = 1;
|
||||||
uint32_t v2 = 0;
|
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(),
|
m_acceptor.async_accept( connection->getSocket(),
|
||||||
connection->getStrand().wrap( std::bind( &Acceptor::handleAccept,
|
connection->getStrand().wrap( std::bind( &Acceptor::handleAccept,
|
||||||
|
@ -46,7 +49,7 @@ void Sapphire::Network::Acceptor::dispatchAccept( ConnectionPtr connection )
|
||||||
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() )
|
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 ) );
|
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
|
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;
|
return m_hive;
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::ip::tcp::acceptor& Sapphire::Network::Acceptor::getAcceptor()
|
asio::ip::tcp::acceptor& Network::Acceptor::getAcceptor()
|
||||||
{
|
{
|
||||||
return m_acceptor;
|
return m_acceptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sapphire::Network::Acceptor::hasError()
|
bool Network::Acceptor::hasError()
|
||||||
{
|
{
|
||||||
uint32_t v1 = 1;
|
uint32_t v1 = 1;
|
||||||
uint32_t v2 = 1;
|
uint32_t v2 = 1;
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
namespace Sapphire::Network::ActorControl
|
namespace Sapphire::Network::ActorControl
|
||||||
{
|
{
|
||||||
|
|
||||||
enum ActorControlType : uint16_t
|
enum ActorControlType : uint16_t
|
||||||
{
|
{
|
||||||
/*! Toggles weapon status -> Sheathed/UnSheathed
|
/*! Toggles weapon status -> Sheathed/UnSheathed
|
||||||
\param param1 status 0|1 */
|
\param param1 status 0|1 */
|
||||||
ToggleWeapon = 0x00,
|
ToggleWeapon = 0x00,
|
||||||
|
@ -24,6 +24,9 @@ enum ActorControlType : uint16_t
|
||||||
SetStatus = 0x02,
|
SetStatus = 0x02,
|
||||||
CastStart = 0x03,
|
CastStart = 0x03,
|
||||||
ToggleAggro = 0x04,
|
ToggleAggro = 0x04,
|
||||||
|
/*!
|
||||||
|
* param1 = ClassJob ID
|
||||||
|
*/
|
||||||
ClassJobChange = 0x05,
|
ClassJobChange = 0x05,
|
||||||
DefeatMsg = 0x06,
|
DefeatMsg = 0x06,
|
||||||
GainExpMsg = 0x07,
|
GainExpMsg = 0x07,
|
||||||
|
@ -98,6 +101,8 @@ enum ActorControlType : uint16_t
|
||||||
|
|
||||||
FreeEventPos = 0x8A,
|
FreeEventPos = 0x8A,
|
||||||
|
|
||||||
|
DailyQuestSeed = 0x90, // param1 = the daily quest seed
|
||||||
|
|
||||||
SetBGM = 0xA1,
|
SetBGM = 0xA1,
|
||||||
|
|
||||||
UnlockAetherCurrentMsg = 0xA4,
|
UnlockAetherCurrentMsg = 0xA4,
|
||||||
|
@ -140,6 +145,15 @@ enum ActorControlType : uint16_t
|
||||||
|
|
||||||
SetPose = 0x127,
|
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,
|
CraftingUnk = 0x12C,
|
||||||
|
|
||||||
GatheringSenseMsg = 0x130,
|
GatheringSenseMsg = 0x130,
|
||||||
|
@ -173,6 +187,14 @@ enum ActorControlType : uint16_t
|
||||||
|
|
||||||
RelicInfuseMsg = 0x179,
|
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,
|
AetherReductionDlg = 0x17D,
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -204,6 +226,22 @@ enum ActorControlType : uint16_t
|
||||||
ChallengeEntryCompleteMsg = 0x20B,
|
ChallengeEntryCompleteMsg = 0x20B,
|
||||||
ChallengeEntryUnlockMsg = 0x20C,
|
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,
|
GilTrailMsg = 0x211,
|
||||||
|
|
||||||
HuntingLogRankUnlock = 0x21D,
|
HuntingLogRankUnlock = 0x21D,
|
||||||
|
@ -220,10 +258,22 @@ enum ActorControlType : uint16_t
|
||||||
|
|
||||||
GearSetEquipMsg = 0x321,
|
GearSetEquipMsg = 0x321,
|
||||||
|
|
||||||
|
SetBait = 0x325, // param1: bait ID
|
||||||
|
|
||||||
SetFestival = 0x386, // param1: festival.exd index
|
SetFestival = 0x386, // param1: festival.exd index
|
||||||
|
|
||||||
ToggleOrchestrionUnlock = 0x396,
|
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
|
// Duty Recorder
|
||||||
BeginReplayAck = 0x3A2,
|
BeginReplayAck = 0x3A2,
|
||||||
|
@ -300,6 +350,7 @@ enum ActorControlType : uint16_t
|
||||||
|
|
||||||
DismountReq = 0x65,
|
DismountReq = 0x65,
|
||||||
SpawnCompanionReq = 0x66,
|
SpawnCompanionReq = 0x66,
|
||||||
|
DespawnCompanionReq = 0x67,
|
||||||
RemoveStatusEffect = 0x68,
|
RemoveStatusEffect = 0x68,
|
||||||
CastCancel = 0x69,
|
CastCancel = 0x69,
|
||||||
|
|
||||||
|
@ -315,20 +366,26 @@ enum ActorControlType : uint16_t
|
||||||
UpdatedSeenHowTos = 0x133,
|
UpdatedSeenHowTos = 0x133,
|
||||||
AllotAttribute = 0x135,
|
AllotAttribute = 0x135,
|
||||||
|
|
||||||
ClearWaymarks = 0x13A,
|
ClearFieldMarkers = 0x13A,
|
||||||
CameraMode = 0x13B, // param12, 1 = camera mode enable, 0 = disable
|
CameraMode = 0x13B, // param12, 1 = camera mode enable, 0 = disable
|
||||||
CharaNameReq = 0x13D, // requests character name by content id
|
CharaNameReq = 0x13D, // requests character name by content id
|
||||||
HuntingLogDetails = 0x194,
|
HuntingLogDetails = 0x194,
|
||||||
|
|
||||||
Timers = 0x1AB,
|
Timers = 0x1AB,
|
||||||
|
|
||||||
DyeItem = 0x1B5,
|
DyeItem = 0x1B0, // updated 5.21
|
||||||
|
|
||||||
RequestChocoboInventory = 0x1C4,
|
RequestChocoboInventory = 0x1C4,
|
||||||
|
|
||||||
EmoteReq = 0x1F4,
|
EmoteReq = 0x1F4,
|
||||||
EmoteCancel = 0x1F6,
|
EmoteCancel = 0x1F6,
|
||||||
PersistentEmoteCancel = 0x1F7,
|
PersistentEmoteCancel = 0x1F7,
|
||||||
|
/*!
|
||||||
|
* param2 = pose ID
|
||||||
|
* 0 = idle pose 0 (just standing)
|
||||||
|
* 1 = idle pose 1
|
||||||
|
* 2-4 = idle poses 2-4
|
||||||
|
*/
|
||||||
PoseChange = 0x1F9,
|
PoseChange = 0x1F9,
|
||||||
PoseReapply = 0x1FA,
|
PoseReapply = 0x1FA,
|
||||||
PoseCancel = 0x1FB,
|
PoseCancel = 0x1FB,
|
||||||
|
@ -337,6 +394,8 @@ enum ActorControlType : uint16_t
|
||||||
AchievementComp = 0x203,
|
AchievementComp = 0x203,
|
||||||
AchievementCatChat = 0x206,
|
AchievementCatChat = 0x206,
|
||||||
|
|
||||||
|
RequestEventBattle = 0x232C,
|
||||||
|
|
||||||
QuestJournalUpdateQuestVisibility = 0x2BE,
|
QuestJournalUpdateQuestVisibility = 0x2BE,
|
||||||
QuestJournalClosed = 0x2BF,
|
QuestJournalClosed = 0x2BF,
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
#include "Connection.h"
|
#include "Connection.h"
|
||||||
#include "Hive.h"
|
#include "Hive.h"
|
||||||
#include <functional>
|
#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_hive( hive ),
|
||||||
m_socket( hive->getService() ),
|
m_socket( hive->getService() ),
|
||||||
m_io_strand( hive->getService() ),
|
m_io_strand( hive->getService() ),
|
||||||
m_receive_buffer_size( 32000 ),
|
m_receive_buffer_size( 32000 ),
|
||||||
m_error_state( 0 ),
|
m_error_state( 0 )
|
||||||
m_pFw( pFw )
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
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 );
|
asio::ip::tcp::endpoint endpoint( asio::ip::address::from_string( ip ), port );
|
||||||
m_socket.open( endpoint.protocol() );
|
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 );
|
m_socket.bind( endpoint );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::Network::Connection::startSend()
|
void Network::Connection::startSend()
|
||||||
{
|
{
|
||||||
if( !m_pending_sends.empty() )
|
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 )
|
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 v1 = 1;
|
||||||
uint32_t v2 = 0;
|
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() )
|
if( error || hasError() || m_hive->hasStopped() )
|
||||||
{
|
{
|
||||||
|
@ -94,8 +92,8 @@ 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 )
|
std::list< std::vector< uint8_t > >::iterator itr )
|
||||||
{
|
{
|
||||||
if( error || hasError() || m_hive->hasStopped() )
|
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() )
|
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();
|
bool should_start_send = m_pending_sends.empty();
|
||||||
m_pending_sends.push_back( buffer );
|
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();
|
bool should_start_receive = m_pending_recvs.empty();
|
||||||
m_pending_recvs.push_back( total_bytes );
|
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 resolver( m_hive->getService() );
|
||||||
asio::ip::tcp::resolver::query query( host, std::to_string( port ) );
|
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();
|
onDisconnect();
|
||||||
m_socket.close();
|
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 ) );
|
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 ) );
|
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;
|
return m_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::strand& Sapphire::Network::Connection::getStrand()
|
asio::strand& Network::Connection::getStrand()
|
||||||
{
|
{
|
||||||
return m_io_strand;
|
return m_io_strand;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sapphire::Network::HivePtr Sapphire::Network::Connection::getHive()
|
Network::HivePtr Network::Connection::getHive()
|
||||||
{
|
{
|
||||||
return m_hive;
|
return m_hive;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::Network::Connection::setReceiveBufferSize( int32_t size )
|
void Network::Connection::setReceiveBufferSize( int32_t size )
|
||||||
{
|
{
|
||||||
m_receive_buffer_size = size;
|
m_receive_buffer_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Sapphire::Network::Connection::getReceiveBufferSize() const
|
int32_t Network::Connection::getReceiveBufferSize() const
|
||||||
{
|
{
|
||||||
return m_receive_buffer_size;
|
return m_receive_buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sapphire::Network::Connection::hasError()
|
bool Network::Connection::hasError()
|
||||||
{
|
{
|
||||||
uint32_t v1 = 1;
|
uint32_t v1 = 1;
|
||||||
uint32_t v2 = 1;
|
uint32_t v2 = 1;
|
||||||
|
|
|
@ -12,12 +12,6 @@
|
||||||
#include "Acceptor.h"
|
#include "Acceptor.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Sapphire
|
|
||||||
{
|
|
||||||
class Framework;
|
|
||||||
using FrameworkPtr = std::shared_ptr< Framework >;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Sapphire::Network
|
namespace Sapphire::Network
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -41,9 +35,8 @@ namespace Sapphire::Network
|
||||||
std::list< std::vector< uint8_t > > m_pending_sends;
|
std::list< std::vector< uint8_t > > m_pending_sends;
|
||||||
int32_t m_receive_buffer_size;
|
int32_t m_receive_buffer_size;
|
||||||
std::atomic< uint32_t > m_error_state;
|
std::atomic< uint32_t > m_error_state;
|
||||||
Sapphire::FrameworkPtr m_pFw;
|
|
||||||
|
|
||||||
Connection( HivePtr hive, FrameworkPtr pFw );
|
Connection( HivePtr hive );
|
||||||
|
|
||||||
virtual ~Connection();
|
virtual ~Connection();
|
||||||
|
|
||||||
|
@ -147,13 +140,13 @@ namespace Sapphire::Network
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template< class T >
|
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
|
try
|
||||||
{
|
{
|
||||||
AcceptorPtr acceptor( new Acceptor( pHive ) );
|
AcceptorPtr acceptor( new Acceptor( pHive ) );
|
||||||
acceptor->listen( listenIp, port );
|
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 );
|
acceptor->accept( connection );
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,7 +257,7 @@ namespace Sapphire::Network::Packets
|
||||||
|
|
||||||
// The IPC type itself.
|
// The IPC type itself.
|
||||||
m_ipcHdr.type = static_cast< ServerZoneIpcType >( m_data._ServerIpcType );
|
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 );
|
m_segHdr.size = sizeof( T ) + sizeof( FFXIVARR_IPC_HEADER ) + sizeof( FFXIVARR_PACKET_SEGMENT_HEADER );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
|
|
||||||
#include <string.h> // memcpy
|
#include <string.h> // memcpy
|
||||||
|
|
||||||
|
using namespace Sapphire;
|
||||||
using namespace Sapphire::Network::Packets;
|
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,
|
const uint32_t offset,
|
||||||
FFXIVARR_PACKET_HEADER& header )
|
FFXIVARR_PACKET_HEADER& header )
|
||||||
{
|
{
|
||||||
|
@ -25,7 +26,7 @@ PacketParseResult Sapphire::Network::Packets::getHeader( const std::vector< uint
|
||||||
return Success;
|
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,
|
const uint32_t offset,
|
||||||
FFXIVARR_PACKET_SEGMENT_HEADER& header )
|
FFXIVARR_PACKET_SEGMENT_HEADER& header )
|
||||||
{
|
{
|
||||||
|
@ -42,7 +43,7 @@ PacketParseResult Sapphire::Network::Packets::getSegmentHeader( const std::vecto
|
||||||
return Success;
|
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 uint32_t offset,
|
||||||
const FFXIVARR_PACKET_HEADER& packetHeader,
|
const FFXIVARR_PACKET_HEADER& packetHeader,
|
||||||
std::vector< FFXIVARR_PACKET_RAW >& packets )
|
std::vector< FFXIVARR_PACKET_RAW >& packets )
|
||||||
|
@ -81,7 +82,7 @@ PacketParseResult Sapphire::Network::Packets::getPackets( const std::vector< uin
|
||||||
return Success;
|
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 )
|
FFXIVARR_PACKET_RAW& packet )
|
||||||
{
|
{
|
||||||
// Copy segment header
|
// Copy segment header
|
||||||
|
@ -103,7 +104,7 @@ PacketParseResult Sapphire::Network::Packets::getPacket( const std::vector< uint
|
||||||
return Success;
|
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.
|
// Max size of the packet is capped at 1MB for now.
|
||||||
if( header.size > 1 * 1024 * 1024 )
|
if( header.size > 1 * 1024 * 1024 )
|
||||||
|
@ -116,7 +117,7 @@ bool Sapphire::Network::Packets::checkHeader( const FFXIVARR_PACKET_HEADER& head
|
||||||
return true;
|
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.
|
// Max size of individual message is capped at 256KB for now.
|
||||||
if( header.size > 256 * 1024 )
|
if( header.size > 256 * 1024 )
|
||||||
|
|
|
@ -2,41 +2,43 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "Hive.h"
|
#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_work_ptr( new asio::io_service::work( m_io_service ) ),
|
||||||
m_shutdown( 0 )
|
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;
|
return m_io_service;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sapphire::Network::Hive::hasStopped()
|
bool Network::Hive::hasStopped()
|
||||||
{
|
{
|
||||||
uint32_t v1 = 1;
|
uint32_t v1 = 1;
|
||||||
uint32_t v2 = 1;
|
uint32_t v2 = 1;
|
||||||
return m_shutdown.compare_exchange_strong( v1, v2 );
|
return m_shutdown.compare_exchange_strong( v1, v2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::Network::Hive::poll()
|
void Network::Hive::poll()
|
||||||
{
|
{
|
||||||
m_io_service.poll();
|
m_io_service.poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::Network::Hive::run()
|
void Network::Hive::run()
|
||||||
{
|
{
|
||||||
m_io_service.run();
|
m_io_service.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::Network::Hive::stop()
|
void Network::Hive::stop()
|
||||||
{
|
{
|
||||||
uint32_t v1 = 1;
|
uint32_t v1 = 1;
|
||||||
uint32_t v2 = 0;
|
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 v1 = 0;
|
||||||
uint32_t v2 = 1;
|
uint32_t v2 = 1;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Sapphire:: Network
|
namespace Sapphire::Network
|
||||||
{
|
{
|
||||||
|
|
||||||
class Hive : public std::enable_shared_from_this< Hive >
|
class Hive : public std::enable_shared_from_this< Hive >
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
Sapphire::Network::Packets::PacketContainer::PacketContainer( uint32_t segmentTargetOverride ) :
|
using namespace Sapphire;
|
||||||
|
|
||||||
|
Network::Packets::PacketContainer::PacketContainer( uint32_t segmentTargetOverride ) :
|
||||||
m_segmentTargetOverride( segmentTargetOverride )
|
m_segmentTargetOverride( segmentTargetOverride )
|
||||||
{
|
{
|
||||||
memset( &m_ipcHdr, 0, sizeof( FFXIVARR_PACKET_HEADER ) );
|
memset( &m_ipcHdr, 0, sizeof( FFXIVARR_PACKET_HEADER ) );
|
||||||
|
@ -15,12 +17,12 @@ Sapphire::Network::Packets::PacketContainer::PacketContainer( uint32_t segmentTa
|
||||||
m_ipcHdr.count = 0;
|
m_ipcHdr.count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sapphire::Network::Packets::PacketContainer::~PacketContainer()
|
Network::Packets::PacketContainer::~PacketContainer()
|
||||||
{
|
{
|
||||||
m_entryList.clear();
|
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 );
|
m_entryList.push_back( entry );
|
||||||
|
|
||||||
|
@ -28,7 +30,7 @@ void Sapphire::Network::Packets::PacketContainer::addPacket( Sapphire::Network::
|
||||||
m_ipcHdr.count++;
|
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 );
|
std::vector< uint8_t > tempBuffer( m_ipcHdr.size );
|
||||||
memset( &tempBuffer[ 0 ], 0, 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;
|
std::vector< uint8_t > tmpBuffer;
|
||||||
|
|
||||||
|
@ -76,7 +78,7 @@ std::string Sapphire::Network::Packets::PacketContainer::toString()
|
||||||
std::string str = "\n";
|
std::string str = "\n";
|
||||||
for( uint32_t i = 0; i < m_ipcHdr.size; i++ )
|
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 )
|
if( ( i + 1 ) % 16 == 0 )
|
||||||
str += "\n";
|
str += "\n";
|
||||||
|
|
|
@ -4,10 +4,8 @@
|
||||||
#include <Common.h>
|
#include <Common.h>
|
||||||
#include <Network/CommonNetwork.h>
|
#include <Network/CommonNetwork.h>
|
||||||
|
|
||||||
namespace Sapphire {
|
namespace Sapphire::Network::Packets::Server
|
||||||
namespace Network {
|
{
|
||||||
namespace Packets {
|
|
||||||
namespace Server {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Structural representation of the packet sent by the server as response
|
* Structural representation of the packet sent by the server as response
|
||||||
|
@ -31,10 +29,37 @@ struct FFXIVIpcTellErrNotFound : FFXIVIpcBasePacket< TellErrNotFound >
|
||||||
char receipientName[32];
|
char receipientName[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* Server */
|
struct FFXIVIpcFreeCompanyEvent : FFXIVIpcBasePacket< FreeCompanyEvent >
|
||||||
} /* Packets */
|
{
|
||||||
} /* Network */
|
uint16_t unknown;
|
||||||
} /* Sapphire */
|
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 */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,176 +43,219 @@ namespace Sapphire::Network::Packets
|
||||||
*/
|
*/
|
||||||
enum ServerZoneIpcType : uint16_t
|
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 )
|
ActorFreeSpawn = 0x0239, // updated 5.35 hotfix
|
||||||
Ping = 0x0065,
|
InitZone = 0x03CD, // updated 5.35 hotfix
|
||||||
Init = 0x0066,
|
|
||||||
|
|
||||||
ActorFreeSpawn = 0x0191,
|
EffectResult = 0x01C2, // updated 5.35 hotfix
|
||||||
InitZone = 0x019A,
|
ActorControl = 0x02A4, // updated 5.35 hotfix
|
||||||
|
ActorControlSelf = 0x02C8, // updated 5.35 hotfix
|
||||||
|
ActorControlTarget = 0x0209, // updated 5.35 hotfix
|
||||||
|
|
||||||
AddStatusEffect = 0x0141,
|
/*!
|
||||||
ActorControl142 = 0x0142,
|
* @brief Used when resting
|
||||||
ActorControl143 = 0x0143,
|
*/
|
||||||
ActorControl144 = 0x0144,
|
UpdateHpMpTp = 0x0319, // updated 5.35 hotfix
|
||||||
UpdateHpMpTp = 0x0145,
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
||||||
|
|
||||||
ChatBanned = 0x006B,
|
ChatBanned = 0xF06B,
|
||||||
Playtime = 0x006C, // updated 4.5
|
Playtime = 0x03A4, // updated 5.35 hotfix
|
||||||
Logout = 0x0077, // updated 4.5
|
Logout = 0x02AD, // updated 5.35 hotfix
|
||||||
CFNotify = 0x0078,
|
CFNotify = 0x02C4, // updated 5.35 hotfix
|
||||||
CFMemberStatus = 0x0079,
|
CFMemberStatus = 0x0079,
|
||||||
CFDutyInfo = 0x007A,
|
CFDutyInfo = 0x007A,
|
||||||
CFPlayerInNeed = 0x007F,
|
CFPlayerInNeed = 0xF07F,
|
||||||
|
CFPreferredRole = 0x0196, // updated 5.35 hotfix
|
||||||
|
CFCancel = 0x00EC, // updated 5.35 hotfix
|
||||||
|
SocialRequestError = 0xF0AD,
|
||||||
|
|
||||||
SocialRequestError = 0x00AD,
|
CFRegistered = 0x010C, // updated 5.35 hotfix
|
||||||
|
SocialRequestResponse = 0x01C7, // updated 5.35 hotfix
|
||||||
CFRegistered = 0x00B8, // updated 4.1
|
SocialMessage = 0x0308, // updated 5.35 hotfix
|
||||||
SocialRequestResponse = 0x00BB, // updated 4.1
|
SocialMessage2 = 0x037C, // updated 5.35 hotfix
|
||||||
CancelAllianceForming = 0x00C6, // updated 4.2
|
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,
|
LogMessage = 0x00D0,
|
||||||
|
|
||||||
LinkshellList = 0x011F, // updated 4.5
|
Chat = 0x0349, // updated 5.35 hotfix
|
||||||
|
PartyChat = 0x0065,
|
||||||
|
|
||||||
MailDeleteRequest = 0x0120, // updated 4.5
|
WorldVisitList = 0xF0FE, // added 4.5
|
||||||
ReqMoogleMailList = 0x0121, // updated 4.5
|
|
||||||
ReqMoogleMailLetter = 0x0122, // updated 4.5
|
|
||||||
MailLetterNotification = 0x0123, // updated 4.5
|
|
||||||
|
|
||||||
MarketBoardItemListingCount = 0x0125, // updated 4.5
|
SocialList = 0x0216, // updated 5.35 hotfix
|
||||||
MarketBoardItemListing = 0x0126, // updated 4.5
|
|
||||||
MarketBoardItemListingHistory = 0x012A, // updated 4.5
|
|
||||||
MarketBoardSearchResult = 0x0139, // updated 4.5
|
|
||||||
|
|
||||||
|
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
|
CharaFreeCompanyTag = 0x013B, // updated 4.5
|
||||||
FreeCompanyBoardMsg = 0x013C, // updated 4.5
|
FreeCompanyBoardMsg = 0x013C, // updated 4.5
|
||||||
FreeCompanyInfo = 0x013D, // updated 4.5
|
FreeCompanyInfo = 0xF13D, // updated 4.5
|
||||||
ExamineFreeCompanyInfo = 0x013E, // updated 4.5
|
ExamineFreeCompanyInfo = 0xF13E, // updated 4.5
|
||||||
|
|
||||||
StatusEffectList = 0x0151, // updated 4.5
|
FreeCompanyUpdateShortMessage = 0xF157, // added 5.0
|
||||||
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
|
|
||||||
|
|
||||||
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
|
GCAffiliation = 0xF16F, // updated 5.0
|
||||||
NpcSpawn = 0x0176, // updated 4.5
|
|
||||||
NpcSpawn2 = 0x0177, // ( Bigger statuseffectlist? ) updated 4.5
|
|
||||||
ActorMove = 0x0178, // updated 4.5
|
|
||||||
|
|
||||||
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
|
PartyList = 0x02B2, // updated 5.35 hotfix
|
||||||
ObjectSpawn = 0x0181, // updated 4.5
|
PartyMessage = 0x00AE, // updated 5.35 hotfix
|
||||||
ObjectDespawn = 0x0182, // updated 4.5
|
HateRank = 0x02CC, // updated 5.35 hotfix
|
||||||
UpdateClassInfo = 0x0183, // updated 4.5
|
HateList = 0x0198, // updated 5.35 hotfix
|
||||||
SilentSetClassJob = 0x0184, // updated 4.5 - seems to be the case, not sure if it's actually used for anything
|
ObjectSpawn = 0x02B8, // updated 5.35 hotfix
|
||||||
InitUI = 0x0185, // updated 4.5
|
ObjectDespawn = 0xF34B, // updated 5.18
|
||||||
PlayerStats = 0x0186, // updated 4.5
|
UpdateClassInfo = 0x0235, // updated 5.35 hotfix
|
||||||
ActorOwner = 0x0187, // updated 4.5
|
SilentSetClassJob = 0x018E, // updated 5.0 - seems to be the case, not sure if it's actually used for anything
|
||||||
PlayerStateFlags = 0x0188, // updated 4.5
|
PlayerSetup = 0x0290, // updated 5.35 hotfix
|
||||||
PlayerClassInfo = 0x0189, // updated 4.5
|
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
|
ModelEquip = 0x0277, // updated 5.35 hotfix
|
||||||
Examine = 0x018C, // updated 4.5
|
Examine = 0x00BC, // updated 5.35 hotfix
|
||||||
CharaNameReq = 0x018D, // updated 4.5
|
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
|
SetLevelSync = 0x1186, // not updated for 4.4, not sure what it is anymore
|
||||||
|
|
||||||
ItemInfo = 0x0196, // updated 4.5
|
ItemInfo = 0x0214, // updated 5.35 hotfix
|
||||||
ContainerInfo = 0x0197, // updated 4.5
|
ContainerInfo = 0x00C5, // updated 5.35 hotfix
|
||||||
InventoryTransactionFinish = 0x0198, // updated 4.5
|
InventoryTransactionFinish = 0x02F0, // updated 5.35 hotfix
|
||||||
InventoryTransaction = 0x0199, // updated 4.5
|
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
|
HuntingLogEntry = 0x0146, // updated 5.35 hotfix
|
||||||
UpdateInventorySlot = 0x019E, // updated 4.5
|
|
||||||
|
|
||||||
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
|
EventStart = 0x009A, // updated 5.35 hotfix
|
||||||
DirectorPlayScene = 0x01AF, // updated 4.5
|
EventFinish = 0x007E, // updated 5.35 hotfix
|
||||||
EventOpenGilShop = 0x01B2, // updated 4.5
|
|
||||||
|
|
||||||
EventStart = 0x01B4, // updated 4.5
|
|
||||||
EventFinish = 0x01B5, // updated 4.5
|
|
||||||
|
|
||||||
EventLinkshell = 0x1169,
|
EventLinkshell = 0x1169,
|
||||||
|
|
||||||
QuestActiveList = 0x01C8, // updated 4.5
|
QuestActiveList = 0x0117, // updated 5.35 hotfix
|
||||||
QuestUpdate = 0x01C9, // updated 4.5
|
QuestUpdate = 0x0073, // updated 5.35 hotfix
|
||||||
QuestCompleteList = 0x01CA, // updated 4.5
|
QuestCompleteList = 0x0240, // updated 5.35 hotfix
|
||||||
|
|
||||||
QuestFinish = 0x01CB, // updated 4.5
|
QuestFinish = 0x00E9, // updated 5.35 hotfix
|
||||||
MSQTrackerComplete = 0x01CC, // updated 4.5
|
MSQTrackerComplete = 0xF1D6, // updated 5.0
|
||||||
MSQTrackerProgress = 0xF1CD, // updated 4.5 ? this actually looks like the two opcodes have been combined, see #474
|
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
|
DirectorVars = 0x00E6, // updated 5.18
|
||||||
DirectorPopUp = 0x01F5, // display dialogue pop-ups in duties and FATEs, for example, Teraflare's countdown
|
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
|
CFAvailableContents = 0xF1FD, // updated 4.2
|
||||||
|
|
||||||
WeatherChange = 0x0205, // updated 4.5
|
WeatherChange = 0x027B, // updated 5.35 hotfix
|
||||||
PlayerTitleList = 0x0206, // updated 4.5?
|
PlayerTitleList = 0x037D, // updated 5.1
|
||||||
Discovery = 0x0207, // updated 4.5?
|
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 //////////////////////////////////////
|
/// Housing //////////////////////////////////////
|
||||||
|
|
||||||
LandSetInitialize = 0x0229, // updated 4.5
|
LandSetInitialize = 0x0234, // updated 5.0
|
||||||
LandUpdate = 0x022A, // updated 4.5
|
LandUpdate = 0x0235, // updated 5.0
|
||||||
YardObjectSpawn = 0x022B, // updated 4.5
|
YardObjectSpawn = 0xF236, // updated 5.0
|
||||||
HousingIndoorInitialize = 0x022C, // updated 4.5
|
HousingIndoorInitialize = 0x0237, // updated 5.0
|
||||||
LandPriceUpdate = 0x022D, // updated 4.5
|
LandPriceUpdate = 0x0238, // updated 5.0
|
||||||
LandInfoSign = 0x022E, // updated 4.5
|
LandInfoSign = 0x023D, // updated 5.35 hotfix
|
||||||
LandRename = 0x022F, // updated 4.5
|
LandRename = 0x023A, // updated 5.0
|
||||||
HousingEstateGreeting = 0x0230, // updated 4.5
|
HousingEstateGreeting = 0x023B, // updated 5.0
|
||||||
HousingUpdateLandFlagsSlot = 0x0231, // updated 4.5
|
HousingUpdateLandFlagsSlot = 0x023C, // updated 5.0
|
||||||
HousingLandFlags = 0x0232, // updated 4.5
|
HousingLandFlags = 0x022F, // updated 5.35 hotfix
|
||||||
HousingShowEstateGuestAccess = 0x0233, // updated 4.5
|
HousingShowEstateGuestAccess = 0x023E, // updated 5.0
|
||||||
|
|
||||||
HousingObjectInitialize = 0x0235, // updated 4.45
|
HousingObjectInitialize = 0x01AA, // updated 5.35 hotfix
|
||||||
HousingInternalObjectSpawn = 0x236, // updated 4.5
|
HousingInternalObjectSpawn = 0xF241, // updated 5.0
|
||||||
|
|
||||||
HousingWardInfo = 0x0238, // updated 4.5
|
HousingWardInfo = 0x02FD, // updated 5.35 hotfix
|
||||||
HousingObjectMove = 0x0239, // updated 4.5
|
HousingObjectMove = 0xF244, // updated 5.0
|
||||||
|
|
||||||
SharedEstateSettingsResponse = 0x0245, // updated 4.5
|
SharedEstateSettingsResponse = 0x0245, // updated 4.5
|
||||||
|
|
||||||
|
@ -225,16 +268,15 @@ namespace Sapphire::Network::Packets
|
||||||
DuelChallenge = 0x0277, // 4.2; this is responsible for opening the ui
|
DuelChallenge = 0x0277, // 4.2; this is responsible for opening the ui
|
||||||
PerformNote = 0x0286, // updated 4.3
|
PerformNote = 0x0286, // updated 4.3
|
||||||
|
|
||||||
PrepareZoning = 0x0299, // updated 4.5
|
PrepareZoning = 0x026C, // updated 5.35 hotfix
|
||||||
ActorGauge = 0x0292, // updated 4.3
|
ActorGauge = 0x0112, // updated 5.35 hotfix
|
||||||
|
|
||||||
// Unknown IPC types that still need to be sent
|
// daily quest info -> without them sent, login will take longer...
|
||||||
// TODO: figure all these out properly
|
DailyQuests = 0x0139, // updated 5.35 hotfix
|
||||||
IPCTYPE_UNK_320 = 0x0253, // updated 4.5
|
DailyQuestRepeatFlags = 0x024C, // updated 5.35 hotfix
|
||||||
IPCTYPE_UNK_322 = 0x0255, // updated 4.5
|
|
||||||
|
|
||||||
/// Doman Mahjong //////////////////////////////////////
|
/// 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
|
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
|
MahjongPlayerAction = 0x02BE, // tsumo(as in drawing a tile) called chi/pon/kan/riichi
|
||||||
MahjongEndRoundTsumo = 0x02BF, // called tsumo
|
MahjongEndRoundTsumo = 0x02BF, // called tsumo
|
||||||
|
@ -251,37 +293,43 @@ namespace Sapphire::Network::Packets
|
||||||
*/
|
*/
|
||||||
enum ClientZoneIpcType : uint16_t
|
enum ClientZoneIpcType : uint16_t
|
||||||
{
|
{
|
||||||
|
PingHandler = 0x0219, // updated 5.35 hotfix
|
||||||
|
InitHandler = 0x0185, // updated 5.35 hotfix
|
||||||
|
|
||||||
PingHandler = 0x0065, // unchanged 4.5
|
FinishLoadingHandler = 0x01BE, // updated 5.35 hotfix
|
||||||
InitHandler = 0x0066, // unchanged 4.5
|
|
||||||
|
|
||||||
FinishLoadingHandler = 0x0069, // unchanged 4.5
|
CFCommenceHandler = 0x0118, // updated 5.35 hotfix
|
||||||
|
|
||||||
CFCommenceHandler = 0x006F,
|
CFCancelHandler = 0x0332, // updated 5.35 hotfix
|
||||||
|
CFRegisterDuty = 0x0289, // updated 5.35 hotfix
|
||||||
|
CFRegisterRoulette = 0x0088, // updated 5.35 hotfix
|
||||||
CFRegisterDuty = 0x0071,
|
PlayTimeHandler = 0x02A8, // updated 5.35 hotfix
|
||||||
CFRegisterRoulette = 0x0072,
|
LogoutHandler = 0x00EC, // updated 5.35 hotfix
|
||||||
PlayTimeHandler = 0x0073, // unchanged 4.5
|
CancelLogout = 0x03DB, // updated 5.35 hotfix
|
||||||
LogoutHandler = 0x0074, // unchanged 4.5
|
|
||||||
|
|
||||||
CFDutyInfoHandler = 0x0078, // updated 4.2
|
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
|
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
|
SocialListHandler = 0x0340, // updated 5.35 hotfix
|
||||||
ReqSearchInfoHandler = 0x00E4, // updated 4.5
|
SetSearchInfoHandler = 0x0314, // updated 5.35 hotfix
|
||||||
ReqExamineSearchCommentHandler = 0x00E5, // updated 4.5
|
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
|
LinkshellListHandler = 0x024B, // updated 5.35 hotfix
|
||||||
PlayerSearchHandler = 0x00E6, // updated 4.5
|
|
||||||
|
|
||||||
LinkshellListHandler = 0x00F8, // updated 4.5
|
|
||||||
|
|
||||||
MarketBoardRequestItemListingInfo = 0x0102, // updated 4.5
|
MarketBoardRequestItemListingInfo = 0x0102, // updated 4.5
|
||||||
MarketBoardRequestItemListings = 0x0103, // updated 4.5
|
MarketBoardRequestItemListings = 0x0103, // updated 4.5
|
||||||
|
@ -291,58 +339,63 @@ namespace Sapphire::Network::Packets
|
||||||
|
|
||||||
FcInfoReqHandler = 0x011A, // updated 4.2
|
FcInfoReqHandler = 0x011A, // updated 4.2
|
||||||
|
|
||||||
|
FreeCompanyUpdateShortMessageHandler = 0x0123, // added 5.0
|
||||||
|
|
||||||
ReqMarketWishList = 0x012C, // updated 4.3
|
ReqMarketWishList = 0x012C, // updated 4.3
|
||||||
|
|
||||||
ReqJoinNoviceNetwork = 0x0129, // updated 4.2
|
ReqJoinNoviceNetwork = 0x0129, // updated 4.2
|
||||||
|
|
||||||
ReqCountdownInitiate = 0x0133, // updated 4.5
|
ReqCountdownInitiate = 0x009A, // updated 5.25
|
||||||
ReqCountdownCancel = 0x0134, // updated 4.5
|
ReqCountdownCancel = 0x0244, // updated 5.25
|
||||||
ClearWaymarks = 0x0135, // updated 4.5
|
|
||||||
|
|
||||||
ZoneLineHandler = 0x0137, // updated 4.5
|
ZoneLineHandler = 0x0279, // updated 5.35 hotfix
|
||||||
ClientTrigger = 0x0138, // updated 4.5
|
ClientTrigger = 0x03D3, // updated 5.35 hotfix
|
||||||
DiscoveryHandler = 0x0139, // updated 4.5
|
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
|
UpdatePositionHandler = 0x0236, // updated 5.35 hotfix
|
||||||
GMCommand1 = 0x013C, // updated 4.5
|
|
||||||
GMCommand2 = 0x013D, // updated 4.5
|
|
||||||
AoESkillHandler = 0x13E, // updated 4.5
|
|
||||||
|
|
||||||
UpdatePositionHandler = 0x013F, // updated 4.5
|
InventoryModifyHandler = 0x0135, // updated 5.35 hotfix
|
||||||
UpdatePositionInstance = 0x0183, // updated 4.3
|
|
||||||
|
InventoryEquipRecommendedItems = 0x0149, // updated 5.0
|
||||||
|
|
||||||
InventoryModifyHandler = 0x0146, // updated 4.5 ( +4 )
|
ReqPlaceHousingItem = 0x014B, // updated 5.0
|
||||||
|
BuildPresetHandler = 0x0150, // updated 5.0
|
||||||
|
|
||||||
ReqPlaceHousingItem = 0x149, // 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
|
||||||
|
|
||||||
BuildPresetHandler = 0x014E, // updated 4.5
|
ReturnEventHandler = 0x02B4, // updated 5.35 hotfix
|
||||||
TalkEventHandler = 0x014F, // updated 4.5
|
TradeReturnEventHandler = 0x00A4, // updated 5.35 hotfix
|
||||||
EmoteEventHandler = 0x0150, // updated 4.5
|
TradeMultipleReturnEventHander = 0x035C, // updated 5.35 hotfix
|
||||||
WithinRangeEventHandler = 0x0151, // updated 4.5
|
|
||||||
OutOfRangeEventHandler = 0x0152, // updated 4.5
|
|
||||||
EnterTeriEventHandler = 0x0153, // updated 4.5
|
|
||||||
|
|
||||||
ShopEventHandler = 0x0155, // updated 4.5
|
|
||||||
|
|
||||||
ReturnEventHandler = 0x0158, // updated 4.5
|
|
||||||
TradeReturnEventHandler = 0x0159, // updated 4.5
|
|
||||||
|
|
||||||
LinkshellEventHandler = 0x016B, // updated 4.5
|
LinkshellEventHandler = 0x016B, // updated 4.5
|
||||||
LinkshellEventHandler1 = 0x016C, // updated 4.5
|
LinkshellEventHandler1 = 0x016C, // updated 4.5
|
||||||
|
|
||||||
LandRenameHandler = 0x0175, // updated 4.5
|
ReqEquipDisplayFlagsChange = 0x02F6, // updated 5.35 hotfix
|
||||||
HousingUpdateHouseGreeting = 0x0176, // updated 4.5
|
|
||||||
HousingUpdateObjectPosition = 0x0177, // updated 4.5
|
|
||||||
|
|
||||||
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
|
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
|
Tell = 0x0064, // updated for sb
|
||||||
TellErrNotFound = 0x0066,
|
TellErrNotFound = 0x0066,
|
||||||
|
|
||||||
|
FreeCompanyEvent = 0x012C, // added 5.0
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,10 +4,7 @@
|
||||||
#include <Common.h>
|
#include <Common.h>
|
||||||
#include <Network/CommonNetwork.h>
|
#include <Network/CommonNetwork.h>
|
||||||
|
|
||||||
namespace Sapphire {
|
namespace Sapphire::Network::Packets::Server {
|
||||||
namespace Network {
|
|
||||||
namespace Packets {
|
|
||||||
namespace Server {
|
|
||||||
|
|
||||||
struct FFXIVIpcRetainerList :
|
struct FFXIVIpcRetainerList :
|
||||||
FFXIVIpcBasePacket< LobbyRetainerList >
|
FFXIVIpcBasePacket< LobbyRetainerList >
|
||||||
|
@ -152,7 +149,5 @@ struct FFXIVIpcLobbyError : FFXIVIpcBasePacket< LobbyError >
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,10 +4,8 @@
|
||||||
#include <Common.h>
|
#include <Common.h>
|
||||||
#include <Network/CommonNetwork.h>
|
#include <Network/CommonNetwork.h>
|
||||||
|
|
||||||
namespace Sapphire {
|
namespace Sapphire::Network::Packets::Client
|
||||||
namespace Network {
|
{
|
||||||
namespace Packets {
|
|
||||||
namespace Client {
|
|
||||||
|
|
||||||
struct FFXIVIpcGmCommand1 :
|
struct FFXIVIpcGmCommand1 :
|
||||||
FFXIVIpcBasePacket< GMCommand1 >
|
FFXIVIpcBasePacket< GMCommand1 >
|
||||||
|
@ -51,14 +49,25 @@ struct FFXIVIpcUpdatePosition :
|
||||||
FFXIVIpcBasePacket< UpdatePositionHandler >
|
FFXIVIpcBasePacket< UpdatePositionHandler >
|
||||||
{
|
{
|
||||||
/* 0000 */ float rotation;
|
/* 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;
|
/* 0007 */ uint8_t headPosition;
|
||||||
/* 0008 */ uint8_t animationType;
|
/* 0008 */ Common::FFXIVARR_POSITION3 position;
|
||||||
/* 0009 */ uint8_t animationState;
|
/* 000C */ uint8_t unk[ 4 ]; // padding?
|
||||||
/* 000A */ uint8_t clientAnimationType;
|
|
||||||
/* 000B */ uint8_t unk_2;
|
|
||||||
/* 000C */ Common::FFXIVARR_POSITION3 position;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 :
|
struct FFXIVIpcSkillHandler :
|
||||||
FFXIVIpcBasePacket< SkillHandler >
|
FFXIVIpcBasePacket< SkillHandler >
|
||||||
|
@ -198,6 +207,13 @@ struct FFXIVIpcChatHandler :
|
||||||
/* 001A */ char message[1012];
|
/* 001A */ char message[1012];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FFXIVIpcPartyChatHandler :
|
||||||
|
FFXIVIpcBasePacket< ChatHandler >
|
||||||
|
{
|
||||||
|
uint64_t unknown;
|
||||||
|
char message[1024];
|
||||||
|
};
|
||||||
|
|
||||||
struct FFXIVIpcShopEventHandler :
|
struct FFXIVIpcShopEventHandler :
|
||||||
FFXIVIpcBasePacket< ShopEventHandler >
|
FFXIVIpcBasePacket< ShopEventHandler >
|
||||||
{
|
{
|
||||||
|
@ -219,7 +235,7 @@ struct FFXIVIpcInventoryModifyHandler :
|
||||||
{
|
{
|
||||||
/* 0000 */ uint32_t seq;
|
/* 0000 */ uint32_t seq;
|
||||||
/* 0004 */ Common::InventoryOperation action;
|
/* 0004 */ Common::InventoryOperation action;
|
||||||
/* 0005 */ uint8_t pad_0005[7];
|
/* 0006 */ uint8_t pad_0006[6];
|
||||||
/* 000C */ uint16_t fromContainer;
|
/* 000C */ uint16_t fromContainer;
|
||||||
/* 000E */ uint8_t pad_000E[2];
|
/* 000E */ uint8_t pad_000E[2];
|
||||||
/* 0010 */ uint8_t fromSlot;
|
/* 0010 */ uint8_t fromSlot;
|
||||||
|
@ -325,9 +341,91 @@ struct FFXIVIpcMarketBoardRequestItemListingInfo :
|
||||||
/* 0000 */ uint32_t requestId;
|
/* 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
|
#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
115
src/common/Service.h
Normal 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
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue