diff --git a/src/tools/event_object_parser/main.cpp b/src/tools/event_object_parser/main.cpp index e8d353fd..155587e2 100644 --- a/src/tools/event_object_parser/main.cpp +++ b/src/tools/event_object_parser/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "pcb.h" #include "lgb.h" @@ -27,15 +28,11 @@ #include - -#include - Sapphire::Common::Util::CrashHandler crashHandler; - Sapphire::Data::ExdDataGenerated g_exdData; using namespace Sapphire; - +using namespace std::chrono_literals; namespace fs = std::experimental::filesystem; // garbage to ignore models @@ -43,8 +40,6 @@ bool ignoreModels = false; std::string gamePath( "/home/mordred/sqpack" ); //std::string gamePath( "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack" ); std::unordered_map< uint32_t, std::string > eobjNameMap; -std::unordered_map< uint16_t, std::vector< std::pair< uint16_t, std::string > > > zoneInstanceMap; -uint32_t zoneId; struct instanceContent { @@ -55,79 +50,17 @@ struct instanceContent }; std::vector< instanceContent > contentList; - -std::set< std::string > zoneDumpList; - xiv::dat::GameData* data1 = nullptr; -using namespace std::chrono_literals; - void initExd( const std::string& gamePath ) { data1 = data1 ? data1 : new xiv::dat::GameData( gamePath ); } -int parseBlockEntry( char* data, std::vector< PCB_BLOCK_ENTRY >& entries, int gOff ) -{ - int offset = 0; - bool isgroup = true; - while( isgroup ) - { - PCB_BLOCK_ENTRY block_entry; - memcpy( &block_entry.header, data + offset, sizeof( block_entry.header ) ); - isgroup = block_entry.header.type == 0x30; - - //printf( " BLOCKHEADER_%X: type: %i, group_size: %i\n", gOff + offset, block_entry.header.type, block_entry.header.group_size ); - - if( isgroup ) - { - parseBlockEntry( data + offset + 0x30, entries, gOff + offset ); - offset += block_entry.header.group_size; - } - else - { - /* printf( "\tnum_v16: %i, num_indices: %i, num_vertices: %i\n\n", - block_entry.header.num_v16, block_entry.header.num_indices, block_entry.header.num_vertices );*/ - int doffset = sizeof( block_entry.header ) + offset; - uint16_t block_size = sizeof( block_entry.header ) + - block_entry.header.num_vertices * 3 * 4 + - block_entry.header.num_v16 * 6 + - block_entry.header.num_indices * 6; - - if( block_entry.header.num_vertices != 0 ) - { - block_entry.data.vertices.resize( block_entry.header.num_vertices ); - - int32_t size_vertexbuffer = block_entry.header.num_vertices * 3; - memcpy( &block_entry.data.vertices[ 0 ], data + doffset, size_vertexbuffer * 4 ); - doffset += size_vertexbuffer * 4; - } - if( block_entry.header.num_v16 != 0 ) - { - block_entry.data.vertices_i16.resize( block_entry.header.num_v16 ); - int32_t size_unknownbuffer = block_entry.header.num_v16 * 6; - memcpy( &block_entry.data.vertices_i16[ 0 ], data + doffset, size_unknownbuffer ); - doffset += block_entry.header.num_v16 * 6; - } - if( block_entry.header.num_indices != 0 ) - { - block_entry.data.indices.resize( block_entry.header.num_indices ); - int32_t size_indexbuffer = block_entry.header.num_indices * 12; - memcpy( &block_entry.data.indices[ 0 ], data + doffset, size_indexbuffer ); - doffset += size_indexbuffer; - } - entries.push_back( block_entry ); - } - } - - return 0; -} - std::unordered_map< std::string, std::string > g_nameMap; std::string zoneNameToPath( const std::string& name ) { std::string path; - bool found = false; auto it = g_nameMap.find( Sapphire::Util::toLowerCopy( name ) ); if( it != g_nameMap.end() ) @@ -149,12 +82,11 @@ std::string zoneNameToPath( const std::string& name ) if( Sapphire::Util::toLowerCopy( name ) == Sapphire::Util::toLowerCopy( teriName ) ) { path = teriPath; - found = true; break; } } - if( found ) + if( !path.empty() ) { path = std::string( "bg/" ) + path.substr( 0, path.find( "/level/" ) ); Logger::debug( "Found path for {0}: {1}", name, path ); @@ -182,44 +114,6 @@ void loadEobjNames() } } -void writeEobjEntry( std::ofstream& out, LGB_ENTRY* pObj ) -{ - static std::string mapRangeStr( "\"MapRange\", " ); - static std::string eobjStr( "\"EObj\", " ); - - uint32_t id; - uint32_t unknown = 0, unknown2 = 0; - std::string name; - std::string typeStr; - uint32_t eobjlevelHierachyId = 0; - - if( pObj->getType() == LgbEntryType::EventObject ) - { - auto pEobj = reinterpret_cast< LGB_EOBJ_ENTRY* >( pObj ); - id = pEobj->header.eobjId; - unknown = pEobj->header.unknown; - name = eobjNameMap[ id ]; - typeStr = eobjStr; - eobjlevelHierachyId = pEobj->header.levelHierachyId; - } - else if( pObj->getType() == LgbEntryType::MapRange ) - { - auto pMapRange = reinterpret_cast< LGB_MAPRANGE_ENTRY* >( pObj ); - id = pMapRange->header.unknown; - unknown = pMapRange->header.unknown2; - unknown2 = pMapRange->header.unknown3; - typeStr = mapRangeStr; - } - - std::string outStr( - std::to_string( id ) + ", " + typeStr + "\"" + name + "\", " + - std::to_string( pObj->header.translation.x ) + ", " + std::to_string( pObj->header.translation.y ) + ", " + - std::to_string( pObj->header.translation.z ) + - ", " + std::to_string( eobjlevelHierachyId ) + "\n" - ); - out.write( outStr.c_str(), outStr.size() ); -} - void loadAllInstanceContentEntries() { auto cfcIdList = g_exdData.getContentFinderConditionIdList(); @@ -266,8 +160,6 @@ void loadAllInstanceContentEntries() while( ( i = name.find( ' ' ) ) != std::string::npos ) name = name.replace( name.begin() + i, name.begin() + i + 1, { '_' } ); - zoneDumpList.emplace( tt->name ); - std::string remove = ",★_ '()[]-\xae\x1a\x1\x2\x1f\x1\x3.:"; Sapphire::Util::eraseAllIn( name, remove ); name[ 0 ] = toupper( name[ 0 ] ); @@ -331,7 +223,7 @@ int main( int argc, char* argv[] ) } catch( std::runtime_error error ) { - std::cout << error.what(); + Logger::error( error.what() ); } loadAllInstanceContentEntries(); @@ -351,171 +243,120 @@ int main( int argc, char* argv[] ) std::string planmapLgbPath( zonePath + "/level/planmap.lgb" ); std::string collisionFilePath( zonePath + "/collision/" ); std::vector< char > section; - std::vector< char > section1; std::vector< char > section2; const xiv::dat::Cat& test = data1->getCategory( "bg" ); auto test_file = data1->getFile( bgLgbPath ); - section = test_file->access_data_sections().at( 0 ); - auto planmap_file = data1->getFile( planmapLgbPath ); + section = test_file->access_data_sections().at( 0 ); section2 = planmap_file->access_data_sections().at( 0 ); - - std::vector< std::string > stringList; - - uint32_t offset1 = 0x20; - - LGB_FILE bgLgb( §ion[ 0 ], "bg" ); LGB_FILE planmapLgb( §ion2[ 0 ], "planmap" ); std::vector< LGB_FILE > lgbList{ bgLgb, planmapLgb }; - uint32_t max_index = 0; - //if( ignoreModels ) + uint32_t totalGroups = 0; + uint32_t totalGroupEntries = 0; + uint32_t count = 0; + for( const auto& lgb : lgbList ) { - std::map< std::string, SGB_FILE > sgbFiles; - - auto loadSgbFile = [ & ]( const std::string& fileName )->bool + std::map< std::string, uint32_t > nameMap; + for( const auto& group : lgb.groups ) { - SGB_FILE sgbFile; - try + totalGroups++; + for( const auto& pEntry : group.entries ) { - char* dataSection = nullptr; - //std::cout << fileName << " "; - auto file = data1->getFile( fileName ); - auto sections = file->get_data_sections(); - dataSection = §ions.at( 0 )[ 0 ]; - sgbFile = SGB_FILE( &dataSection[ 0 ] ); - sgbFiles.insert( std::make_pair( fileName, sgbFile ) ); - return true; - } - catch( std::exception& e ) - { - Logger::error( "Unable to load SGB {}", fileName ); - Logger::error( "{}", e.what() ); - sgbFiles.insert( std::make_pair( fileName, sgbFile ) ); - } - return false; - }; + auto pGimmick = dynamic_cast< LGB_GIMMICK_ENTRY* >( pEntry.get() ); + auto pBgParts = dynamic_cast< LGB_BGPARTS_ENTRY* >( pEntry.get() ); + totalGroupEntries++; - uint32_t totalGroups = 0; - uint32_t totalGroupEntries = 0; - std::cout << zoneName << "\n"; - uint32_t count = 0; - for( const auto& lgb : lgbList ) - { - std::map< std::string, uint32_t > nameMap; - for( const auto& group : lgb.groups ) - { - //std::cout << "\t" << group.name << " Size " << group.header.entryCount << "\n"; - totalGroups++; - for( const auto& pEntry : group.entries ) + if( pEntry->getType() == LgbEntryType::EventObject ) { - auto pGimmick = dynamic_cast< LGB_GIMMICK_ENTRY* >( pEntry.get() ); - auto pBgParts = dynamic_cast< LGB_BGPARTS_ENTRY* >( pEntry.get() ); + auto pObj = pEntry.get(); + static std::string eobjStr( "\"EObj\", " ); + uint32_t id; + uint32_t unknown = 0, unknown2 = 0; + std::string name; + uint32_t eobjlevelHierachyId = 0; - std::string fileName( "" ); - fileName.resize( 256 ); - totalGroupEntries++; + auto pEobj = reinterpret_cast< LGB_EOBJ_ENTRY* >( pObj ); + id = pEobj->header.eobjId; + unknown = pEobj->header.unknown; - if( pEntry->getType() == LgbEntryType::EventObject ) + eobjlevelHierachyId = pEobj->header.levelHierachyId; + + std::string states = ""; + std::string gimmickName = ""; + for( const auto& pEntry1 : group.entries ) { - auto pObj = pEntry.get(); - static std::string eobjStr( "\"EObj\", " ); - - uint32_t id; - uint32_t unknown = 0, unknown2 = 0; - std::string name; - std::string typeStr; - uint32_t eobjlevelHierachyId = 0; - - auto pEobj = reinterpret_cast< LGB_EOBJ_ENTRY* >( pObj ); - id = pEobj->header.eobjId; - unknown = pEobj->header.unknown; - - - typeStr = eobjStr; - eobjlevelHierachyId = pEobj->header.levelHierachyId; - - std::string states = ""; - std::string gimmickName = ""; - for( const auto& pEntry1 : group.entries ) + auto pGObj = pEntry1.get(); + if( pGObj->getType() == LgbEntryType::Gimmick && + pGObj->header.unknown == pEobj->header.levelHierachyId ) { - auto pGObj = pEntry1.get(); - if( pGObj->getType() == LgbEntryType::Gimmick ) + auto pGObjR = reinterpret_cast< LGB_GIMMICK_ENTRY* >( pGObj ); + char* dataSection = nullptr; + + auto file = data1->getFile( pGObjR->gimmickFileName ); + auto sections = file->get_data_sections(); + dataSection = §ions.at( 0 )[ 0 ]; + auto sgbFile = SGB_FILE( &dataSection[ 0 ] ); + + auto pos = pGObjR->gimmickFileName.find_last_of( "/" ); + + if( pos != std::string::npos ) { - if( pGObj->header.unknown == pEobj->header.levelHierachyId ) - { - auto pGObjR = reinterpret_cast< LGB_GIMMICK_ENTRY* >( pGObj ); - char* dataSection = nullptr; - //std::cout << fileName << " "; - - auto file = data1->getFile( pGObjR->gimmickFileName ); - auto sections = file->get_data_sections(); - dataSection = §ions.at( 0 )[ 0 ]; - auto sgbFile = SGB_FILE( &dataSection[ 0 ] ); - - auto pos = pGObjR->gimmickFileName.find_last_of( "/" ); - - if( pos != std::string::npos ) - { - name = pGObjR->gimmickFileName.substr( pos + 1 ); - name = name.substr( 0, name.length() - 4 ); - gimmickName = name; - } - - if( sgbFile.stateEntries.size() > 0 ) - { - states = " // States -> "; - for( auto entries1 : sgbFile.stateEntries ) - { - states += entries1.name + " (id: " + std::to_string( entries1.header.id ) + ") "; - } - states += "\n"; - } - - break; - - } + name = pGObjR->gimmickFileName.substr( pos + 1 ); + name = name.substr( 0, name.length() - 4 ); + gimmickName = name; } + + if( sgbFile.stateEntries.size() > 0 ) + { + states = " // States -> "; + for( auto entries1 : sgbFile.stateEntries ) + { + states += entries1.name + " (id: " + std::to_string( entries1.header.id ) + ") "; + } + states += "\n"; + } + break; } - int state = 4; + } + int state = 4; - if( eobjNameMap.find( id ) != eobjNameMap.end() ) - { - name = eobjNameMap[ id ]; - std::string remove = ",★_ '()[]-\xae\x1a\x1\x2\x1f\x1\x3.:"; - Sapphire::Util::eraseAllIn( name, remove ); + if( eobjNameMap.find( id ) != eobjNameMap.end() ) + { + name = eobjNameMap[ id ]; + std::string remove = ",★_ '()[]-\xae\x1a\x1\x2\x1f\x1\x3.:"; + Sapphire::Util::eraseAllIn( name, remove ); + name[ 0 ] = toupper( name[ 0 ] ); + } + if( name.empty() ) + name = "unknown_" + std::to_string( count++ ); - name[ 0 ] = toupper( name[ 0 ] ); - } - if( name.empty() ) - name = "unknown_" + std::to_string( count++ ); + if( id == 2000182 || gimmickName == "sgvf_w_lvd_b0095" ) + { + state = 5; + name = "Entrance"; + } - if( id == 2000182 || gimmickName == "sgvf_w_lvd_b0095" ) - { - state = 5; - name = "Entrance"; - } + auto count1 = 0; + if( nameMap.find( name ) == nameMap.end() ) + { + nameMap[ name ] = 0; + } + else + { + nameMap[ name ] = ++nameMap[ name ]; + count1 = nameMap[ name ]; + } - auto count1 = 0; - if( nameMap.find( name ) == nameMap.end() ) - { - nameMap[ name ] = 0; - } - else - { - nameMap[ name ] = ++nameMap[ name ]; - count1 = nameMap[ name ]; - } + if( count1 > 0 ) + name = name + "_" + std::to_string( count1 ); - if( count1 > 0 ) - name = name + "_" + std::to_string( count1 ); - - eobjects += " instance.registerEObj( \"" + name + "\", " + std::to_string( id ) + + eobjects += " instance.registerEObj( \"" + name + "\", " + std::to_string( id ) + ", " + std::to_string( eobjlevelHierachyId ) + ", " + std::to_string( state ) + ", " + "{ " + std::to_string( pObj->header.translation.x ) + "f, " @@ -523,19 +364,8 @@ int main( int argc, char* argv[] ) + std::to_string( pObj->header.translation.z ) + "f }, " + std::to_string( pObj->header.scale.x ) + "f, " + - // for whatever reason, the rotation inside the sgbs is the inverse of what the game uses + // the rotation inside the sgbs is the inverse of what the game uses std::to_string( pObj->header.rotation.y * -1.f ) + "f ); \n" + states; - - - std::string outStr( - std::to_string( id ) + ", " + typeStr + "\"" + name + "\", " + - std::to_string( pObj->header.translation.x ) + ", " + - std::to_string( pObj->header.translation.y ) + ", " + - std::to_string( pObj->header.translation.z ) + ", " + - std::to_string( eobjlevelHierachyId ) + "\n" - ); - //eobjOut.write( outStr.c_str(), outStr.size() ); - } } } } @@ -549,7 +379,6 @@ int main( int argc, char* argv[] ) { Logger::error( "{}", e.what() ); } - std::cout << "\n\n\n"; std::ifstream t; if( entry.type == 7 ) @@ -587,7 +416,6 @@ int main( int argc, char* argv[] ) result = std::regex_replace( result, std::regex( "\\SCRIPT_INSTRUCTIONS" ), instruction ); } - std::string subdir = ""; auto subdirIt = instanceContentTypeMap.find( entry.type ); @@ -603,7 +431,7 @@ int main( int argc, char* argv[] ) } - Logger::info( "Finished all tasts in {} seconds", + Logger::info( "Finished all tasks in {} seconds", std::chrono::duration_cast< std::chrono::seconds >( std::chrono::system_clock::now() - startTime ).count() ); if( data1 )