diff --git a/config/global.ini.default b/config/global.ini.default index 87c3b4cc..db3ec4a2 100644 --- a/config/global.ini.default +++ b/config/global.ini.default @@ -12,6 +12,8 @@ ServerSecret = default DataPath = C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack WorldID = 67 DefaultGMRank = 255 +LogLevel = 1 +LogFilter = 0 [Network] ; Values definining how Users and other servers will access - these have to be set to your public IP when running a public server diff --git a/src/api/main.cpp b/src/api/main.cpp index 5fd967a0..92d422b1 100644 --- a/src/api/main.cpp +++ b/src/api/main.cpp @@ -713,6 +713,8 @@ int main( int argc, char* argv[] ) if( !loadSettings( argc, argv ) ) throw std::exception(); + Logger::setLogLevel( m_config.global.general.logLevel ); + server.resource[ "^/ZoneName/([0-9]+)$" ][ "GET" ] = &getZoneName; server.resource[ "^/sapphire-api/lobby/createAccount" ][ "POST" ] = &createAccount; server.resource[ "^/sapphire-api/lobby/login" ][ "POST" ] = &login; diff --git a/src/common/Config/ConfigDef.h b/src/common/Config/ConfigDef.h index 587ae30f..3aca9cff 100644 --- a/src/common/Config/ConfigDef.h +++ b/src/common/Config/ConfigDef.h @@ -16,6 +16,8 @@ namespace Sapphire::Common::Config uint16_t worldID; uint8_t defaultGMRank; + uint8_t logLevel; + uint32_t logFilter; } general; struct Network diff --git a/src/common/Config/ConfigMgr.cpp b/src/common/Config/ConfigMgr.cpp index a1ad914b..a4fa1bdc 100644 --- a/src/common/Config/ConfigMgr.cpp +++ b/src/common/Config/ConfigMgr.cpp @@ -57,6 +57,8 @@ bool Sapphire::ConfigMgr::loadGlobalConfig( Common::Config::GlobalConfig& config config.general.serverSecret = getValue< std::string >( "General", "ServerSecret", "default" ); config.general.worldID = getValue< uint16_t >( "General", "WorldID", 67 ); config.general.defaultGMRank = getValue< uint8_t >( "General", "DefaultGMRank", 255 ); + config.general.logLevel = getValue< uint8_t >( "General", "LogLevel", 1 ); + config.general.logFilter = getValue< uint32_t >( "General", "LogFilter", 0 ); // network config.network.zoneHost = getValue< std::string >( "Network", "ZoneHost", "127.0.0.1" ); diff --git a/src/common/Logging/Logger.cpp b/src/common/Logging/Logger.cpp index dbf83f4f..a8c17bff 100644 --- a/src/common/Logging/Logger.cpp +++ b/src/common/Logging/Logger.cpp @@ -53,6 +53,11 @@ namespace Sapphire spdlog::flush_on( spdlog::level::critical ); } + void Logger::setLogLevel( uint8_t logLevel ) + { + spdlog::set_level( static_cast< spdlog::level::level_enum >( logLevel ) ); + } + void Logger::error( const std::string& text ) { spdlog::get( "logger" )->error( text ); diff --git a/src/common/Logging/Logger.h b/src/common/Logging/Logger.h index 5151eb1d..af0c9d0d 100644 --- a/src/common/Logging/Logger.h +++ b/src/common/Logging/Logger.h @@ -19,6 +19,7 @@ namespace Sapphire public: static void init( const std::string& logPath ); + static void setLogLevel( uint8_t logLevel ); // todo: this is a minor increase in build time because of fmtlib, but much less than including spdlog directly diff --git a/src/lobby/ServerLobby.cpp b/src/lobby/ServerLobby.cpp index d1530dcf..47d8a868 100644 --- a/src/lobby/ServerLobby.cpp +++ b/src/lobby/ServerLobby.cpp @@ -63,6 +63,8 @@ namespace Sapphire return; } + Logger::setLogLevel( m_config.global.general.logLevel ); + auto pFw = std::make_shared< Framework >(); Network::HivePtr hive( new Network::Hive() ); Network::addServerToHive< Network::GameConnection >( m_ip, m_port, hive, pFw ); diff --git a/src/world/Manager/NaviMgr.cpp b/src/world/Manager/NaviMgr.cpp index 5462af7f..c3490920 100644 --- a/src/world/Manager/NaviMgr.cpp +++ b/src/world/Manager/NaviMgr.cpp @@ -10,10 +10,11 @@ Sapphire::World::Manager::NaviMgr::NaviMgr( FrameworkPtr pFw ) : bool Sapphire::World::Manager::NaviMgr::setupTerritory( const std::string& bgPath ) { - std::string bg; - auto findPos = bgPath.find_last_of( "/" ); - if( findPos != std::string::npos ) - bg = bgPath.substr( findPos + 1 ); + std::string bg = getBgName( bgPath ); + + // check if a provider exists already + if( m_naviProviderTerritoryMap.find( bg ) != m_naviProviderTerritoryMap.end() ) + return true; auto provider = Navi::make_NaviProvider( bg, m_pFw ); @@ -28,13 +29,19 @@ bool Sapphire::World::Manager::NaviMgr::setupTerritory( const std::string& bgPat Sapphire::World::Navi::NaviProviderPtr Sapphire::World::Manager::NaviMgr::getNaviProvider( const std::string& bgPath ) { - std::string bg; - auto findPos = bgPath.find_last_of( "/" ); - if( findPos != std::string::npos ) - bg = bgPath.substr( findPos + 1 ); + std::string bg = getBgName( bgPath ); if( m_naviProviderTerritoryMap.find( bg ) != m_naviProviderTerritoryMap.end() ) return m_naviProviderTerritoryMap[ bg ]; return nullptr; } + +std::string Sapphire::World::Manager::NaviMgr::getBgName( const std::string& bgPath ) +{ + auto findPos = bgPath.find_last_of( "/" ); + if( findPos != std::string::npos ) + return bgPath.substr( findPos + 1 ); + + return ""; +} diff --git a/src/world/Manager/NaviMgr.h b/src/world/Manager/NaviMgr.h index 5a55ab0c..6aeac713 100644 --- a/src/world/Manager/NaviMgr.h +++ b/src/world/Manager/NaviMgr.h @@ -22,6 +22,8 @@ namespace Sapphire::World::Manager private: FrameworkPtr m_pFw; + std::string getBgName( const std::string& bgPath ); + std::unordered_map< std::string, Navi::NaviProviderPtr > m_naviProviderTerritoryMap; }; diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index eab3d6b7..7ad3f463 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -36,7 +36,8 @@ bool Sapphire::World::Navi::NaviProvider::init() { auto baseMesh = meshFolder / std::experimental::filesystem::path( m_internalName + ".nav" ); - loadMesh( baseMesh.string() ); + if( !loadMesh( baseMesh.string() ) ) + return false; initQuery(); @@ -376,11 +377,14 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > return resultCoords; } -void Sapphire::World::Navi::NaviProvider::loadMesh( const std::string& path ) +bool Sapphire::World::Navi::NaviProvider::loadMesh( const std::string& path ) { FILE* fp = fopen( path.c_str(), "rb" ); if( !fp ) - throw std::runtime_error( "Could open navimesh file" ); + { + Logger::error( "Couldn't open navimesh file: {0}", path ); + return false; + } // Read header. NavMeshSetHeader header; @@ -389,19 +393,22 @@ void Sapphire::World::Navi::NaviProvider::loadMesh( const std::string& path ) if( readLen != 1 ) { fclose( fp ); - throw std::runtime_error( "Could not read NavMeshSetHeader" ); + Logger::error( "Couldn't read NavMeshSetHeader for {0}", path ); + return false; } if( header.magic != NAVMESHSET_MAGIC ) { fclose( fp ); - throw std::runtime_error( "Not a NavMeshSet" ); + Logger::error( "'{0}' has an incorrect NavMeshSet header.", path ); + return false; } if( header.version != NAVMESHSET_VERSION ) { fclose( fp ); - throw std::runtime_error( "Invalid NavMeshSet version" ); + Logger::error( "'{0}' has an incorrect NavMeshSet version. Expected '{1}', got '{2}'", path, NAVMESHSET_VERSION, header.version ); + return false; } if( !m_naviMesh ) @@ -410,14 +417,16 @@ void Sapphire::World::Navi::NaviProvider::loadMesh( const std::string& path ) if( !m_naviMesh ) { fclose( fp ); - throw std::runtime_error( "Could not allocate dtNavMesh" ); + Logger::error( "Couldn't allocate dtNavMesh" ); + return false; } dtStatus status = m_naviMesh->init( &header.params ); if( dtStatusFailed( status ) ) { fclose( fp ); - throw std::runtime_error( "Could not initialize dtNavMesh" ); + Logger::error( "Couldn't initialise dtNavMesh" ); + return false; } } @@ -429,13 +438,14 @@ void Sapphire::World::Navi::NaviProvider::loadMesh( const std::string& path ) if( readLen != 1 ) { fclose( fp ); - throw std::runtime_error( "Could not read NavMeshTileHeader" ); + Logger::error( "Couldn't read NavMeshTileHeader from '{0}'", path ); + return false; } if( !tileHeader.tileRef || !tileHeader.dataSize ) break; - uint8_t* data = reinterpret_cast< uint8_t* >( dtAlloc( tileHeader.dataSize, DT_ALLOC_PERM ) ); + auto data = reinterpret_cast< uint8_t* >( dtAlloc( tileHeader.dataSize, DT_ALLOC_PERM ) ); if( !data ) break; memset( data, 0, tileHeader.dataSize ); @@ -444,11 +454,15 @@ void Sapphire::World::Navi::NaviProvider::loadMesh( const std::string& path ) { dtFree( data ); fclose( fp ); - throw std::runtime_error( "Could not read tile data" ); + + Logger::error( "Couldn't read tile data from '{0}'", path ); + return false; } m_naviMesh->addTile( data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0 ); } fclose( fp ); + + return true; } diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 6d7d0f0b..ff833ca4 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -34,7 +34,7 @@ namespace Sapphire::World::Navi explicit NaviProvider( const std::string& internalName, FrameworkPtr pFw ); bool init(); - void loadMesh( const std::string& path ); + bool loadMesh( const std::string& path ); void initQuery(); void toDetourPos( const Common::FFXIVARR_POSITION3& position, float* out ); diff --git a/src/world/Script/ScriptMgr.cpp b/src/world/Script/ScriptMgr.cpp index c1cb2f69..d9021b9f 100644 --- a/src/world/Script/ScriptMgr.cpp +++ b/src/world/Script/ScriptMgr.cpp @@ -53,7 +53,7 @@ bool Sapphire::Scripting::ScriptMgr::init() if( !status ) { - Logger::error( "ScriptMgr: failed to load scripts, the server will not function correctly without scripts loaded." ); + Logger::error( "ScriptMgr: failed to load modules, the server will not function correctly without scripts loaded." ); return false; } diff --git a/src/world/ServerMgr.cpp b/src/world/ServerMgr.cpp index 1b314584..7149356d 100644 --- a/src/world/ServerMgr.cpp +++ b/src/world/ServerMgr.cpp @@ -129,6 +129,8 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) return; } + Logger::setLogLevel( m_config.global.general.logLevel ); + Logger::info( "Setting up generated EXD data" ); auto pExdData = std::make_shared< Data::ExdDataGenerated >(); auto dataPath = m_config.global.general.dataPath;