mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-21 17:47:45 +00:00
Fixed exd slowness
This commit is contained in:
parent
a65b23778b
commit
137a75d5a5
9 changed files with 247 additions and 352 deletions
121
deps/datReader/DatCat.cpp
vendored
121
deps/datReader/DatCat.cpp
vendored
|
@ -1,86 +1,77 @@
|
|||
#include "DatCat.h"
|
||||
|
||||
#include "Index.h"
|
||||
#include "Dat.h"
|
||||
#include "File.h"
|
||||
#include "GameData.h"
|
||||
#include "Index.h"
|
||||
|
||||
namespace xiv
|
||||
{
|
||||
namespace dat
|
||||
{
|
||||
namespace dat
|
||||
{
|
||||
|
||||
Cat::Cat( const std::filesystem::path& basePath, uint32_t catNum, const std::string& name ) :
|
||||
m_name( name ),
|
||||
m_catNum( catNum ),
|
||||
m_chunk( -1 )
|
||||
{
|
||||
// From the category number, compute back the real filename for.index .datXs
|
||||
std::stringstream ss;
|
||||
ss << std::setw( 2 ) << std::setfill( '0' ) << std::hex << catNum;
|
||||
std::string prefix = ss.str() + "0000.win32";
|
||||
Cat::Cat( const std::filesystem::path& basePath, uint32_t catNum, const std::string& name ) : m_name( name ),
|
||||
m_catNum( catNum ),
|
||||
m_chunk( -1 )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::setw( 2 ) << std::setfill( '0' ) << std::hex << catNum;
|
||||
std::string prefix = ss.str() + "0000.win32";
|
||||
|
||||
// Creates the index: XX0000.win32.index
|
||||
m_index = std::unique_ptr<Index>( new Index( basePath / "ffxiv" / ( prefix + ".index" ) ) );
|
||||
m_index = std::make_unique< Index >( basePath / "ffxiv" / ( prefix + ".index" ) );
|
||||
|
||||
// For all dat files linked to this index, create it: XX0000.win32.datX
|
||||
for( uint32_t i = 0; i < getIndex().getDatCount(); ++i )
|
||||
{
|
||||
m_dats.emplace_back( std::make_unique< Dat >(basePath / "ffxiv" / ( prefix + ".dat" + std::to_string( i ) ), i ) );
|
||||
}
|
||||
}
|
||||
for( uint32_t i = 0; i < getIndex().getDatCount(); ++i )
|
||||
{
|
||||
m_dats.emplace_back( std::make_unique< Dat >( basePath / "ffxiv" / ( prefix + ".dat" + std::to_string( i ) ), i ) );
|
||||
}
|
||||
}
|
||||
|
||||
Cat::Cat( const std::filesystem::path& basePath, uint32_t catNum, const std::string& name, uint32_t exNum, uint32_t chunk ) :
|
||||
m_name( name ),
|
||||
m_catNum( catNum ),
|
||||
m_chunk( chunk )
|
||||
{
|
||||
// Creates the index: XX0000.win32.index
|
||||
m_index = std::make_unique< Index >( basePath / GameData::buildDatStr( "ex" + std::to_string( exNum ), catNum, exNum, chunk, "win32", "index" ) );
|
||||
Cat::Cat( const std::filesystem::path& basePath, uint32_t catNum, const std::string& name, uint32_t exNum, uint32_t chunk ) : m_name( name ),
|
||||
m_catNum( catNum ),
|
||||
m_chunk( chunk )
|
||||
{
|
||||
m_index = std::make_unique< Index >( basePath / GameData::buildDatStr( "ex" + std::to_string( exNum ), catNum, exNum, chunk, "win32", "index" ) );
|
||||
|
||||
// For all dat files linked to this index, create it: XX0000.win32.datX
|
||||
for( uint32_t i = 0; i < getIndex().getDatCount(); ++i )
|
||||
{
|
||||
m_dats.emplace_back( std::make_unique< Dat >( basePath / GameData::buildDatStr( "ex" + std::to_string( exNum ), catNum, exNum, chunk, "win32", "dat" + std::to_string( i ) ), i ) );
|
||||
}
|
||||
}
|
||||
for( uint32_t i = 0; i < getIndex().getDatCount(); ++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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
Cat::~Cat()
|
||||
{
|
||||
Cat::~Cat()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
const Index& Cat::getIndex() const
|
||||
{
|
||||
return *m_index;
|
||||
}
|
||||
|
||||
const Index& Cat::getIndex() const
|
||||
{
|
||||
return *m_index;
|
||||
}
|
||||
std::unique_ptr< File > Cat::getFile( uint32_t dir_hash, uint32_t filename_hash ) const
|
||||
{
|
||||
auto& hash_table_entry = getIndex().getHashTableEntry( dir_hash, filename_hash );
|
||||
return m_dats[ hash_table_entry.datNum ]->getFile( hash_table_entry.datOffset );
|
||||
}
|
||||
|
||||
std::unique_ptr<File> Cat::getFile(uint32_t dir_hash, uint32_t filename_hash) const
|
||||
{
|
||||
// Fetch the correct hash_table_entry for these hashes, from that request the file from the right dat file
|
||||
auto& hash_table_entry = getIndex().getHashTableEntry(dir_hash, filename_hash);
|
||||
return m_dats[hash_table_entry.datNum]->getFile(hash_table_entry.datOffset);
|
||||
}
|
||||
bool Cat::doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const
|
||||
{
|
||||
return getIndex().doesFileExist( dir_hash, filename_hash );
|
||||
}
|
||||
|
||||
bool Cat::doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const
|
||||
{
|
||||
return getIndex().doesFileExist( dir_hash, filename_hash );
|
||||
}
|
||||
bool Cat::doesDirExist( uint32_t dir_hash ) const
|
||||
{
|
||||
return getIndex().doesDirExist( dir_hash );
|
||||
}
|
||||
|
||||
bool Cat::doesDirExist( uint32_t dir_hash ) const
|
||||
{
|
||||
return getIndex().doesDirExist( dir_hash );
|
||||
}
|
||||
const std::string& Cat::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const std::string& Cat::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
uint32_t Cat::getCatNum() const
|
||||
{
|
||||
return m_catNum;
|
||||
}
|
||||
|
||||
uint32_t Cat::getCatNum() const
|
||||
{
|
||||
return m_catNum;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}// namespace dat
|
||||
}// namespace xiv
|
8
deps/datReader/DatCat.h
vendored
8
deps/datReader/DatCat.h
vendored
|
@ -1,9 +1,8 @@
|
|||
#ifndef XIV_DAT_CAT_H
|
||||
#define XIV_DAT_CAT_H
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
namespace xiv::dat
|
||||
{
|
||||
|
@ -60,9 +59,8 @@ namespace xiv::dat
|
|||
std::unique_ptr< Index > m_index;
|
||||
|
||||
// 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
|
||||
|
|
21
deps/datReader/conv.cpp
vendored
21
deps/datReader/conv.cpp
vendored
|
@ -1,4 +1,5 @@
|
|||
#include "conv.h"
|
||||
#include <cstring>// for memcpy
|
||||
|
||||
namespace xiv::utils::conv
|
||||
{
|
||||
|
@ -9,19 +10,21 @@ namespace xiv::utils::conv
|
|||
uint32_t t2;
|
||||
uint32_t t3;
|
||||
|
||||
t1 = i_value & 0x7fff; // Non-sign bits
|
||||
t2 = i_value & 0x8000; // Sign bit
|
||||
t3 = i_value & 0x7c00; // Exponent
|
||||
t1 <<= 13; // Align mantissa on MSB
|
||||
t2 <<= 16; // Shift sign bit into position
|
||||
t1 = i_value & 0x7fff; // Non-sign bits
|
||||
t2 = i_value & 0x8000; // Sign bit
|
||||
t3 = i_value & 0x7c00; // Exponent
|
||||
t1 <<= 13; // Align mantissa on MSB
|
||||
t2 <<= 16; // Shift sign bit into position
|
||||
|
||||
t1 += 0x38000000; // Adjust bias
|
||||
t1 += 0x38000000; // Adjust bias
|
||||
|
||||
t1 = ( t3 == 0 ? 0 : t1 ); // Denormals-as-zero
|
||||
t1 = ( t3 == 0 ? 0 : t1 );// Denormals-as-zero
|
||||
|
||||
t1 |= t2; // Re-insert sign bit
|
||||
t1 |= t2; // Re-insert sign bit
|
||||
|
||||
return *reinterpret_cast< float* >( &t1 );
|
||||
float result;
|
||||
memcpy( &result, &t1, sizeof( float ) );// Convert uint32_t to float using memcpy
|
||||
return result;
|
||||
}
|
||||
|
||||
float ubyte2float( const uint8_t i_value )
|
||||
|
|
138
deps/datReader/crc32.cpp
vendored
138
deps/datReader/crc32.cpp
vendored
|
@ -1,79 +1,52 @@
|
|||
#include "crc32.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
#include <zlib/zlib.h>
|
||||
|
||||
namespace internal
|
||||
{
|
||||
// Mutex to prevent two threads from concurrently trying to build the crc tables atthe same time
|
||||
std::mutex crc_creation_mutex;
|
||||
using CrcTable = std::array< uint32_t, 0x100 >;
|
||||
|
||||
typedef std::vector<uint32_t> CrcTable;
|
||||
|
||||
// Our crc/rev_crc tables
|
||||
CrcTable crc_table;
|
||||
CrcTable rev_crc_table;
|
||||
|
||||
bool crc_tables_created = false;
|
||||
|
||||
void build_crc_tables()
|
||||
constexpr CrcTable build_crc_table()
|
||||
{
|
||||
CrcTable crc_table{};
|
||||
for( size_t i = 0; i < 0x100; ++i )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(crc_creation_mutex);
|
||||
if (!crc_tables_created)
|
||||
{
|
||||
crc_table.resize(0x100);
|
||||
rev_crc_table.resize(0x100);
|
||||
for (auto i = 0; i < 0x100; ++i)
|
||||
{
|
||||
uint32_t crc = i;
|
||||
for (auto j = 0; j < 8; ++j)
|
||||
{
|
||||
if (crc & 1)
|
||||
{
|
||||
crc = 0xEDB88320 ^ (crc >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
crc = crc >> 1;
|
||||
}
|
||||
}
|
||||
crc_table[i] = crc;
|
||||
rev_crc_table[crc >> 24] = i + ((crc & 0xFFFFFF) << 8);
|
||||
}
|
||||
}
|
||||
crc_tables_created = true;
|
||||
uint32_t crc = i;
|
||||
for( size_t j = 0; j < 8; ++j )
|
||||
{
|
||||
crc = ( crc & 1 ) ? ( 0xEDB88320 ^ ( crc >> 1 ) ) : ( crc >> 1 );
|
||||
}
|
||||
crc_table[ i ] = crc;
|
||||
}
|
||||
return crc_table;
|
||||
}
|
||||
|
||||
const CrcTable& get_crc_table()
|
||||
constexpr CrcTable build_rev_crc_table()
|
||||
{
|
||||
CrcTable rev_crc_table{};
|
||||
auto crc_table = build_crc_table();
|
||||
for( size_t i = 0; i < 0x100; ++i )
|
||||
{
|
||||
if (!crc_tables_created)
|
||||
{
|
||||
build_crc_tables();
|
||||
}
|
||||
return crc_table;
|
||||
uint32_t crc = crc_table[ i ];
|
||||
rev_crc_table[ crc >> 24 ] = i + ( ( crc & 0xFFFFFF ) << 8 );
|
||||
}
|
||||
return rev_crc_table;
|
||||
}
|
||||
|
||||
const CrcTable& get_rev_crc_table()
|
||||
{
|
||||
if (!crc_tables_created)
|
||||
{
|
||||
build_crc_tables();
|
||||
}
|
||||
return rev_crc_table;
|
||||
}
|
||||
}
|
||||
constexpr CrcTable crc_table = build_crc_table();
|
||||
constexpr CrcTable rev_crc_table = build_rev_crc_table();
|
||||
}// namespace internal
|
||||
|
||||
namespace xiv::utils::crc32
|
||||
{
|
||||
|
||||
uint32_t compute( const std::string& i_input, uint32_t init_crc )
|
||||
{
|
||||
// Classical crc stuff
|
||||
auto& crc_table = internal::get_crc_table();
|
||||
auto crc = init_crc;
|
||||
for( std::size_t i = 0; i < i_input.size(); ++i )
|
||||
auto& crc_table = internal::crc_table;
|
||||
uint32_t crc = init_crc;
|
||||
for( size_t i = 0; i < i_input.size(); ++i )
|
||||
{
|
||||
crc = crc_table[ ( crc ^ i_input[ i ] ) & 0xFF ] ^ ( crc >> 8 );
|
||||
}
|
||||
|
@ -82,43 +55,38 @@ namespace xiv::utils::crc32
|
|||
|
||||
uint32_t rev_compute( const std::string& i_input, uint32_t init_crc )
|
||||
{
|
||||
auto& rev_crc_table = internal::get_rev_crc_table();
|
||||
auto crc = init_crc;
|
||||
auto& rev_crc_table = internal::rev_crc_table;
|
||||
uint32_t crc = init_crc;
|
||||
const auto input_size = i_input.size();
|
||||
// Reverse crc
|
||||
for( auto i = input_size; i > 0; --i )
|
||||
for( size_t i = input_size; i > 0; --i )
|
||||
{
|
||||
crc = rev_crc_table[ crc >> 24 ] ^ ( ( crc << 8 ) & 0xFFFFFF00 ) ^ i_input[ input_size - i - 1 ];
|
||||
}
|
||||
// Compute the 4 bytes needed for this init_crc
|
||||
for( auto i = 0; i < 4; ++i )
|
||||
for( size_t i = 0; i < 4; ++i )
|
||||
{
|
||||
crc = rev_crc_table[ crc >> 24 ] ^ ( ( crc << 8 ) & 0xFFFFFF00 );
|
||||
}
|
||||
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::array< uint32_t, 10000 >& o_hashes )
|
||||
{
|
||||
char* str = const_cast<char*>(i_format.data());
|
||||
const auto str_size = static_cast< uInt >( i_format.size() );
|
||||
|
||||
o_hashes.resize( 10000 );
|
||||
|
||||
uint32_t i = 0;
|
||||
for( char a = '0'; a <= '9'; ++a )
|
||||
{
|
||||
str[ i_first_index ] = a;
|
||||
i_format[ i_first_index ] = a;
|
||||
for( char b = '0'; b <= '9'; ++b )
|
||||
{
|
||||
str[ i_first_index + 1 ] = b;
|
||||
i_format[ i_first_index + 1 ] = b;
|
||||
for( char c = '0'; c <= '9'; ++c )
|
||||
{
|
||||
str[ i_first_index + 2 ] = c;
|
||||
i_format[ i_first_index + 2 ] = c;
|
||||
for( char d = '0'; d <= '9'; ++d )
|
||||
{
|
||||
str[ i_first_index + 3 ] = d;
|
||||
o_hashes[ i ] = ::crc32( 0, reinterpret_cast<uint8_t*>(&( str[ 0 ] )), str_size ) ^ 0xFFFFFFFF;
|
||||
i_format[ i_first_index + 3 ] = d;
|
||||
o_hashes[ i ] = ::crc32( 0, reinterpret_cast< const Bytef* >( i_format.data() ), str_size ) ^ 0xFFFFFFFF;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
@ -127,39 +95,36 @@ namespace xiv::utils::crc32
|
|||
}
|
||||
|
||||
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 )
|
||||
std::array< uint32_t, 100000000 >& o_hashes )
|
||||
{
|
||||
char* str = const_cast<char*>(i_format.data());
|
||||
const auto str_size = static_cast< uInt >( i_format.size() );
|
||||
|
||||
o_hashes.resize( 100000000 );
|
||||
|
||||
uint32_t i = 0;
|
||||
for( char a = '0'; a <= '9'; ++a )
|
||||
{
|
||||
str[ i_first_index ] = a;
|
||||
i_format[ i_first_index ] = a;
|
||||
for( char b = '0'; b <= '9'; ++b )
|
||||
{
|
||||
str[ i_first_index + 1 ] = b;
|
||||
i_format[ i_first_index + 1 ] = b;
|
||||
for( char c = '0'; c <= '9'; ++c )
|
||||
{
|
||||
str[ i_first_index + 2 ] = c;
|
||||
i_format[ i_first_index + 2 ] = c;
|
||||
for( char d = '0'; d <= '9'; ++d )
|
||||
{
|
||||
str[ i_first_index + 3 ] = d;
|
||||
i_format[ i_first_index + 3 ] = d;
|
||||
for( char e = '0'; e <= '9'; ++e )
|
||||
{
|
||||
str[ i_second_index ] = e;
|
||||
i_format[ i_second_index ] = e;
|
||||
for( char f = '0'; f <= '9'; ++f )
|
||||
{
|
||||
str[ i_second_index + 1 ] = f;
|
||||
i_format[ i_second_index + 1 ] = f;
|
||||
for( char g = '0'; g <= '9'; ++g )
|
||||
{
|
||||
str[ i_second_index + 2 ] = g;
|
||||
i_format[ i_second_index + 2 ] = g;
|
||||
for( char h = '0'; h <= '9'; ++h )
|
||||
{
|
||||
str[ i_second_index + 3 ] = h;
|
||||
o_hashes[ i ] = ::crc32( 0, reinterpret_cast<uint8_t*>(&( str[ 0 ] )), str_size ) ^ 0xFFFFFFFF;
|
||||
i_format[ i_second_index + 3 ] = h;
|
||||
o_hashes[ i ] = ::crc32( 0, reinterpret_cast< const Bytef* >( i_format.data() ), str_size ) ^ 0xFFFFFFFF;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
@ -171,5 +136,4 @@ namespace xiv::utils::crc32
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}// namespace xiv::utils::crc32
|
12
deps/datReader/zlib.cpp
vendored
12
deps/datReader/zlib.cpp
vendored
|
@ -1,8 +1,8 @@
|
|||
#include "zlib.h"
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <zlib/zlib.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <zlib/zlib.h>
|
||||
|
||||
namespace xiv::utils::zlib
|
||||
{
|
||||
|
@ -18,13 +18,13 @@ namespace xiv::utils::zlib
|
|||
|
||||
if( ret != Z_OK )
|
||||
{
|
||||
throw std::runtime_error( "Error at zlib uncompress: " + std::to_string( ret ) );
|
||||
throw std::runtime_error( "Error at zlib compress: " + std::to_string( ret ) );
|
||||
}
|
||||
|
||||
out.resize( out_size );
|
||||
}
|
||||
|
||||
void no_header_decompress( uint8_t* in, size_t in_size, uint8_t* out, size_t out_size )
|
||||
void no_header_decompress( const uint8_t* in, size_t in_size, uint8_t* out, size_t out_size )
|
||||
{
|
||||
z_stream strm;
|
||||
strm.zalloc = Z_NULL;
|
||||
|
@ -41,7 +41,7 @@ namespace xiv::utils::zlib
|
|||
}
|
||||
|
||||
// Set pointers to the right addresses
|
||||
strm.next_in = in;
|
||||
strm.next_in = const_cast< uint8_t* >( in );
|
||||
strm.avail_out = static_cast< uInt >( out_size );
|
||||
strm.next_out = out;
|
||||
|
||||
|
@ -56,4 +56,4 @@ namespace xiv::utils::zlib
|
|||
inflateEnd( &strm );
|
||||
}
|
||||
|
||||
}
|
||||
}// namespace xiv::utils::zlib
|
2
deps/datReader/zlib.h
vendored
2
deps/datReader/zlib.h
vendored
|
@ -10,7 +10,7 @@ namespace xiv::utils::zlib
|
|||
|
||||
void compress( const std::vector< char >& in, std::vector< char >& out );
|
||||
|
||||
void no_header_decompress( uint8_t* in, size_t in_size, uint8_t* out, size_t out_size );
|
||||
void no_header_decompress( const uint8_t* in, size_t in_size, uint8_t* out, size_t out_size );
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,162 +1,117 @@
|
|||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#if !_WIN32
|
||||
# include <cxxabi.h>
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
#include <datReader/GameData.h>
|
||||
#include <File.h>
|
||||
#include <ExdData.h>
|
||||
#include <ExdCat.h>
|
||||
#include <Exd.h>
|
||||
|
||||
#include <ExdCat.h>
|
||||
#include <ExdData.h>
|
||||
#include <File.h>
|
||||
#include <Logging/Logger.h>
|
||||
#include <datReader/GameData.h>
|
||||
|
||||
namespace Sapphire::Data
|
||||
{
|
||||
|
||||
class ExdData
|
||||
{
|
||||
public:
|
||||
bool init( const std::string& path );
|
||||
|
||||
template< typename T >
|
||||
std::shared_ptr< Excel::ExcelStruct< T > > getRow( uint32_t row, uint32_t subrow = 0 )
|
||||
{
|
||||
xiv::exd::Exd sheet;
|
||||
auto needle = m_sheets.find( typeid( T ) );
|
||||
if( needle == m_sheets.end() )
|
||||
{
|
||||
auto sheetName = getSheetName< T >();
|
||||
|
||||
// load sheet
|
||||
auto& cat = m_exd_data->get_category( sheetName );
|
||||
m_sheets[ typeid( T ) ] = sheet = static_cast< xiv::exd::Exd >( cat.get_data( xiv::exd::Language::en ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sheet = needle->second;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return sheet.get_row< T >( row );
|
||||
}
|
||||
catch( const std::runtime_error& ex )
|
||||
{
|
||||
Logger::error( "Error fetching row from sheet {}: {}", getSheetName< T >(), ex.what() );
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
catch( const std::out_of_range& )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
std::shared_ptr< Excel::ExcelStruct< T > > getRow( uint32_t row, uint32_t subrow = 0 );
|
||||
|
||||
template< typename T >
|
||||
std::vector< uint32_t > getIdList()
|
||||
{
|
||||
xiv::exd::Exd sheet;
|
||||
auto needle = m_sheets.find( typeid( T ) );
|
||||
if( needle == m_sheets.end() )
|
||||
{
|
||||
auto sheetName = getSheetName< T >();
|
||||
|
||||
// load sheet
|
||||
auto& cat = m_exd_data->get_category( sheetName );
|
||||
m_sheets[ typeid( T ) ] = sheet = static_cast< xiv::exd::Exd >( cat.get_data( xiv::exd::Language::en ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sheet = needle->second;
|
||||
}
|
||||
|
||||
auto rows = sheet.get_rows();
|
||||
std::vector< uint32_t > ids;
|
||||
|
||||
for( const auto& row : rows )
|
||||
{
|
||||
ids.push_back( row.first );
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
std::vector< uint32_t > getIdList();
|
||||
|
||||
template< typename T >
|
||||
std::unordered_map< uint32_t, std::shared_ptr< Excel::ExcelStruct< T > > > getRows()
|
||||
{
|
||||
xiv::exd::Exd sheet;
|
||||
auto needle = m_sheets.find( typeid( T ) );
|
||||
if( needle == m_sheets.end() )
|
||||
{
|
||||
auto sheetName = getSheetName< T >();
|
||||
std::unordered_map< uint32_t, std::shared_ptr< Excel::ExcelStruct< T > > > getRows();
|
||||
|
||||
// load sheet
|
||||
auto& cat = m_exd_data->get_category( sheetName );
|
||||
m_sheets[ typeid( T ) ] = sheet = static_cast< xiv::exd::Exd >( cat.get_data( xiv::exd::Language::en ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sheet = needle->second;
|
||||
}
|
||||
|
||||
return sheet.get_sheet_rows< T >();
|
||||
}
|
||||
|
||||
std::shared_ptr< xiv::dat::GameData > getGameData()
|
||||
std::shared_ptr< xiv::dat::GameData > ExdData::getGameData()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
private:
|
||||
template< typename T >
|
||||
std::string getSheetName()
|
||||
{
|
||||
auto origName = std::string( typeid( T ).name() );
|
||||
#if _WIN32
|
||||
auto pos = origName.find_last_of(':');
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
return origName.substr(pos + 1);
|
||||
}
|
||||
std::string getSheetName();
|
||||
|
||||
return "[something fucking died]";
|
||||
#else
|
||||
|
||||
int status = -4;
|
||||
|
||||
auto res = abi::__cxa_demangle( origName.c_str(), NULL, NULL, &status );
|
||||
|
||||
auto name = ( status == 0 ) ? res : origName;
|
||||
|
||||
std::string demangledName( name );
|
||||
|
||||
auto pos = demangledName.find_last_of( ':' );
|
||||
if( pos != std::string::npos )
|
||||
{
|
||||
demangledName = demangledName.substr( pos + 1 );
|
||||
}
|
||||
|
||||
free( res );
|
||||
|
||||
return demangledName;
|
||||
#endif
|
||||
}
|
||||
template< typename T >
|
||||
xiv::exd::Exd& getSheet();
|
||||
|
||||
std::unordered_map< std::type_index, xiv::exd::Exd > m_sheets;
|
||||
|
||||
std::shared_ptr< xiv::dat::GameData > m_data;
|
||||
std::shared_ptr< xiv::exd::ExdData > m_exd_data;
|
||||
};
|
||||
|
||||
}
|
||||
template< typename T >
|
||||
std::string ExdData::getSheetName()
|
||||
{
|
||||
auto origName = std::string( typeid( T ).name() );
|
||||
#if _WIN32
|
||||
auto pos = origName.find_last_of( ':' );
|
||||
return pos != std::string::npos ? origName.substr( pos + 1 ) : "[something_fucking_died]";
|
||||
#else
|
||||
int status = -4;
|
||||
char* res = abi::__cxa_demangle( origName.c_str(), nullptr, nullptr, &status );
|
||||
std::string demangledName = ( status == 0 ) ? res : origName;
|
||||
auto pos = demangledName.find_last_of( ':' );
|
||||
if( pos != std::string::npos ) demangledName = demangledName.substr( pos + 1 );
|
||||
free( res );
|
||||
return demangledName;
|
||||
#endif
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
xiv::exd::Exd& ExdData::getSheet()
|
||||
{
|
||||
auto needle = m_sheets.find( typeid( T ) );
|
||||
if( needle == m_sheets.end() )
|
||||
{
|
||||
auto sheetName = getSheetName< T >();
|
||||
auto& cat = m_exd_data->get_category( sheetName );
|
||||
needle = m_sheets.emplace( typeid( T ), static_cast< xiv::exd::Exd >( cat.get_data( xiv::exd::Language::en ) ) ).first;
|
||||
}
|
||||
return needle->second;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
std::shared_ptr< Excel::ExcelStruct< T > > ExdData::getRow( uint32_t row, uint32_t subrow )
|
||||
{
|
||||
try
|
||||
{
|
||||
return getSheet< T >().get_row< T >( row );
|
||||
} catch( const std::runtime_error& ex )
|
||||
{
|
||||
Logger::error( "Error fetching row from sheet {}: {}", getSheetName< T >(), ex.what() );
|
||||
return nullptr;
|
||||
} catch( const std::out_of_range& )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
std::vector< uint32_t > ExdData::getIdList()
|
||||
{
|
||||
auto sheet = getSheet< T >();
|
||||
auto rows = sheet.get_rows();
|
||||
std::vector< uint32_t > ids;
|
||||
for( const auto& row : rows ) ids.push_back( row.first );
|
||||
return ids;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
std::unordered_map< uint32_t, std::shared_ptr< Excel::ExcelStruct< T > > > ExdData::getRows()
|
||||
{
|
||||
return getSheet< T >().get_sheet_rows< T >();
|
||||
}
|
||||
|
||||
}// namespace Sapphire::Data
|
|
@ -4,12 +4,6 @@
|
|||
#include <datReader/DatCategories/bg/pcb.h>
|
||||
#include <datReader/DatCategories/bg/lgb.h>
|
||||
#include <datReader/DatCategories/bg/sgb.h>
|
||||
#include <GameData.h>
|
||||
#include <File.h>
|
||||
#include <DatCat.h>
|
||||
#include <ExdData.h>
|
||||
#include <ExdCat.h>
|
||||
#include <Exd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <execution>
|
||||
|
@ -23,12 +17,8 @@ Sapphire::InstanceObjectCache::InstanceObjectCache()
|
|||
auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref();
|
||||
auto teriList = exdData.getRows< Excel::TerritoryType >();
|
||||
|
||||
size_t count = 0;
|
||||
for( const auto& [ id, territoryType ] : teriList ) {
|
||||
// show some loading indication...
|
||||
if( count++ % 10 == 0 )
|
||||
std::cout << ".";
|
||||
|
||||
for( const auto& [ id, territoryType ] : teriList )
|
||||
{
|
||||
auto path = territoryType->getString( territoryType->data().LVB );
|
||||
|
||||
if( path.empty() )
|
||||
|
@ -36,16 +26,6 @@ Sapphire::InstanceObjectCache::InstanceObjectCache()
|
|||
|
||||
path = std::string( "bg/" ) + path.substr( 0, path.find( "/level/" ) );
|
||||
|
||||
// TODO: it does feel like this needs to be streamlined into the datReader instead of being done here...
|
||||
std::string bgLgbPath( path + "/level/bg.lgb" );
|
||||
std::string planmapLgbPath( path + "/level/planmap.lgb" );
|
||||
std::string planeventLgbPath( path + "/level/planevent.lgb" );
|
||||
std::string plannerLgbPath( path + "/level/planner.lgb" );
|
||||
std::vector< char > bgSection;
|
||||
std::vector< char > planmapSection;
|
||||
std::vector< char > planeventSection;
|
||||
std::vector< char > plannerSection;
|
||||
|
||||
std::unique_ptr< xiv::dat::File > bgFile;
|
||||
std::unique_ptr< xiv::dat::File > planmap_file;
|
||||
std::unique_ptr< xiv::dat::File > planevent_file;
|
||||
|
@ -53,46 +33,39 @@ Sapphire::InstanceObjectCache::InstanceObjectCache()
|
|||
|
||||
try
|
||||
{
|
||||
if( exdData.getGameData()->doesFileExist( bgLgbPath ) )
|
||||
bgFile = exdData.getGameData()->getFile( bgLgbPath );
|
||||
if( exdData.getGameData()->doesFileExist( path + "/level/bg.lgb" ) )
|
||||
bgFile = loadFile( path + "/level/bg.lgb" );
|
||||
else
|
||||
continue;
|
||||
|
||||
planmap_file = exdData.getGameData()->getFile( planmapLgbPath );
|
||||
planevent_file = exdData.getGameData()->getFile( planeventLgbPath );
|
||||
}
|
||||
catch( std::runtime_error& )
|
||||
planmap_file = loadFile( path + "/level/planmap.lgb" );
|
||||
planevent_file = loadFile( path + "/level/planevent.lgb" );
|
||||
} catch( std::runtime_error& )
|
||||
{
|
||||
// ignore files that aren't found
|
||||
continue;
|
||||
}
|
||||
|
||||
bgSection = bgFile->access_data_sections().at( 0 );
|
||||
planmapSection = planmap_file->access_data_sections().at( 0 );
|
||||
planeventSection = planevent_file->access_data_sections().at( 0 );
|
||||
std::vector< char > bgSection( bgFile->access_data_sections().at( 0 ) );
|
||||
std::vector< char > planmapSection( planmap_file->access_data_sections().at( 0 ) );
|
||||
std::vector< char > planeventSection( planevent_file->access_data_sections().at( 0 ) );
|
||||
|
||||
std::vector< std::string > stringList;
|
||||
|
||||
uint32_t offset1 = 0x20;
|
||||
|
||||
LGB_FILE bgLgb( &bgSection[ 0 ], "bg" );
|
||||
LGB_FILE planmapLgb( &planmapSection[ 0 ], "planmap" );
|
||||
LGB_FILE planeventLgb( &planeventSection[ 0 ], "planevent" );
|
||||
|
||||
uint32_t max_index = 0;
|
||||
LGB_FILE bgLgb( bgSection.data(), "bg" );
|
||||
LGB_FILE planmapLgb( planmapSection.data(), "planmap" );
|
||||
LGB_FILE planeventLgb( planeventSection.data(), "planevent" );
|
||||
|
||||
std::vector< LGB_FILE > lgbList;
|
||||
|
||||
try
|
||||
{
|
||||
planner_file = exdData.getGameData()->getFile( plannerLgbPath );
|
||||
plannerSection = planner_file->access_data_sections().at( 0 );
|
||||
LGB_FILE plannerLgb( &plannerSection[ 0 ], "planner" );
|
||||
planner_file = loadFile( path + "/level/planner.lgb" );
|
||||
std::vector< char > plannerSection( planner_file->access_data_sections().at( 0 ) );
|
||||
LGB_FILE plannerLgb( plannerSection.data(), "planner" );
|
||||
|
||||
lgbList.reserve( 4 );
|
||||
lgbList = { bgLgb, planmapLgb, planeventLgb, plannerLgb };
|
||||
}
|
||||
catch( std::runtime_error& )
|
||||
} catch( std::runtime_error& )
|
||||
{
|
||||
lgbList.reserve( 3 );
|
||||
lgbList = { bgLgb, planmapLgb, planeventLgb };
|
||||
}
|
||||
|
||||
|
@ -126,9 +99,6 @@ Sapphire::InstanceObjectCache::InstanceObjectCache()
|
|||
}
|
||||
case LgbEntryType::CollisionBox:
|
||||
{
|
||||
//auto pEObj = std::reinterpret_pointer_cast< LGB_ENPC_ENTRY >( pEntry );
|
||||
|
||||
//Logger::debug( "CollisionBox {}", pEntry->header.nameOffset );
|
||||
break;
|
||||
}
|
||||
case LgbEntryType::EventObject:
|
||||
|
@ -155,14 +125,20 @@ Sapphire::InstanceObjectCache::InstanceObjectCache()
|
|||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
Logger::debug(
|
||||
"InstanceObjectCache Cached: MapRange: {} ExitRange: {} PopRange: {} EventObj: {} EventNpc: {} EventRange: {}",
|
||||
m_mapRangeCache.size(), m_exitRangeCache.size(), m_popRangeCache.size(), m_eobjCache.size(), m_enpcCache.size(), m_eventRangeCache.size()
|
||||
);
|
||||
"InstanceObjectCache Cached: MapRange: {} ExitRange: {} PopRange: {} EventObj: {} EventNpc: {} EventRange: {}",
|
||||
m_mapRangeCache.size(), m_exitRangeCache.size(), m_popRangeCache.size(), m_eobjCache.size(), m_enpcCache.size(),
|
||||
m_eventRangeCache.size() );
|
||||
}
|
||||
|
||||
std::unique_ptr< xiv::dat::File > Sapphire::InstanceObjectCache::loadFile( const std::string& filePath ) const
|
||||
{
|
||||
auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref();
|
||||
if( exdData.getGameData()->doesFileExist( filePath ) )
|
||||
return exdData.getGameData()->getFile( filePath );
|
||||
|
||||
throw std::runtime_error( "File not found: " + filePath );
|
||||
}
|
||||
|
||||
Sapphire::InstanceObjectCache::MapRangePtr
|
||||
Sapphire::InstanceObjectCache::getMapRange( uint16_t zoneId, uint32_t mapRangeId )
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
#include <unordered_map>
|
||||
#include <Common.h>
|
||||
|
||||
#include <GameData.h>
|
||||
#include <File.h>
|
||||
#include <DatCat.h>
|
||||
#include <ExdData.h>
|
||||
#include <ExdCat.h>
|
||||
#include <Exd.h>
|
||||
|
||||
struct LGB_MAP_RANGE_ENTRY;
|
||||
struct LGB_EXIT_RANGE_ENTRY;
|
||||
struct LGB_POP_RANGE_ENTRY;
|
||||
|
@ -99,13 +106,14 @@ namespace Sapphire
|
|||
InstanceObjectCache();
|
||||
~InstanceObjectCache() = default;
|
||||
|
||||
std::unique_ptr< xiv::dat::File > loadFile( const std::string& filePath ) const;
|
||||
|
||||
MapRangePtr getMapRange( uint16_t zoneId, uint32_t mapRangeId );
|
||||
ExitRangePtr getExitRange( uint16_t zoneId, uint32_t exitRangeId );
|
||||
PopRangePtr getPopRange( uint32_t popRangeId );
|
||||
|
||||
std::shared_ptr< PopRangeInfo > getPopRangeInfo( uint32_t popRangeId );
|
||||
|
||||
|
||||
EObjPtr getEObj( uint32_t eObjId );
|
||||
ENpcPtr getENpc( uint32_t eNpcId );
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue