mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 06:47:45 +00:00
add wiki_parser;
This commit is contained in:
parent
29f8a8673a
commit
a093ae9864
4 changed files with 464 additions and 1 deletions
|
@ -28,4 +28,5 @@ add_subdirectory( "nav_export" )
|
|||
#add_subdirectory( "BattleNpcParserPs3" )
|
||||
add_subdirectory( "event_object_parser" )
|
||||
add_subdirectory( "action_parse" )
|
||||
add_subdirectory( "wiki_parse" )
|
||||
#add_subdirectory( "questbattle_bruteforce" )
|
14
src/tools/wiki_parse/CMakeLists.txt
Normal file
14
src/tools/wiki_parse/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
cmake_minimum_required( VERSION 3.0.2 )
|
||||
cmake_policy(SET CMP0015 NEW)
|
||||
project(Tool_WikiParse)
|
||||
|
||||
file(GLOB SERVER_PUBLIC_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*")
|
||||
file(GLOB SERVER_SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}*.c*")
|
||||
|
||||
add_executable( wiki_parse ${SERVER_PUBLIC_INCLUDE_FILES} ${SERVER_SOURCE_FILES})
|
||||
|
||||
if (UNIX)
|
||||
target_link_libraries( wiki_parse common xivdat pthread mysql dl z stdc++fs )
|
||||
else()
|
||||
target_link_libraries( wiki_parse common xivdat mysql zlib)
|
||||
endif()
|
448
src/tools/wiki_parse/main.cpp
Normal file
448
src/tools/wiki_parse/main.cpp
Normal file
|
@ -0,0 +1,448 @@
|
|||
|
||||
#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 <string>
|
||||
#include <Exd/ExdData.h>
|
||||
#include <Exd/Structs.h>
|
||||
#include <Logging/Logger.h>
|
||||
#include <Common.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
using namespace Sapphire;
|
||||
Sapphire::Data::ExdData g_exdDataGen;
|
||||
|
||||
//std::string datLocation( "F:\\client3.0\\game\\sqpack" );
|
||||
std::string datLocation( "C:\\Data\\Dev\\ffxiv3.35\\game\\sqpack" );
|
||||
//const std::string datLocation( "/mnt/c/Program Files (x86)/Steam/steamapps/common/FINAL FANTASY XIV Online/game/sqpack" );
|
||||
|
||||
bool invalidChar( char c )
|
||||
{
|
||||
return !( c >= 0 && c < 128 );
|
||||
}
|
||||
|
||||
void stripUnicode( std::string& str )
|
||||
{
|
||||
str.erase( std::remove_if( str.begin(), str.end(), invalidChar ), str.end() );
|
||||
str.erase( std::remove_if( str.begin(), str.end(),
|
||||
[]( char c )
|
||||
{
|
||||
return !std::isalpha( c ) && !std::isdigit( c ) && !std::isspace( c ) &&
|
||||
!std::ispunct( c );
|
||||
} ),
|
||||
str.end() );
|
||||
}
|
||||
|
||||
uint32_t stripNonNumerics( std::string& str )
|
||||
{
|
||||
str.erase( std::remove_if( str.begin(), str.end(),
|
||||
[]( char c )
|
||||
{
|
||||
return !std::isdigit( c );
|
||||
}), str.end() );
|
||||
|
||||
return std::atoi( str.c_str() );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
std::string stringVec( const std::vector< T >& vec )
|
||||
{
|
||||
if( vec.empty() )
|
||||
return "";
|
||||
|
||||
std::ostringstream oss;
|
||||
std::copy( vec.begin(), vec.end() - 1, std::ostream_iterator< T >( oss, ", " ) );
|
||||
oss << vec.back();
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
Logger::init( "wiki_parse" );
|
||||
|
||||
if( argc == 2 )
|
||||
{
|
||||
datLocation = std::string( argv[ 1 ] );
|
||||
}
|
||||
|
||||
Logger::info( "Setting up EXD data" );
|
||||
if( !g_exdDataGen.init( datLocation ) )
|
||||
{
|
||||
Logger::fatal( "Error setting up EXD data " );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CFC list
|
||||
{
|
||||
|
||||
auto idList = g_exdDataGen.getIdList< Excel::ContentFinderCondition >();
|
||||
|
||||
std::stringstream cfcOutputStream;
|
||||
|
||||
auto total = idList.size();
|
||||
int cursor = 0;
|
||||
|
||||
std::map< uint8_t, std::string > instanceContentTypeMap;
|
||||
instanceContentTypeMap[ 0 ] = "";
|
||||
instanceContentTypeMap[ 1 ] = "Raid";
|
||||
instanceContentTypeMap[ 2 ] = "Dungeon";
|
||||
instanceContentTypeMap[ 3 ] = "Guildhest";
|
||||
instanceContentTypeMap[ 4 ] = "Trial";
|
||||
instanceContentTypeMap[ 5 ] = "PvP (The Feast)";
|
||||
instanceContentTypeMap[ 6 ] = "PvP";
|
||||
instanceContentTypeMap[ 7 ] = "Quest Battle";
|
||||
instanceContentTypeMap[ 8 ] = "Hall of the Novice";
|
||||
instanceContentTypeMap[ 9 ] = "Deep Dungeon";
|
||||
instanceContentTypeMap[ 10 ] = "Treasure Hunt";
|
||||
instanceContentTypeMap[ 11 ] = "Event";
|
||||
instanceContentTypeMap[ 12 ] = "PvP (Rival Wings)";
|
||||
instanceContentTypeMap[ 13 ] = "Masked Carnivale";
|
||||
instanceContentTypeMap[ 14 ] = "Goldsaucer (Mahjong)";
|
||||
instanceContentTypeMap[ 15 ] = "Goldsaucer";
|
||||
|
||||
|
||||
cfcOutputStream << "| ID | Instance | Territory | Name | Type |" << std::endl
|
||||
<< "| --- | --- | --- | --- | --- |" << std::endl;
|
||||
|
||||
for( auto id : idList )
|
||||
{
|
||||
auto done = ( cursor++ / static_cast< float >( total ) ) * 100.f;
|
||||
if( cursor % 50 == 0 && cursor > 0 )
|
||||
Logger::info( "Processing {} CFCs of {} ({:.2f}%)", cursor, total, done );
|
||||
|
||||
if( id == 0 )
|
||||
continue;
|
||||
|
||||
auto cfc = g_exdDataGen.getRow< Excel::ContentFinderCondition >( id );
|
||||
|
||||
if( cfc )
|
||||
{
|
||||
auto& cfcData = cfc->data();
|
||||
|
||||
auto pInstanceContent = g_exdDataGen.getRow< Excel::InstanceContent >( cfcData.InstanceContentId );
|
||||
if( !pInstanceContent )
|
||||
continue;
|
||||
|
||||
auto name = pInstanceContent->getString( pInstanceContent->data().Text.Name );
|
||||
|
||||
// cfc ID
|
||||
cfcOutputStream << "| " << std::to_string( id ) << " | ";
|
||||
|
||||
// instance ID
|
||||
cfcOutputStream << std::to_string( cfcData.InstanceContentId ) << " | ";
|
||||
|
||||
// territory type
|
||||
cfcOutputStream << std::to_string( pInstanceContent->data().TerritoryType ) << " | ";
|
||||
|
||||
// instance name
|
||||
cfcOutputStream << name << " | ";
|
||||
|
||||
// instance type
|
||||
cfcOutputStream << instanceContentTypeMap[ pInstanceContent->data().Type ] << " |" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Logger::info( cfcOutputStream.str() );
|
||||
std::ofstream outH( "generated/cfc.txt" );
|
||||
outH << cfcOutputStream.str() << std::endl;
|
||||
outH.close();
|
||||
}
|
||||
|
||||
// territory type list
|
||||
{
|
||||
|
||||
enum TerritoryIntendedUse : uint8_t
|
||||
{
|
||||
Town = 0,
|
||||
OpenWorld = 1,
|
||||
Inn = 2,
|
||||
Dungeon = 3,
|
||||
JailArea = 5,
|
||||
OpeningArea = 6,
|
||||
BeforeTrialDung = 7,
|
||||
AllianceRaid = 8,
|
||||
OpenWorldInstanceBattle = 9,
|
||||
Trial = 10,
|
||||
HousingArea = 13,
|
||||
HousingPrivateArea = 14,
|
||||
MSQPrivateArea = 15,
|
||||
Raids = 16,
|
||||
RaidFights = 17,
|
||||
ChocoboSquare = 19,
|
||||
ChocoboTutorial = 21,
|
||||
Wedding = 22,
|
||||
GoldSaucer = 23,
|
||||
DiademV1 = 26,
|
||||
BeginnerTutorial = 27,
|
||||
PvPTheFeast = 28,
|
||||
MSQEventArea = 29,
|
||||
FreeCompanyGarrison = 30,
|
||||
PalaceOfTheDead = 31,
|
||||
TreasureMapInstance = 33,
|
||||
EventTrial = 36,
|
||||
TheFeastArea = 37,
|
||||
PrivateEventArea = 40,
|
||||
//Eureka = 41, // wat
|
||||
};
|
||||
|
||||
std::map< uint8_t, std::string > teriTypeIntendedUseMap;
|
||||
for( int i = 0; i < 255; ++i )
|
||||
{
|
||||
teriTypeIntendedUseMap[ i ] = "Unknown";
|
||||
}
|
||||
teriTypeIntendedUseMap[ Town ] = "Town";
|
||||
teriTypeIntendedUseMap[ OpenWorld ] = "OpenWorld";
|
||||
teriTypeIntendedUseMap[ Inn ] = "Inn";
|
||||
teriTypeIntendedUseMap[ Dungeon ] = "Dungeon";
|
||||
teriTypeIntendedUseMap[ JailArea ] = "JailArea";
|
||||
teriTypeIntendedUseMap[ OpeningArea ] = "OpeningArea";
|
||||
teriTypeIntendedUseMap[ BeforeTrialDung ] = "BeforeTrialDung";
|
||||
teriTypeIntendedUseMap[ AllianceRaid ] = "AllianceRaid";
|
||||
teriTypeIntendedUseMap[ OpenWorldInstanceBattle ] = "OpenWorldInstanceBattle";
|
||||
teriTypeIntendedUseMap[ Trial ] = "Trial";
|
||||
teriTypeIntendedUseMap[ HousingArea ] = "HousingArea";
|
||||
teriTypeIntendedUseMap[ HousingPrivateArea ] = "HousingPrivateArea";
|
||||
teriTypeIntendedUseMap[ MSQPrivateArea ] = "MSQPrivateArea";
|
||||
teriTypeIntendedUseMap[ Raids ] = "Raids";
|
||||
teriTypeIntendedUseMap[ RaidFights ] = "RaidFights";
|
||||
teriTypeIntendedUseMap[ ChocoboSquare ] = "ChocoboSquare";
|
||||
teriTypeIntendedUseMap[ ChocoboTutorial ] = "ChocoboTutorial";
|
||||
teriTypeIntendedUseMap[ Wedding ] = "Wedding";
|
||||
teriTypeIntendedUseMap[ GoldSaucer ] = "GoldSaucer";
|
||||
teriTypeIntendedUseMap[ DiademV1 ] = "DiademV1";
|
||||
teriTypeIntendedUseMap[ BeginnerTutorial ] = "BeginnerTutorial";
|
||||
teriTypeIntendedUseMap[ PvPTheFeast ] = "PvPTheFeast";
|
||||
teriTypeIntendedUseMap[ MSQEventArea ] = "MSQEventArea";
|
||||
teriTypeIntendedUseMap[ FreeCompanyGarrison ] = "FreeCompanyGarrison";
|
||||
teriTypeIntendedUseMap[ PalaceOfTheDead ] = "PalaceOfTheDead";
|
||||
teriTypeIntendedUseMap[ TreasureMapInstance ] = "TreasureMapInstance";
|
||||
teriTypeIntendedUseMap[ EventTrial ] = "EventTrial";
|
||||
teriTypeIntendedUseMap[ TheFeastArea ] = "TheFeastArea";
|
||||
teriTypeIntendedUseMap[ PrivateEventArea ] = "PrivateEventArea";
|
||||
|
||||
auto idList = g_exdDataGen.getIdList< Excel::TerritoryType >();
|
||||
|
||||
std::stringstream teritypeOutputStream;
|
||||
|
||||
teritypeOutputStream << "| ID | Place Name | Name | Intended Use |" << std::endl
|
||||
<< "| --- | --- | --- | --- |" << std::endl;
|
||||
|
||||
auto total = idList.size();
|
||||
int cursor = 0;
|
||||
|
||||
for( auto id : idList )
|
||||
{
|
||||
auto done = ( cursor++ / static_cast< float >( total ) ) * 100.f;
|
||||
if( cursor % 50 == 0 && cursor > 0 )
|
||||
Logger::info( "Processing {} teritypes of {} ({:.2f}%)", cursor, total, done );
|
||||
|
||||
auto teriType = g_exdDataGen.getRow< Excel::TerritoryType >( id );
|
||||
|
||||
if( teriType )
|
||||
{
|
||||
auto& teriTypeData = teriType->data();
|
||||
|
||||
auto name = teriType->getString( teriTypeData.Name );
|
||||
std::string placeName = "";
|
||||
|
||||
auto pPlaceName = g_exdDataGen.getRow< Excel::PlaceName >( teriTypeData.Area );
|
||||
if( pPlaceName )
|
||||
{
|
||||
placeName = pPlaceName->getString( pPlaceName->data().Text.SGL );
|
||||
}
|
||||
|
||||
if( placeName == "" )
|
||||
placeName = "[empty]";
|
||||
|
||||
// teritype ID
|
||||
teritypeOutputStream << "| " << std::to_string( id ) << " | ";
|
||||
|
||||
// aetheryte placename
|
||||
teritypeOutputStream << placeName << " | ";
|
||||
|
||||
// name
|
||||
teritypeOutputStream << name << " | ";
|
||||
|
||||
// territory intended use
|
||||
teritypeOutputStream << teriTypeIntendedUseMap[ teriTypeData.IntendedUse ] << " |" << std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Logger::info( teritypeOutputStream.str() );
|
||||
std::ofstream outH( "generated/teritype.txt" );
|
||||
outH << teritypeOutputStream.str() << std::endl;
|
||||
outH.close();
|
||||
}
|
||||
|
||||
// class/job list
|
||||
{
|
||||
auto idList = g_exdDataGen.getIdList< Excel::ClassJob >();
|
||||
|
||||
std::stringstream classjobOutputStream;
|
||||
|
||||
classjobOutputStream << "| ID | Name | Short | Main Class |" << std::endl
|
||||
<< "| --- | --- | --- | --- |" << std::endl;
|
||||
|
||||
auto total = idList.size();
|
||||
int cursor = 0;
|
||||
|
||||
for( auto id : idList )
|
||||
{
|
||||
auto done = ( cursor++ / static_cast< float >( total ) ) * 100.f;
|
||||
if( cursor % 50 == 0 && cursor > 0 )
|
||||
Logger::info( "Processing {} classjobs of {} ({:.2f}%)", cursor, total, done );
|
||||
|
||||
auto classJob = g_exdDataGen.getRow< Excel::ClassJob >( id );
|
||||
|
||||
if( classJob )
|
||||
{
|
||||
auto& classJobData = classJob->data();
|
||||
|
||||
auto name = classJob->getString( classJobData.Text.Name );
|
||||
auto shortName = classJob->getString( classJobData.Text.Abbreviation );
|
||||
|
||||
// ID
|
||||
classjobOutputStream << "| " << std::to_string( id ) << " | ";
|
||||
|
||||
// name
|
||||
classjobOutputStream << name << " | ";
|
||||
|
||||
// short name
|
||||
classjobOutputStream << shortName << " | ";
|
||||
|
||||
// main class
|
||||
classjobOutputStream << std::to_string( classJobData.MainClass ) << " |" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Logger::info( classjobOutputStream.str() );
|
||||
std::ofstream outH( "generated/classjob.txt" );
|
||||
outH << classjobOutputStream.str() << std::endl;
|
||||
outH.close();
|
||||
}
|
||||
|
||||
// achievement list
|
||||
{
|
||||
auto idList = g_exdDataGen.getIdList< Excel::Achievement >();
|
||||
|
||||
enum class Type : uint8_t
|
||||
{
|
||||
None,
|
||||
General,
|
||||
LinkedAchievement,
|
||||
Classjob,
|
||||
Unknown_4,// Materia related? id 304
|
||||
Unknown_5,// Hunt related? id 1259
|
||||
Quest, // Quests that need all required args met
|
||||
Unknown_7,
|
||||
Unknown_8,// Map discovery related
|
||||
QuestAny, // Quests that need any required args met
|
||||
ChocoboRank,
|
||||
PvPRank,
|
||||
WolvesDenMatches,
|
||||
WolvesDenWins,
|
||||
InstanceContent,
|
||||
BeastTribeReputation,
|
||||
Unknown_16,
|
||||
FrontlineMatches,
|
||||
FrontlineWinsGC,
|
||||
FrontlineWinsAll,
|
||||
AetherCurrent,
|
||||
};
|
||||
|
||||
std::map< Common::Achievement::Type, std::string > achievementTypeMap;
|
||||
|
||||
achievementTypeMap[ Common::Achievement::Type::None ] = "None";
|
||||
achievementTypeMap[ Common::Achievement::Type::General ] = "General";
|
||||
achievementTypeMap[ Common::Achievement::Type::LinkedAchievement ] = "LinkedAchievement";
|
||||
achievementTypeMap[ Common::Achievement::Type::Classjob ] = "Classjob";
|
||||
achievementTypeMap[ Common::Achievement::Type::Unknown_4 ] = "Unknown_4";
|
||||
achievementTypeMap[ Common::Achievement::Type::Unknown_5 ] = "Unknown_5";
|
||||
achievementTypeMap[ Common::Achievement::Type::Quest ] = "Quest";
|
||||
achievementTypeMap[ Common::Achievement::Type::Unknown_7 ] = "Unknown_7";
|
||||
achievementTypeMap[ Common::Achievement::Type::Unknown_8 ] = "Unknown_8";
|
||||
achievementTypeMap[ Common::Achievement::Type::QuestAny ] = "QuestAny";
|
||||
achievementTypeMap[ Common::Achievement::Type::ChocoboRank ] = "ChocoboRank";
|
||||
achievementTypeMap[ Common::Achievement::Type::PvPRank ] = "PvPRank";
|
||||
achievementTypeMap[ Common::Achievement::Type::WolvesDenMatches ] = "WolvesDenMatches";
|
||||
achievementTypeMap[ Common::Achievement::Type::WolvesDenWins ] = "WolvesDenWins";
|
||||
achievementTypeMap[ Common::Achievement::Type::InstanceContent ] = "InstanceContent";
|
||||
achievementTypeMap[ Common::Achievement::Type::BeastTribeReputation ] = "BeastTribeReputation";
|
||||
achievementTypeMap[ Common::Achievement::Type::Unknown_16 ] = "Unknown_16";
|
||||
achievementTypeMap[ Common::Achievement::Type::FrontlineMatches ] = "FrontlineMatches";
|
||||
achievementTypeMap[ Common::Achievement::Type::FrontlineWinsGC ] = "FrontlineWinsGC";
|
||||
achievementTypeMap[ Common::Achievement::Type::FrontlineWinsAll ] = "FrontlineWinsAll";
|
||||
achievementTypeMap[ Common::Achievement::Type::AetherCurrent ] = "AetherCurrent";
|
||||
|
||||
std::stringstream achvOutputStream;
|
||||
|
||||
achvOutputStream << "| ID | Name | Type (Subtype) | Description |" << std::endl
|
||||
<< "| --- | --- | --- | --- |" << std::endl;
|
||||
|
||||
auto total = idList.size();
|
||||
int cursor = 0;
|
||||
|
||||
for( auto id : idList )
|
||||
{
|
||||
auto done = ( cursor++ / static_cast< float >( total ) ) * 100.f;
|
||||
if( cursor % 50 == 0 && cursor > 0 )
|
||||
Logger::info( "Processing {} achievements of {} ({:.2f}%)", cursor, total, done );
|
||||
|
||||
auto pAchv = g_exdDataGen.getRow< Excel::Achievement >( id );
|
||||
|
||||
if( pAchv )
|
||||
{
|
||||
auto& achvData = pAchv->data();
|
||||
|
||||
auto achvType = static_cast< Common::Achievement::Type >( achvData.ConditionType );
|
||||
std::string type = std::to_string( achvData.ConditionType );
|
||||
|
||||
// verify if achievement type has already been added
|
||||
if( achvType == Common::Achievement::Type::General ||
|
||||
achvType == Common::Achievement::Type::Classjob ||
|
||||
achvType == Common::Achievement::Type::InstanceContent )
|
||||
{
|
||||
type = std::to_string( achvData.ConditionType ) + ", " + std::to_string( achvData.ConditionArg[ 0 ] );
|
||||
}
|
||||
|
||||
auto name = pAchv->getString( achvData.Text.Name );
|
||||
auto desc = pAchv->getString( achvData.Text.Help );
|
||||
|
||||
// ID
|
||||
achvOutputStream << "| " << std::to_string( id ) << " | ";
|
||||
|
||||
// name
|
||||
achvOutputStream << name << " | ";
|
||||
|
||||
// type (+subtype)
|
||||
achvOutputStream << achievementTypeMap[ achvType ] << " (" << type << ") | ";
|
||||
|
||||
// desc
|
||||
achvOutputStream << desc << " |" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Logger::info( achvOutputStream.str() );
|
||||
std::ofstream outH( "generated/achievement.txt" );
|
||||
outH << achvOutputStream.str() << std::endl;
|
||||
outH.close();
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -471,7 +471,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR
|
|||
{
|
||||
server.queueForPlayer( player.getCharacterId(),
|
||||
std::make_shared< ActorControlSelfPacket >( player.getId(), ActorControlType::ToggleWireframeRendering ) );
|
||||
PlayerMgr::sendServerNotice( player, "Wireframe Rendering for {0} was toggled", player.getName());
|
||||
PlayerMgr::sendServerNotice( player, "Wireframe Rendering for {0} was toggled", player.getName() );
|
||||
break;
|
||||
}
|
||||
case GmCommand::Teri:
|
||||
|
|
Loading…
Add table
Reference in a new issue