1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-26 06:27:45 +00:00

Simplistic parser for mobs

This commit is contained in:
Mordred 2018-08-26 11:46:56 +02:00
parent 80e67c2846
commit 95b6d3370c
3 changed files with 362 additions and 0 deletions

View file

@ -52,5 +52,6 @@ add_subdirectory( "src/tools/exd_struct_gen" )
add_subdirectory( "src/tools/exd_struct_test" )
add_subdirectory( "src/tools/quest_parser" )
add_subdirectory( "src/tools/discovery_parser" )
add_subdirectory( "src/tools/mob_parse" )
#add_subdirectory("src/tools/pcb_reader")
#add_subdirectory("src/tools/event_object_parser")

View file

@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
project(Tool_mob_parse)
set(SAPPHIRE_BOOST_VER 1.63.0)
set(SAPPHIRE_BOOST_FOLDER_NAME boost_1_63_0)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin/")
file(GLOB SERVER_PUBLIC_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*")
file(GLOB SERVER_SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}*.c*")
#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin/")
add_executable(mob_parse ${SERVER_PUBLIC_INCLUDE_FILES} ${SERVER_SOURCE_FILES})
set_target_properties(mob_parse PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS ON
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../bin/"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../bin/"
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../bin/"
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../bin/"
)
if (UNIX)
target_link_libraries (mob_parse common xivdat pthread mysqlclient dl z)
else()
target_link_libraries (mob_parse common xivdat libmysql zlib1)
endif()
target_link_libraries(mob_parse ${Boost_LIBRARIES} ${Boost_LIBRARIES})

View file

@ -0,0 +1,328 @@
#include <GameData.h>
#include <File.h>
#include <DatCat.h>
#include <ExdData.h>
#include <ExdCat.h>
#include <Exd.h>
#include <Exh.h>
#include <iostream>
#include <cctype>
#include <set>
#include <Exd/ExdDataGenerated.h>
#include <Logging/Logger.h>
#include <boost/range/algorithm/remove_if.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/filesystem.hpp>
using namespace boost::system;
namespace filesys = boost::filesystem;
#include <fstream>
#include <streambuf>
#include <regex>
#include <map>
Core::Logger g_log;
Core::Data::ExdDataGenerated g_exdData;
//const std::string datLocation( "/opt/sapphire_3_15_0/bin/sqpack" );
const std::string datLocation( "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack" );
struct StatusEffect
{
uint16_t effect_id;
uint16_t unknown1;
float duration;
uint32_t sourceActorId;
};
struct FFXIVIpcNpcSpawn
{
uint32_t gimmickId; // needs to be existing in the map, mob will snap to it
uint8_t u2b;
uint8_t u2ab;
uint8_t gmRank;
uint8_t u3b;
uint8_t aggressionMode; // 1 passive, 2 aggressive
uint8_t onlineStatus;
uint8_t u3c;
uint8_t pose;
uint32_t u4;
uint64_t targetId;
uint32_t u6;
uint32_t u7;
uint64_t mainWeaponModel;
uint64_t secWeaponModel;
uint64_t craftToolModel;
uint32_t u14;
uint32_t u15;
uint32_t bNPCBase;
uint32_t bNPCName;
uint32_t u18;
uint32_t u19;
uint32_t directorId;
uint32_t spawnerId;
uint32_t parentActorId;
uint32_t hPMax;
uint32_t hPCurr;
uint32_t displayFlags;
uint16_t fateID;
uint16_t mPCurr;
uint16_t tPCurr;
uint16_t mPMax;
uint16_t tPMax;
uint16_t modelChara;
uint16_t rotation;
uint16_t activeMinion;
uint8_t spawnIndex;
uint8_t state;
uint8_t persistantEmote;
uint8_t modelType;
uint8_t subtype;
uint8_t voice;
uint16_t u25c;
uint8_t enemyType;
uint8_t level;
uint8_t classJob;
uint8_t u26d;
uint16_t u27a;
uint8_t currentMount;
uint8_t mountHead;
uint8_t mountBody;
uint8_t mountFeet;
uint8_t mountColor;
uint8_t scale;
uint32_t u29b;
uint32_t u30b;
StatusEffect effect[30];
float posX;
float posY;
float posZ;
uint32_t models[10];
char name[32];
uint8_t look[26];
char fcTag[6];
uint32_t unk30;
uint32_t unk31;
uint8_t bNPCPartSlot;
uint8_t unk32;
uint16_t unk33;
uint32_t unk34;
};
std::vector< std::string > getAllFilesInDir( const std::string &dirPath,
const std::vector<std::string> dirSkipList = {} )
{
// Create a vector of string
std::vector< std::string > listOfFiles;
try {
// Check if given path exists and points to a directory
if( filesys::exists( dirPath ) && filesys::is_directory( dirPath ) )
{
// Create a Recursive Directory Iterator object and points to the starting of directory
filesys::recursive_directory_iterator iter( dirPath );
// Create a Recursive Directory Iterator object pointing to end.
filesys::recursive_directory_iterator end;
// Iterate till end
while( iter != end )
{
// Check if current entry is a directory and if exists in skip list
if( filesys::is_directory( iter->path() ) &&
( std::find(dirSkipList.begin(), dirSkipList.end(), iter->path().filename() ) != dirSkipList.end() ) )
{
// Skip the iteration of current directory pointed by iterator
#ifdef USING_BOOST
// Boost Fileystsem API to skip current directory iteration
iter.no_push();
#else
// c++17 Filesystem API to skip current directory iteration
iter.disable_recursion_pending();
#endif
}
else
{
// Add the name in vector
listOfFiles.push_back( iter->path().string() );
}
error_code ec;
// Increment the iterator to point to next entry in recursive iteration
iter.increment( ec );
if( ec )
{
std::cerr << "Error While Accessing : " << iter->path().string() << " :: " << ec.message() << '\n';
}
}
}
}
catch( std::system_error & e )
{
std::cerr << "Exception :: " << e.what();
}
return listOfFiles;
}
int main()
{
g_log.init();
g_log.info( "Setting up EXD data" );
if( !g_exdData.init( datLocation ) )
{
g_log.fatal( "Error setting up EXD data " );
return 0;
}
std::map< int, std::vector< FFXIVIpcNpcSpawn > > nameToPacketList;
std::map< int, std::vector< FFXIVIpcNpcSpawn > > zoneToPacketList;
auto listOfFiles = getAllFilesInDir( "G:\\programming\\sapphire\\github\\ffxivmon\\bin\\CapturedNpcs", { ".svn", "logs", "backup" });
for( auto file : listOfFiles )
{
if( !filesys::is_directory( file ) )
{
auto pos = file.find_last_of( "\\" );
if( pos != std::string::npos )
{
auto str = file.substr( 0, pos );
pos = str.find_last_of( "\\" );
auto zone = str.substr( pos + 1 );
//g_log.info( zone );
FFXIVIpcNpcSpawn packet;
std::ifstream is;
is.open( file, std::ios::binary );
is.seekg( 0x20, std::ios::beg );
is.read( ( char* )&packet, sizeof( FFXIVIpcNpcSpawn ) );
is.close();
if( packet.subtype != 2 &&
packet.subtype != 3 &&
packet.enemyType != 0 &&
packet.spawnerId == 0xE0000000 &&
packet.fateID == 0 )
zoneToPacketList[ std::stoi( zone ) ].push_back( packet );
}
}
/* if( filesys::is_directory( file ) )
{
auto pos = file.find_last_of( "\\" );
if( pos != std::string::npos )
{
auto zoneIdStr = file.substr( pos + 1 );
auto teri1 = g_exdData.get< Core::Data::TerritoryType >( std::stoi( zoneIdStr ) );
g_log.info( zoneIdStr + " - " + teri1->name );
}
}
else
{
FFXIVIpcNpcSpawn packet;
std::ifstream is;
is.open( file, std::ios::binary );
is.seekg( 0x20, std::ios::beg );
is.read( ( char* )&packet, sizeof( FFXIVIpcNpcSpawn ) );
is.close();
nameToPacketList[ packet.bNPCName ].push_back( packet );
auto nameStruct = g_exdData.get< Core::Data::BNpcName >( packet.bNPCName );
//g_log.info( nameStruct->singular + " " + std::to_string( packet.bNPCBase ) );
}
*/
}
for( auto entry : zoneToPacketList )
{
//auto nameStruct = g_exdData.get< Core::Data::BNpcName >( entry.first );
auto teri1 = g_exdData.get< Core::Data::TerritoryType >( entry.first );
auto teriPlaceName = g_exdData.get< Core::Data::PlaceName >( teri1->placeName );
g_log.info( std::to_string( entry.first ) + " - " + teri1->name + " - " + teriPlaceName->name );
g_log.info( "Mob Count: " + std::to_string( entry.second.size() ) );
for( auto mob : entry.second )
{
nameToPacketList[ mob.bNPCName ].push_back( mob );
auto nameStruct = g_exdData.get< Core::Data::BNpcName >( mob.bNPCName );
//g_log.info( nameStruct->singular + " " + std::to_string( packet.bNPCBase ) );
}
g_log.info( "Unique Mobs: " + std::to_string( nameToPacketList.size() ) );
for( auto mobName : nameToPacketList )
{
auto nameStruct = g_exdData.get< Core::Data::BNpcName >( mobName.first );
g_log.info( "|--> " + nameStruct->singular + "(" + std::to_string( mobName.second.size() ) + ")" );
for( FFXIVIpcNpcSpawn instance : mobName.second )
{
std::string modelStr = "[";
for( auto modelEntry : instance.models )
{
modelStr += std::to_string( modelEntry ) + ", ";
}
modelStr += "]";
std::string cusStr = "[";
for( auto cusEntry : instance.look )
{
cusStr += std::to_string( cusEntry ) + ", ";
}
cusStr += "]";
//g_log.info( "|----> " + std::to_string( instance.bNPCBase ) + " " + std::to_string( instance.posX ) + ", " + std::to_string( instance.posY ) + ", " + std::to_string( instance.posZ ) );
g_log.info( "|----> " + std::to_string( instance.bNPCBase ) +
" " + std::to_string( instance.mainWeaponModel ) +
", " + std::to_string( instance.secWeaponModel ) +
", " + std::to_string( instance.aggressionMode ) +
", " + std::to_string( instance.enemyType ) +
", " + std::to_string( instance.onlineStatus ) +
", " + std::to_string( instance.pose ) +
", " + std::to_string( instance.modelChara ) +
", " + std::to_string( instance.displayFlags ) + ", " + modelStr + ", " + cusStr + ", " + std::to_string( instance.gimmickId ) );
}
}
nameToPacketList.clear();
}
/*g_log.info( "getting id list " );
auto idList = g_exdData.getTerritoryTypeIdList();
g_log.info( "getting id list done" );
for( auto id : idList )
{
auto teri1 = g_exdData.get<Core::Data::TerritoryType>( id );
g_log.info( teri1->name );
}*/
return 0;
}