From 01ba6ad8586658b5eacef2efbf11423ada8b79b0 Mon Sep 17 00:00:00 2001 From: Tahir Akhlaq Date: Sun, 4 Feb 2018 20:09:55 +0000 Subject: [PATCH] added option to dump all level.exd entries for all instances in pcb_reader --- src/tools/pcb_reader/lgb.h | 36 ++++++++++------ src/tools/pcb_reader/main.cpp | 80 +++++++++++++++++++++++++++-------- 2 files changed, 85 insertions(+), 31 deletions(-) diff --git a/src/tools/pcb_reader/lgb.h b/src/tools/pcb_reader/lgb.h index 94fbfa20..e29d517c 100644 --- a/src/tools/pcb_reader/lgb.h +++ b/src/tools/pcb_reader/lgb.h @@ -70,23 +70,26 @@ struct LGB_ENTRY_HEADER vec3 scale; }; -class LGB_MODEL_ENTRY +class LGB_ENTRY { public: char* m_buf; uint32_t m_offset; + LGB_ENTRY_HEADER header; - LGB_MODEL_ENTRY() + LGB_ENTRY() { m_buf = nullptr; m_offset = 0; + memset( &header, 0, sizeof( header ) ); }; - LGB_MODEL_ENTRY( char* buf, uint32_t offset ) + LGB_ENTRY( char* buf, uint32_t offset ) { m_buf = buf; m_offset = offset; + header = *reinterpret_cast< LGB_ENTRY_HEADER* >( buf + offset ); }; - virtual ~LGB_MODEL_ENTRY() {}; + virtual ~LGB_ENTRY() {}; }; @@ -102,7 +105,7 @@ struct LGB_BGPARTS_HEADER : public LGB_ENTRY_HEADER uint32_t unknown9; }; -class LGB_BGPARTS_ENTRY : public LGB_MODEL_ENTRY +class LGB_BGPARTS_ENTRY : public LGB_ENTRY { public: LGB_BGPARTS_HEADER header; @@ -110,7 +113,7 @@ public: std::string modelFileName; std::string collisionFileName; LGB_BGPARTS_ENTRY() {}; - LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) + LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) : LGB_ENTRY( buf, offset ) { header = *reinterpret_cast( buf + offset ); name = std::string( buf + offset + header.nameOffset ); @@ -125,14 +128,14 @@ struct LGB_GIMMICK_HEADER : public LGB_ENTRY_HEADER char unknownBytes[100]; }; -class LGB_GIMMICK_ENTRY : public LGB_MODEL_ENTRY +class LGB_GIMMICK_ENTRY : public LGB_ENTRY { public: LGB_GIMMICK_HEADER header; std::string name; std::string gimmickFileName; - LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) + LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) : LGB_ENTRY( buf, offset ) { header = *reinterpret_cast( buf + offset ); name = std::string( buf + offset + header.nameOffset ); @@ -147,13 +150,13 @@ struct LGB_ENPC_HEADER : public LGB_ENTRY_HEADER uint8_t unknown1[0x24]; }; -class LGB_ENPC_ENTRY : public LGB_MODEL_ENTRY +class LGB_ENPC_ENTRY : public LGB_ENTRY { public: LGB_ENPC_HEADER header; std::string name; - LGB_ENPC_ENTRY( char* buf, uint32_t offset ) + LGB_ENPC_ENTRY( char* buf, uint32_t offset ) : LGB_ENTRY( buf, offset ) { header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset ); name = std::string( buf + offset + header.nameOffset ); @@ -167,13 +170,13 @@ struct LGB_EOBJ_HEADER : public LGB_ENTRY_HEADER uint8_t unknown1[0x10]; }; -class LGB_EOBJ_ENTRY : public LGB_MODEL_ENTRY +class LGB_EOBJ_ENTRY : public LGB_ENTRY { public: LGB_EOBJ_HEADER header; std::string name; - LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) + 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"; @@ -203,7 +206,7 @@ struct LGB_GROUP LGB_FILE* parent; LGB_GROUP_HEADER header; std::string name; - std::vector< std::shared_ptr< LGB_MODEL_ENTRY > > entries; + std::vector< std::shared_ptr< LGB_ENTRY > > entries; LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset ) { @@ -236,12 +239,17 @@ struct LGB_GROUP { entries.push_back( std::make_shared< LGB_EOBJ_ENTRY >( buf, entryOffset ) ); } + else if( type == LgbEntryType::MapRange ) + { + entries.push_back( std::make_shared< LGB_EOBJ_ENTRY >( buf, entryOffset ) ); + } /* else { - //entries[i] = nullptr; + entries[i] = nullptr; } */ + } catch( std::exception& e ) { diff --git a/src/tools/pcb_reader/main.cpp b/src/tools/pcb_reader/main.cpp index 2a5d5c61..fb9b5326 100644 --- a/src/tools/pcb_reader/main.cpp +++ b/src/tools/pcb_reader/main.cpp @@ -23,6 +23,8 @@ std::string gamePath("C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv"); std::unordered_map< uint32_t, std::string > eobjNameMap; +std::unordered_map< uint16_t, std::string > zoneNameMap; + xiv::dat::GameData* data1 = nullptr; xiv::exd::ExdData* eData = nullptr; @@ -103,8 +105,8 @@ int parseBlockEntry( char* data, std::vector& entries, int gOff void dumpLevelExdEntries( uint32_t zoneId, const std::string& name = std::string() ) { - auto& cat = eData->get_category( "Level" ); - auto exd = static_cast< xiv::exd::Exd >( cat.get_data_ln( xiv::exd::Language::none ) ); + static auto& cat = eData->get_category( "Level" ); + static auto exd = static_cast< xiv::exd::Exd >( cat.get_data_ln( xiv::exd::Language::none ) ); std::string fileName( name + "_" + std::to_string( zoneId ) + "_Level" + ".csv" ); std::ofstream outfile( fileName, std::ios::trunc ); @@ -113,8 +115,8 @@ void dumpLevelExdEntries( uint32_t zoneId, const std::string& name = std::string { outfile.close(); outfile.open( fileName, std::ios::app ); - - for( auto& row : exd.get_rows() ) + static auto rows = exd.get_rows(); + for( auto& row : rows ) { auto id = row.first; auto& fields = row.second; @@ -144,6 +146,8 @@ std::string zoneNameToPath( const std::string& name ) { std::string path; uint32_t id; + bool found = false; + #ifdef STANDALONE auto inFile = std::ifstream( "territorytype.exh.csv" ); if( inFile.good() ) @@ -153,22 +157,22 @@ std::string zoneNameToPath( const std::string& name ) while( std::getline( inFile, line ) ) { std::smatch match; - if( std::regex_match( line, match, re ) ) + if( std::regex_match( line, match, re ) { - if( name == match[2].str() ) + if( !found && name == match[2].str() ) { id = match[1].str(); path = match[3].str(); - break; + found = true; } + zoneNameMap[std::stoul( match[1].str() )] = match[2].str(); } } inFile.close(); } #else - xiv::dat::GameData dat( gamePath ); - xiv::exd::ExdData eData( dat ); - auto& cat = eData.get_category( "TerritoryType" ); + + auto& cat = eData->get_category( "TerritoryType" ); auto exd = static_cast< xiv::exd::Exd >( cat.get_data_ln( xiv::exd::Language::none ) ); for( auto& row : exd.get_rows() ) { @@ -177,16 +181,17 @@ std::string zoneNameToPath( const std::string& name ) if( teriName.empty() ) continue; auto teriPath = *boost::get< std::string >( &fields.at( static_cast< size_t >( TerritoryTypeExdIndexes::Path ) ) ); - id = row.first; - if( boost::iequals( name, teriName ) ) + if( !found && boost::iequals( name, teriName ) ) { path = teriPath; - break; + found = true; + id = row.first; } + zoneNameMap[row.first] = teriName; } #endif - if( !path.empty() ) + if( found ) { //path = path.substr( path.find_first_of( "/" ) + 1, path.size() - path.find_first_of( "/" )); //path = std::string( "ffxiv/" ) + path; @@ -217,13 +222,43 @@ void loadEobjNames() void writeEobjEntry( std::ofstream& out, LGB_EOBJ_ENTRY* pEobj, const std::string& name ) { + static std::string mapRangeStr( "\"MapRange\", " ); + static std::string eobjStr( "\"EObj\", " ); + std::string outStr( - std::to_string( pEobj->header.eobjId ) + ", \"" + name + "\", " + + std::to_string( pEobj->header.eobjId ) + ", \"" + name + "\", " + std::string( pEobj->header.type == LgbEntryType::MapRange ? mapRangeStr : eobjStr ) + std::to_string( pEobj->header.translation.x ) + ", " + std::to_string( pEobj->header.translation.y ) + ", " + std::to_string( pEobj->header.translation.z ) + "\n" ); out.write( outStr.c_str(), outStr.size() ); } +void dumpAllInstanceContentEntries() +{ + + auto& catInstance = eData->get_category( "InstanceContent" ); + auto exdInstance = static_cast< xiv::exd::Exd >( catInstance.get_data_ln( xiv::exd::Language::en ) ); + + if( zoneNameMap.size() == 0 ) + { + zoneNameToPath( "f1d1" ); + } + + for( auto& row : exdInstance.get_rows() ) + { + auto id = row.first; + auto& fields = row.second; + + auto name = *boost::get< std::string >( &fields.at( 3 ) ); + if( name.empty() ) + continue; + auto teri = *boost::get< uint32_t >( &fields.at( 7 ) ); + auto i = 0; + while( ( i = name.find( ' ' ) ) != std::string::npos ) + name = name.replace( name.begin() + i, name.begin() + i + 1, { '_' } ); + dumpLevelExdEntries( teri, name ); + } +} + void readFileToBuffer( const std::string& path, std::vector< char >& buf ) { auto inFile = std::ifstream( path, std::ios::binary ); @@ -286,13 +321,15 @@ int main( int argc, char* argv[] ) readFileToBuffer( listPcbPath, section1 ); } #endif + if( argc > 3 && argv[3] == "--instanceDump" ) + dumpAllInstanceContentEntries(); std::vector< std::string > stringList; uint32_t offset1 = 0x20; loadEobjNames(); - std::string eobjFileName( zoneName + "eobj.csv" ); + std::string eobjFileName( zoneName + "_eobj.csv" ); std::ofstream eobjOut( eobjFileName, std::ios::trunc ); if( !eobjOut.good() ) throw std::string( "Unable to create " + zoneName + "_eobj.csv for eobj entries. Run as admin or check there isnt already a handle on the file." ).c_str(); @@ -300,6 +337,9 @@ int main( int argc, char* argv[] ) eobjOut.close(); eobjOut.open( eobjFileName, std::ios::app ); + if( !eobjOut.good() ) + throw std::string( "Unable to create " + zoneName + "_eobj.csv for eobj entries. Run as admin or check there isnt already a handle on the file." ).c_str(); + for( ; ; ) { @@ -351,7 +391,7 @@ int main( int argc, char* argv[] ) { if( fileName.find( '.' ) == std::string::npos ) return false; - else if( fileName.substr(fileName.find_last_of('.')) != ".pcb" ) + else if( fileName.substr( fileName.find_last_of( '.' ) ) != ".pcb" ) throw std::runtime_error( "Not a PCB file." ); char* dataSection = nullptr; @@ -591,6 +631,12 @@ int main( int argc, char* argv[] ) } } + if( pEntry->header.type == LgbEntryType::EventObject || pEntry->header.type == LgbEntryType::EventNpc || + pEntry->header.type == LgbEntryType::MapRange ) + { + std::cout << "HEADER SHIT " << std::to_string( ( int )pEntry->header.type ) << "\n"; + } + if( pEventObj ) { fileName = pEventObj->name.empty() ? eobjNameMap[pEventObj->header.eobjId] : pEventObj->name;