diff --git a/config/api.ini.default b/config/api.ini.default new file mode 100644 index 00000000..25cacbb0 --- /dev/null +++ b/config/api.ini.default @@ -0,0 +1,3 @@ +[Network] +ListenIp = 0.0.0.0 +ListenPort = 80 \ No newline at end of file diff --git a/config/config.ini.default b/config/config.ini.default deleted file mode 100644 index cacd9115..00000000 --- a/config/config.ini.default +++ /dev/null @@ -1,62 +0,0 @@ -[Database] -Host = 127.0.0.1 -Port = 3306 -Database = sapphire -Username = sapphire -Password = -SyncThreads = 2 -AsyncThreads = 2 - -[GlobalParameters] -ServerSecret = default -DataPath = C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack - -[GlobalNetwork] -; Values definining how Users and other servers will access - these have to be set to your public IP when running a public server -ZoneHost = 127.0.0.1 -ZonePort = 54992 - -LobbyHost = 127.0.0.1 -LobbyPort = 54994 - -RestHost = 127.0.0.1 -RestPort = 80 - -[Lobby] -WorldID = 67 -AllowNoSessionConnect = false -WorldName = Sapphire - -[LobbyNetwork] -ListenIp = 0.0.0.0 -ListenPort = 54994 - -[CharacterCreation] -DefaultGMRank = 255 - -[RestNetwork] -ListenIp = 0.0.0.0 -ListenPort = 80 - -[Scripts] -; where compiled script modules are located -Path = ./compiledscripts/ -; relative to Path, where we copy and load modules from -CachePath = ./cache/ -; whether we should detect changes to script modules and reload them -HotSwap = true - -[Network] -DisconnectTimeout = 20 - -[ZoneNetwork] -ListenIp = 0.0.0.0 -ListenPort = 54992 - -[General] -; Sent on login - each line must be shorter than 307 characters, split lines with ';' -MotD = Welcome to Sapphire!;This is a very good server;You can change these messages by editing General.MotD in config/config.ini - -[Housing] -; Set the default estate name. %i will be replaced with the plot number -DefaultEstateName = Estate #%i \ No newline at end of file diff --git a/config/global.ini.default b/config/global.ini.default new file mode 100644 index 00000000..87c3b4cc --- /dev/null +++ b/config/global.ini.default @@ -0,0 +1,25 @@ +[Database] +Host = 127.0.0.1 +Port = 3306 +Database = sapphire +Username = sapphire +Password = +SyncThreads = 2 +AsyncThreads = 2 + +[General] +ServerSecret = default +DataPath = C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack +WorldID = 67 +DefaultGMRank = 255 + +[Network] +; Values definining how Users and other servers will access - these have to be set to your public IP when running a public server +ZoneHost = 127.0.0.1 +ZonePort = 54992 + +LobbyHost = 127.0.0.1 +LobbyPort = 54994 + +RestHost = 127.0.0.1 +RestPort = 80 \ No newline at end of file diff --git a/config/lobby.ini.default b/config/lobby.ini.default new file mode 100644 index 00000000..4d88ee63 --- /dev/null +++ b/config/lobby.ini.default @@ -0,0 +1,7 @@ +[Lobby] +AllowNoSessionConnect = false +WorldName = Sapphire + +[Network] +ListenIp = 0.0.0.0 +ListenPort = 54994 \ No newline at end of file diff --git a/config/world.ini.default b/config/world.ini.default new file mode 100644 index 00000000..0fd35e32 --- /dev/null +++ b/config/world.ini.default @@ -0,0 +1,20 @@ +[Scripts] +; where compiled script modules are located +Path = ./compiledscripts/ +; relative to Path, where we copy and load modules from +CachePath = ./cache/ +; whether we should detect changes to script modules and reload them +HotSwap = true + +[Network] +ListenIp = 0.0.0.0 +ListenPort = 54992 +DisconnectTimeout = 20 + +[General] +; Sent on login - each line must be shorter than 307 characters, split lines with ';' +MotD = Welcome to Sapphire!;This is a very good server;You can change these messages by editing General.MotD in config/config.ini + +[Housing] +; Set the default estate name. {0} will be replaced with the plot number +DefaultEstateName = Estate ${0} \ No newline at end of file diff --git a/src/api/main.cpp b/src/api/main.cpp index 467797a4..5fd967a0 100644 --- a/src/api/main.cpp +++ b/src/api/main.cpp @@ -49,16 +49,40 @@ void default_resource_send( const HttpServer& server, const shared_ptr< HttpServ const shared_ptr< ifstream >& ifs ); -auto m_pConfig = std::make_shared< Sapphire::ConfigMgr >(); HttpServer server; -std::string configPath( "config.ini" ); +std::string configPath( "api.ini" ); +Sapphire::Common::Config::ApiConfig m_config; void reloadConfig() { - m_pConfig = std::make_shared< Sapphire::ConfigMgr >(); + auto pConfig = std::make_shared< Sapphire::ConfigMgr >(); - if( !m_pConfig->loadConfig( configPath ) ) - throw "Error loading config "; + Logger::info( "Loading config " + configPath ); + + bool failedLoad = false; + + // load global cfg first + if( !pConfig->loadGlobalConfig( m_config.global ) ) + { + Logger::fatal( "Error loading config global.ini" ); + failedLoad = true; + } + + if( !pConfig->loadConfig( configPath ) ) + { + Logger::fatal( "Error loading config {0}", configPath ); + failedLoad = true; + } + + if( failedLoad ) + { + Logger::fatal( "If this is the first time starting the server, we've copied the default configs for your editing pleasure." ); + throw "Error loading config"; + } + + // setup api config + m_config.network.listenPort = pConfig->getValue< uint16_t >( "Network", "ListenPort", 80 ); + m_config.network.listenIP = pConfig->getValue< std::string >( "Network", "ListenIp", "0.0.0.0" ); } void print_request_info( shared_ptr< HttpServer::Request > request ) @@ -68,14 +92,7 @@ void print_request_info( shared_ptr< HttpServer::Request > request ) bool loadSettings( int32_t argc, char* argv[] ) { - Logger::info( "Loading config " + configPath ); - - if( !m_pConfig->loadConfig( configPath ) ) - { - Logger::fatal( "Error loading config {0}", configPath ); - Logger::fatal( "If this is the first time starting the server, we've copied the default one for your editing pleasure." ); - return false; - } + reloadConfig(); std::vector< std::string > args( argv + 1, argv + argc ); for( size_t i = 0; i + 1 < args.size(); i += 2 ) @@ -91,46 +108,7 @@ bool loadSettings( int32_t argc, char* argv[] ) // trim '-' from start of arg arg = arg.erase( 0, arg.find_first_not_of( '-' ) ); - if( arg == "ip" ) - { - m_pConfig->setValue< std::string >( "RestNetwork.ListenIp", val ); - } - else if( arg == "p" || arg == "port" ) - { - m_pConfig->setValue< std::string >( "RestNetwork.ListenPort", val ); - } - else if( arg == "exdpath" || arg == "datapath" ) - { - m_pConfig->setValue< std::string >( "GlobalParameters.DataPath", val ); - } - else if( arg == "h" || arg == "dbhost" ) - { - m_pConfig->setValue< std::string >( "Database.Host", val ); - } - else if( arg == "dbport" ) - { - m_pConfig->setValue< std::string >( "Database.Port", val ); - } - else if( arg == "u" || arg == "user" || arg == "dbuser" ) - { - m_pConfig->setValue< std::string >( "Database.Username", val ); - } - else if( arg == "pass" || arg == "dbpass" ) - { - m_pConfig->setValue< std::string >( "Database.Password", val ); - } - else if( arg == "d" || arg == "db" || arg == "database" ) - { - m_pConfig->setValue< std::string >( "Database.Database", val ); - } - else if( arg == "lobbyip" || arg == "lobbyhost" ) - { - m_pConfig->setValue< std::string >( "GlobalNetwork.LobbyHost", val ); - } - else if( arg == "lobbyport" ) - { - m_pConfig->setValue< std::string >( "GlobalNetwork.LobbyPort", val ); - } + } catch( ... ) { @@ -140,34 +118,24 @@ bool loadSettings( int32_t argc, char* argv[] ) } Logger::info( "Setting up generated EXD data" ); - auto dataPath = m_pConfig->getValue< std::string >( "GlobalParameters", "DataPath", "" ); + auto dataPath = m_config.global.general.dataPath; if( !g_exdDataGen.init( dataPath ) ) { - Logger::fatal( "Error setting up generated EXD data. Make sure that DataPath is set correctly in config.ini" ); + Logger::fatal( "Error setting up generated EXD data. Make sure that DataPath is set correctly in global.ini" ); Logger::fatal( "DataPath: {0}", dataPath ); return false; } Sapphire::Db::DbLoader loader; - Sapphire::Db::ConnectionInfo info; - info.password = m_pConfig->getValue< std::string >( "Database", "Password", "" ); - info.host = m_pConfig->getValue< std::string >( "Database", "Host", "127.0.0.1" ); - info.database = m_pConfig->getValue< std::string >( "Database", "Database", "sapphire" ); - info.port = m_pConfig->getValue< uint16_t >( "Database", "Port", 3306 ); - info.user = m_pConfig->getValue< std::string >( "Database", "Username", "root" ); - info.syncThreads = m_pConfig->getValue< uint8_t >( "Database", "SyncThreads", 2 ); - info.asyncThreads = m_pConfig->getValue< uint8_t >( "Database", "AsyncThreads", 2 ); - - loader.addDb( g_charaDb, info ); + loader.addDb( g_charaDb, m_config.global.database ); if( !loader.initDbs() ) return false; - server.config.port = static_cast< uint16_t >( std::stoul( - m_pConfig->getValue< std::string >( "RestNetwork", "ListenPort", "80" ) ) ); - server.config.address = m_pConfig->getValue< std::string >( "RestNetwork", "ListenIp", "0.0.0.0" ); + server.config.port = m_config.network.listenPort; + server.config.address = m_config.network.listenIP; - Logger::info( "Database: Connected to {0}:{1}", info.host, info.port ); + Logger::info( "Database: Connected to {0}:{1}", m_config.global.database.host, m_config.global.database.port ); return true; } @@ -267,9 +235,9 @@ void createAccount( shared_ptr< HttpServer::Response > response, shared_ptr< Htt // todo: construct proper json object here std::string json_string = "{\"sId\":\"" + sId + "\", \"lobbyHost\":\"" + - m_pConfig->getValue< std::string >( "GlobalNetwork", "LobbyHost" ) + + m_config.global.network.lobbyHost + "\", \"frontierHost\":\"" + - m_pConfig->getValue< std::string >( "GlobalNetwork", "RestHost" ) + "\"}"; + m_config.global.network.restHost + "\"}"; *response << buildHttpResponse( 200, json_string, JSON ); } else @@ -300,9 +268,9 @@ void login( shared_ptr< HttpServer::Response > response, shared_ptr< HttpServer: // todo: build proper json object and stringify it std::string json_string = "{\"sId\":\"" + sId + "\", \"lobbyHost\":\"" + - m_pConfig->getValue< std::string >( "GlobalNetwork", "LobbyHost" ) + + m_config.global.network.lobbyHost + "\", \"frontierHost\":\"" + - m_pConfig->getValue< std::string >( "GlobalNetwork", "RestHost" ) + "\"}"; + m_config.global.network.restHost + "\"}"; *response << buildHttpResponse( 200, json_string, JSON ); } else @@ -332,7 +300,7 @@ void deleteCharacter( shared_ptr< HttpServer::Response > response, shared_ptr< H int32_t accountId = g_sapphireAPI.checkSession( sId ); - if( m_pConfig->getValue< std::string >( "GlobalParameters", "ServerSecret" ) != secret ) + if( m_config.global.general.serverSecret != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; *response << buildHttpResponse( 403, json_string, JSON ); @@ -372,15 +340,15 @@ void createCharacter( shared_ptr< HttpServer::Response > response, shared_ptr< H if( result != -1 ) { - if( m_pConfig->getValue< std::string >( "GlobalParameters", "ServerSecret" ) != secret ) + if( m_config.global.general.serverSecret != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; *response << buildHttpResponse( 403, json_string, JSON ); } else { - int32_t charId = g_sapphireAPI.createCharacter( result, name, finalJson, m_pConfig->getValue< uint8_t >( - "CharacterCreation", "DefaultGMRank", 255 ) ); + int32_t charId = g_sapphireAPI.createCharacter( result, name, finalJson, + m_config.global.general.defaultGMRank ); std::string json_string = "{\"result\":\"" + std::to_string( charId ) + "\"}"; *response << buildHttpResponse( 200, json_string, JSON ); @@ -413,7 +381,7 @@ void insertSession( shared_ptr< HttpServer::Response > response, shared_ptr< Htt std::string secret = json["secret"]; // reloadConfig(); - if( m_pConfig->getValue< std::string >( "GlobalParameters", "ServerSecret" ) != secret ) + if( m_config.global.general.serverSecret != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; *response << buildHttpResponse( 403, json_string, JSON ); @@ -445,7 +413,7 @@ void checkNameTaken( shared_ptr< HttpServer::Response > response, shared_ptr< Ht // reloadConfig(); - if( m_pConfig->getValue< std::string >( "GlobalParameters", "ServerSecret" ) != secret ) + if( m_config.global.general.serverSecret != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; *response << buildHttpResponse( 403, json_string, JSON ); @@ -482,7 +450,7 @@ void checkSession( shared_ptr< HttpServer::Response > response, shared_ptr< Http if( result != -1 ) { - if( m_pConfig->getValue< std::string >( "GlobalParameters", "ServerSecret" ) != secret ) + if( m_config.global.general.serverSecret != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; *response << buildHttpResponse( 403, json_string, JSON ); @@ -521,7 +489,7 @@ void getNextCharId( shared_ptr< HttpServer::Response > response, shared_ptr< Htt // reloadConfig(); - if( m_pConfig->getValue< std::string >( "GlobalParameters", "ServerSecret" ) != secret ) + if( m_config.global.general.serverSecret != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; *response << buildHttpResponse( 403, json_string, JSON ); @@ -552,7 +520,7 @@ void getNextContentId( shared_ptr< HttpServer::Response > response, shared_ptr< // reloadConfig(); - if( m_pConfig->getValue< std::string >( "GlobalParameters", "ServerSecret" ) != secret ) + if( m_config.global.general.serverSecret != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; *response << buildHttpResponse( 403, json_string, JSON ); @@ -587,7 +555,7 @@ void getCharacterList( shared_ptr< HttpServer::Response > response, shared_ptr< if( result != -1 ) { - if( m_pConfig->getValue< std::string >( "GlobalParameters", "ServerSecret" ) != secret ) + if( m_config.global.general.serverSecret != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; *response << buildHttpResponse( 403, json_string, JSON ); @@ -767,8 +735,7 @@ int main( int argc, char* argv[] ) server.start(); } ); - Logger::info( "API server running on {0}:{1}", m_pConfig->getValue< std::string >( "RestNetwork", "ListenIp", "0.0.0.0" ), - m_pConfig->getValue< std::string >( "RestNetwork", "ListenPort", "80" ) ); + Logger::info( "API server running on {0}:{1}", m_config.network.listenIP, m_config.network.listenPort ); //Wait for server to start so that the client can connect this_thread::sleep_for( chrono::seconds( 1 ) ); diff --git a/src/common/Config/ConfigDef.h b/src/common/Config/ConfigDef.h new file mode 100644 index 00000000..a6a111b8 --- /dev/null +++ b/src/common/Config/ConfigDef.h @@ -0,0 +1,88 @@ +#ifndef SAPPHIRE_CONFIGDEF_H +#define SAPPHIRE_CONFIGDEF_H + +#include + +namespace Sapphire::Common::Config +{ + struct GlobalConfig + { + Sapphire::Db::ConnectionInfo database; + + struct General + { + std::string serverSecret; + std::string dataPath; + uint16_t worldID; + + uint8_t defaultGMRank; + } general; + + struct Network + { + std::string zoneHost; + uint16_t zonePort; + + std::string lobbyHost; + uint16_t lobbyPort; + + std::string restHost; + uint16_t restPort; + } network; + }; + + + struct WorldConfig + { + GlobalConfig global; + + struct Network + { + std::string listenIp; + uint16_t listenPort; + + uint16_t disconnectTimeout; + } network; + + struct Housing + { + std::string defaultEstateName; + } housing; + + struct Scripts + { + std::string path; + std::string cachePath; + bool hotSwap; + } scripts; + + std::string motd; + }; + + struct LobbyConfig + { + GlobalConfig global; + + struct Network + { + std::string listenIp; + uint16_t listenPort; + } network; + + bool allowNoSessionConnect; + std::string worldName; + }; + + struct ApiConfig + { + GlobalConfig global; + + struct Network + { + std::string listenIP; + uint16_t listenPort; + } network; + }; +} + +#endif //SAPPHIRE_CONFIGDEF_H diff --git a/src/common/Config/ConfigMgr.cpp b/src/common/Config/ConfigMgr.cpp index b1e975f2..a1ad914b 100644 --- a/src/common/Config/ConfigMgr.cpp +++ b/src/common/Config/ConfigMgr.cpp @@ -29,6 +29,46 @@ bool Sapphire::ConfigMgr::loadConfig( const std::string& configName ) return true; } +bool Sapphire::ConfigMgr::loadGlobalConfig( Common::Config::GlobalConfig& config, const std::string& configName ) +{ + auto configFile = fs::path( fs::path( m_configFolderRoot ) / configName ); + + if( !fs::exists( configFile ) ) + { + copyDefaultConfig( configName ); + return false; + } + + m_pInih = std::make_unique< INIReader >( configFile.string() ); + if( m_pInih->ParseError() < 0 ) + return false; + + // database + config.database.host = getValue< std::string >( "Database", "Host", "127.0.0.1" ); + config.database.port = getValue< uint16_t >( "Database", "Port", 3306 ); + config.database.database = getValue< std::string >( "Database", "Database", "sapphire" ); + config.database.user = getValue< std::string >( "Database", "Username", "sapphire" ); + config.database.password = getValue< std::string >( "Database", "Password", "" ); + config.database.syncThreads = getValue< uint8_t >( "Database", "SyncThreads", 2 ); + config.database.asyncThreads = getValue< uint8_t >( "Database", "AsyncThreads", 2 ); + + // params + config.general.dataPath = getValue< std::string >( "General", "DataPath", "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack" ); + 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 ); + + // network + config.network.zoneHost = getValue< std::string >( "Network", "ZoneHost", "127.0.0.1" ); + config.network.zonePort = getValue< uint16_t >( "Network", "ZonePort", 54992 ); + config.network.lobbyHost = getValue< std::string >( "Network", "LobbyHost", "127.0.0.1" ); + config.network.lobbyPort = getValue< uint16_t >( "Network", "LobbyPort", 54994 ); + config.network.restHost = getValue< std::string >( "Network", "RestHost", "127.0.0.1" ); + config.network.restPort = getValue< uint16_t >( "Network", "RestPort", 80 ); + + return true; +} + bool Sapphire::ConfigMgr::copyDefaultConfig( const std::string& configName ) { fs::path configPath( m_configFolderRoot ); @@ -43,4 +83,4 @@ bool Sapphire::ConfigMgr::copyDefaultConfig( const std::string& configName ) fs::copy_file( configPath.string() + m_configDefaultSuffix, configPath ); return true; -} +} \ No newline at end of file diff --git a/src/common/Config/ConfigMgr.h b/src/common/Config/ConfigMgr.h index 09586261..919762c2 100644 --- a/src/common/Config/ConfigMgr.h +++ b/src/common/Config/ConfigMgr.h @@ -6,6 +6,7 @@ #include #include #include +#include "ConfigDef.h" namespace Sapphire { @@ -13,10 +14,10 @@ namespace Sapphire { public: ConfigMgr() = default; - ~ConfigMgr() = default; bool loadConfig( const std::string& configName ); + bool loadGlobalConfig( Common::Config::GlobalConfig& config, const std::string& configName = "global.ini" ); template< class T > struct always_false : std::false_type {}; diff --git a/src/common/Database/DbCommon.h b/src/common/Database/DbCommon.h new file mode 100644 index 00000000..89d537b6 --- /dev/null +++ b/src/common/Database/DbCommon.h @@ -0,0 +1,18 @@ +#ifndef SAPPHIRE_DBCOMMON_H +#define SAPPHIRE_DBCOMMON_H + +namespace Sapphire::Db +{ + struct ConnectionInfo + { + std::string user; + std::string password; + std::string database; + std::string host; + uint16_t port; + uint8_t syncThreads; + uint8_t asyncThreads; + }; +} + +#endif //SAPPHIRE_DBCOMMON_H diff --git a/src/common/Database/DbConnection.h b/src/common/Database/DbConnection.h index 05bfd793..a31a531d 100644 --- a/src/common/Database/DbConnection.h +++ b/src/common/Database/DbConnection.h @@ -7,6 +7,7 @@ #include #include #include "Util/LockedWaitQueue.h" +#include "DbCommon.h" namespace Mysql { @@ -31,17 +32,6 @@ namespace Sapphire::Db CONNECTION_BOTH = CONNECTION_ASYNC | CONNECTION_SYNC }; - struct ConnectionInfo - { - std::string user; - std::string password; - std::string database; - std::string host; - uint16_t port; - uint8_t syncThreads; - uint8_t asyncThreads; - }; - using PreparedStatementMap = std::map< uint32_t, std::pair< std::string, ConnectionFlags > >; class DbConnection : diff --git a/src/lobby/GameConnection.cpp b/src/lobby/GameConnection.cpp index 206c06a9..6b17b453 100644 --- a/src/lobby/GameConnection.cpp +++ b/src/lobby/GameConnection.cpp @@ -128,11 +128,10 @@ void Sapphire::Network::GameConnection::getCharList( FFXIVARR_PACKET_RAW& packet serverListPacket->data().seq = 1; serverListPacket->data().offset = 0; serverListPacket->data().numServers = 1; - serverListPacket->data().server[ 0 ].id = g_serverLobby.getConfig()->getValue< uint16_t >( "Lobby", "WorldID", 1 ); + serverListPacket->data().server[ 0 ].id = g_serverLobby.getConfig().global.general.worldID; serverListPacket->data().server[ 0 ].index = 0; serverListPacket->data().final = 1; - strcpy( serverListPacket->data().server[ 0 ].name, - g_serverLobby.getConfig()->getValue< std::string >( "Lobby", "WorldName", "Sapphire" ).c_str() ); + strcpy( serverListPacket->data().server[ 0 ].name, g_serverLobby.getConfig().worldName.c_str() ); pRP.addPacket( serverListPacket ); auto retainerListPacket = makeLobbyPacket< FFXIVIpcRetainerList >( tmpId ); @@ -162,15 +161,13 @@ void Sapphire::Network::GameConnection::getCharList( FFXIVARR_PACKET_RAW& packet auto& charEntry = charList[ charIndex ]; details.uniqueId = std::get< 1 >( charEntry ); details.contentId = std::get< 2 >( charEntry ); - details.serverId = g_serverLobby.getConfig()->getValue< uint16_t >( "Lobby", "WorldID", 1 ); - details.serverId1 = g_serverLobby.getConfig()->getValue< uint16_t >( "Lobby", "WorldID", 1 ); + details.serverId = g_serverLobby.getConfig().global.general.worldID; + details.serverId1 = g_serverLobby.getConfig().global.general.worldID; details.index = charIndex; strcpy( details.charDetailJson, std::get< 3 >( charEntry ).c_str() ); strcpy( details.nameChara, std::get< 0 >( charEntry ).c_str() ); - strcpy( details.nameServer, - g_serverLobby.getConfig()->getValue< std::string >( "Lobby", "WorldName", "Sapphire" ).c_str() ); - strcpy( details.nameServer1, - g_serverLobby.getConfig()->getValue< std::string >( "Lobby", "WorldName", "Sapphire" ).c_str() ); + strcpy( details.nameServer, g_serverLobby.getConfig().worldName.c_str() ); + strcpy( details.nameServer1, g_serverLobby.getConfig().worldName.c_str() ); charListPacket->data().charaDetails[ j ] = details; @@ -236,9 +233,8 @@ void Sapphire::Network::GameConnection::enterWorld( FFXIVARR_PACKET_RAW& packet, auto enterWorldPacket = makeLobbyPacket< FFXIVIpcEnterWorld >( tmpId ); enterWorldPacket->data().contentId = lookupId; enterWorldPacket->data().seq = sequence; - strcpy( enterWorldPacket->data().host, - g_serverLobby.getConfig()->getValue< std::string >( "GlobalNetwork", "ZoneHost" ).c_str() ); - enterWorldPacket->data().port = g_serverLobby.getConfig()->getValue< uint16_t >( "GlobalNetwork", "ZonePort" ); + strcpy( enterWorldPacket->data().host, g_serverLobby.getConfig().global.network.zoneHost.c_str() ); + enterWorldPacket->data().port = g_serverLobby.getConfig().global.network.zonePort; enterWorldPacket->data().charId = logInCharId; memcpy( enterWorldPacket->data().sid, m_pSession->getSessionId(), 66 ); pRP.addPacket( enterWorldPacket ); @@ -249,7 +245,7 @@ bool Sapphire::Network::GameConnection::sendServiceAccountList( FFXIVARR_PACKET_ { LobbySessionPtr pSession = g_serverLobby.getSession( ( char* ) &packet.data[ 0 ] + 0x20 ); - if( g_serverLobby.getConfig()->getValue< bool >( "Lobby", "AllowNoSessionConnect" ) && pSession == nullptr ) + if( g_serverLobby.getConfig().allowNoSessionConnect && pSession == nullptr ) { auto session = make_LobbySession(); session->setAccountID( 0 ); @@ -316,8 +312,7 @@ bool Sapphire::Network::GameConnection::createOrModifyChar( FFXIVARR_PACKET_RAW& auto charCreatePacket = makeLobbyPacket< FFXIVIpcCharCreate >( tmpId ); charCreatePacket->data().content_id = newContentId; strcpy( charCreatePacket->data().name, name.c_str() ); - strcpy( charCreatePacket->data().world, - g_serverLobby.getConfig()->getValue< std::string >( "Lobby", "WorldName", "Sapphire" ).c_str() ); + strcpy( charCreatePacket->data().world, g_serverLobby.getConfig().worldName.c_str() ); charCreatePacket->data().type = 1; charCreatePacket->data().seq = sequence; charCreatePacket->data().unknown = 1; @@ -340,10 +335,8 @@ bool Sapphire::Network::GameConnection::createOrModifyChar( FFXIVARR_PACKET_RAW& auto charCreatePacket = makeLobbyPacket< FFXIVIpcCharCreate >( tmpId ); charCreatePacket->data().content_id = newContentId; strcpy( charCreatePacket->data().name, name.c_str() ); - strcpy( charCreatePacket->data().world, - g_serverLobby.getConfig()->getValue< std::string >( "Lobby", "WorldName", "Sapphire" ).c_str() ); - strcpy( charCreatePacket->data().world2, - g_serverLobby.getConfig()->getValue< std::string >( "Lobby", "WorldName", "Sapphire" ).c_str() ); + strcpy( charCreatePacket->data().world, g_serverLobby.getConfig().worldName.c_str() ); + strcpy( charCreatePacket->data().world2, g_serverLobby.getConfig().worldName.c_str() ); charCreatePacket->data().type = 2; charCreatePacket->data().seq = sequence; charCreatePacket->data().unknown = 1; @@ -371,8 +364,7 @@ bool Sapphire::Network::GameConnection::createOrModifyChar( FFXIVARR_PACKET_RAW& //charCreatePacket->data().content_id = deletePlayer.getContentId(); charCreatePacket->data().content_id = 0; strcpy( charCreatePacket->data().name, name.c_str() ); - strcpy( charCreatePacket->data().world, - g_serverLobby.getConfig()->getValue< std::string >( "Lobby", "WorldName", "Sapphire" ).c_str() ); + strcpy( charCreatePacket->data().world, g_serverLobby.getConfig().worldName.c_str() ); charCreatePacket->data().type = 4; charCreatePacket->data().seq = sequence; charCreatePacket->data().unknown = 1; diff --git a/src/lobby/ServerLobby.cpp b/src/lobby/ServerLobby.cpp index 1efaf3d0..d1530dcf 100644 --- a/src/lobby/ServerLobby.cpp +++ b/src/lobby/ServerLobby.cpp @@ -41,9 +41,9 @@ namespace Sapphire return g_restConnector.getSession( sessionId ); } - ConfigMgrPtr ServerLobby::getConfig() const + Sapphire::Common::Config::LobbyConfig& ServerLobby::getConfig() { - return m_pConfig; + return m_config; } void ServerLobby::run( int32_t argc, char* argv[] ) @@ -67,9 +67,7 @@ namespace Sapphire Network::HivePtr hive( new Network::Hive() ); Network::addServerToHive< Network::GameConnection >( m_ip, m_port, hive, pFw ); - Logger::info( - "Lobby server running on " + m_pConfig->getValue< std::string >( "LobbyNetwork", "ListenIp", "0.0.0.0" ) + ":" + - m_pConfig->getValue< std::string >( "LobbyNetwork", "ListenPort", "80" ) ); + Logger::info( "Lobby server running on {0}:{1}", m_ip, m_port ); std::vector< std::thread > threadGroup; @@ -85,12 +83,33 @@ namespace Sapphire { Logger::info( "Loading config {0}", m_configPath ); + bool failedLoad = false; + if( !m_pConfig->loadGlobalConfig( m_config.global, "global.ini" ) ) + { + Logger::fatal( "Error loading config global.ini, copying default..." ); + failedLoad = true; + } + if( !m_pConfig->loadConfig( m_configPath ) ) { Logger::fatal( "Error loading config {0}", m_configPath ); - Logger::fatal( "If this is the first time starting the server, we've copied the default one for your editing pleasure." ); + failedLoad = true; + } + + if( failedLoad ) + { + Logger::fatal( "If this is the first time starting the server, " + "we've copied the default configs for your editing pleasure." ); return false; } + + // load lobby config + m_config.allowNoSessionConnect = m_pConfig->getValue< bool >( "Lobby", "AllowNoSessionConnect", false ); + m_config.worldName = m_pConfig->getValue< std::string >( "Lobby", "WorldName", "Sapphire" ); + + m_config.network.listenIp = m_pConfig->getValue< std::string >( "Network", "ListenIp", "0.0.0.0" ); + m_config.network.listenPort = m_pConfig->getValue< uint16_t >( "Network", "ListenPort", 54994 ); + std::vector< std::string > args( argv + 1, argv + argc ); for( size_t i = 0; i + 1 < args.size(); i += 2 ) { @@ -108,19 +127,19 @@ namespace Sapphire if( arg == "ip" ) { // todo: ip addr in config - m_pConfig->setValue< std::string >( "LobbyNetwork.ListenIp", val ); + m_config.network.listenIp = val; } else if( arg == "p" || arg == "port" ) { - m_pConfig->setValue< std::string >( "LobbyNetwork.LobbyPort", val ); + m_config.network.listenPort = std::stoi( val ); } else if( arg == "worldip" || arg == "worldip" ) { - m_pConfig->setValue< std::string >( "GlobalNetwork.ZoneHost", val ); + m_config.global.network.zoneHost = val; } else if( arg == "worldport" ) { - m_pConfig->setValue< std::string >( "GlobalNetwork.ZonePort", val ); + m_config.global.network.zonePort = std::stoi( val ); } } catch( ... ) @@ -130,12 +149,13 @@ namespace Sapphire } } - m_port = m_pConfig->getValue< uint16_t >( "LobbyNetwork", "ListenPort", 54994 ); - m_ip = m_pConfig->getValue< std::string >( "LobbyNetwork", "ListenIp", "0.0.0.0" ); + m_port = m_config.network.listenPort; + m_ip = m_config.network.listenIp; - g_restConnector.restHost = m_pConfig->getValue< std::string >( "GlobalNetwork", "RestHost" ) + ":" + - m_pConfig->getValue< std::string >( "GlobalNetwork", "RestPort" ); - g_restConnector.serverSecret = m_pConfig->getValue< std::string >( "GlobalParameters", "ServerSecret" ); + + g_restConnector.restHost = m_config.global.network.restHost + ":" + + std::to_string( m_config.global.network.restPort ); + g_restConnector.serverSecret = m_config.global.general.serverSecret; return true; } diff --git a/src/lobby/ServerLobby.h b/src/lobby/ServerLobby.h index e0907682..8e101bfb 100644 --- a/src/lobby/ServerLobby.h +++ b/src/lobby/ServerLobby.h @@ -4,6 +4,7 @@ #include #include +#include #include "Forwards.h" const std::string LOBBY_VERSION = "0.0.5"; @@ -44,12 +45,14 @@ namespace Sapphire m_sessionMap[ std::string( sessionId ) ] = pSession; } - std::shared_ptr< ConfigMgr > getConfig() const; + Sapphire::Common::Config::LobbyConfig& getConfig(); LobbySessionPtr getSession( char* sessionId ); uint32_t m_numConnections; + Sapphire::Common::Config::LobbyConfig m_config; + }; } diff --git a/src/lobby/mainLobbyServer.cpp b/src/lobby/mainLobbyServer.cpp index 2ef742e4..54e1f9ff 100644 --- a/src/lobby/mainLobbyServer.cpp +++ b/src/lobby/mainLobbyServer.cpp @@ -1,6 +1,6 @@ #include "ServerLobby.h" -Sapphire::ServerLobby g_serverLobby( "config.ini" ); +Sapphire::ServerLobby g_serverLobby( "lobby.ini" ); int main( int32_t argc, char* argv[] ) { diff --git a/src/world/Actor/PlayerEvent.cpp b/src/world/Actor/PlayerEvent.cpp index e243d2a2..089cc5c0 100644 --- a/src/world/Actor/PlayerEvent.cpp +++ b/src/world/Actor/PlayerEvent.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include "Network/GameConnection.h" #include "Network/PacketWrappers/ActorControlPacket142.h" @@ -326,8 +325,8 @@ void Sapphire::Entity::Player::eventItemActionStart( uint32_t eventId, void Sapphire::Entity::Player::onLogin() { - auto pConfig = m_pFw->get< ConfigMgr >(); - auto motd = pConfig->getValue< std::string >( "General", "MotD", "" ); + auto pServerMgr = m_pFw->get< Sapphire::World::ServerMgr >(); + auto motd = pServerMgr->getConfig().motd; std::istringstream ss( motd ); std::string msg; diff --git a/src/world/Script/NativeScriptMgr.cpp b/src/world/Script/NativeScriptMgr.cpp index 6f2f6169..2cf8fa37 100644 --- a/src/world/Script/NativeScriptMgr.cpp +++ b/src/world/Script/NativeScriptMgr.cpp @@ -1,7 +1,7 @@ #include "NativeScriptMgr.h" #include -#include +#include "ServerMgr.h" #include "Framework.h" @@ -124,8 +124,8 @@ namespace Sapphire::Scripting NativeScriptMgr::NativeScriptMgr( FrameworkPtr pFw ) : World::Manager::BaseManager( pFw ) { - auto pConfig = framework()->get< ConfigMgr >(); - m_loader.setCachePath( pConfig->getValue< std::string >( "Scripts", "CachePath", "./cache/" ) ); + auto pServerMgr = framework()->get< Sapphire::World::ServerMgr >(); + m_loader.setCachePath( pServerMgr->getConfig().scripts.cachePath ); } diff --git a/src/world/Script/ScriptMgr.cpp b/src/world/Script/ScriptMgr.cpp index 408c51d9..13702363 100644 --- a/src/world/Script/ScriptMgr.cpp +++ b/src/world/Script/ScriptMgr.cpp @@ -1,6 +1,5 @@ #include #include -#include #include @@ -48,10 +47,9 @@ void Sapphire::Scripting::ScriptMgr::update() bool Sapphire::Scripting::ScriptMgr::init() { std::set< std::string > files; - auto pConfig = framework()->get< ConfigMgr >(); + auto pServerMgr = framework()->get< World::ServerMgr >(); - auto status = loadDir( pConfig->getValue< std::string >( "Scripts", "Path", "./compiledscripts/" ), - files, m_nativeScriptMgr->getModuleExtension() ); + auto status = loadDir( pServerMgr->getConfig().scripts.path, files, m_nativeScriptMgr->getModuleExtension() ); if( !status ) { @@ -81,12 +79,12 @@ bool Sapphire::Scripting::ScriptMgr::init() void Sapphire::Scripting::ScriptMgr::watchDirectories() { - auto pConfig = framework()->get< ConfigMgr >(); - auto shouldWatch = pConfig->getValue< bool >( "Scripts", "HotSwap", true ); + auto pServerMgr = framework()->get< World::ServerMgr >(); + auto shouldWatch = pServerMgr->getConfig().scripts.hotSwap; if( !shouldWatch ) return; - Watchdog::watchMany( pConfig->getValue< std::string >( "Scripts", "Path", "./compiledscripts/" ) + "*" + + Watchdog::watchMany( pServerMgr->getConfig().scripts.path + "*" + m_nativeScriptMgr->getModuleExtension(), [ this ]( const std::vector< ci::fs::path >& paths ) { diff --git a/src/world/ServerMgr.cpp b/src/world/ServerMgr.cpp index 70f452f4..d675859a 100644 --- a/src/world/ServerMgr.cpp +++ b/src/world/ServerMgr.cpp @@ -67,15 +67,43 @@ bool Sapphire::World::ServerMgr::loadSettings( int32_t argc, char* argv[] ) Logger::info( "Loading config {0}", m_configName ); + bool failedLoad = false; + + // load global cfg first + if( !pConfig->loadGlobalConfig( m_config.global ) ) + { + Logger::fatal( "Error loading config global.ini, copying default..." ); + failedLoad = true; + } + if( !pConfig->loadConfig( m_configName ) ) { Logger::fatal( "Error loading config {0}", m_configName ); - Logger::fatal( "If this is the first time starting the server, we've copied the default one for your editing pleasure." ); + failedLoad = true; + } + + if( failedLoad ) + { + Logger::fatal( "If this is the first time starting the server, " + "we've copied the default configs for your editing pleasure." ); return false; } - m_port = pConfig->getValue< uint16_t >( "ZoneNetwork", "ListenPort", 54992 ); - m_ip = pConfig->getValue< std::string >( "ZoneNetwork", "ListenIp", "0.0.0.0" ); + // load world specific config + m_config.scripts.hotSwap = pConfig->getValue( "Scripts", "HotSwap", true ); + m_config.scripts.path = pConfig->getValue< std::string >( "Scripts", "Path", "./compiledscripts/" ); + m_config.scripts.cachePath = pConfig->getValue< std::string >( "Scripts", "CachePath", "./cache/" ); + + m_config.network.disconnectTimeout = pConfig->getValue< uint16_t >( "Network", "DisconnectTimeout", 20 ); + m_config.network.listenIp = pConfig->getValue< std::string >( "Network", "ListenIp", "0.0.0.0" ); + m_config.network.listenPort = pConfig->getValue< uint16_t >( "Network", "ListenPort", 54992 ); + + m_config.motd = pConfig->getValue< std::string >( "General", "MotD", "" ); + + m_config.housing.defaultEstateName = pConfig->getValue< std::string >( "Housing", "DefaultEstateName", "Estate #{}" ); + + m_port = m_config.network.listenPort; + m_ip = m_config.network.listenIp; return true; } @@ -99,27 +127,18 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) Logger::info( "Setting up generated EXD data" ); auto pExdData = std::make_shared< Data::ExdDataGenerated >(); - auto dataPath = pConfig->getValue< std::string >( "GlobalParameters", "DataPath", "" ); + auto dataPath = m_config.global.general.dataPath; if( !pExdData->init( dataPath ) ) { - Logger::fatal( "Error setting up generated EXD data. Make sure that DataPath is set correctly in config.ini" ); + Logger::fatal( "Error setting up generated EXD data. Make sure that DataPath is set correctly in global.ini" ); Logger::fatal( "DataPath: {0}", dataPath ); return; } framework()->set< Data::ExdDataGenerated >( pExdData ); - Sapphire::Db::ConnectionInfo info; - info.password = pConfig->getValue< std::string >( "Database", "Password", "" ); - info.host = pConfig->getValue< std::string >( "Database", "Host", "127.0.0.1" ); - info.database = pConfig->getValue< std::string >( "Database", "Database", "sapphire" ); - info.port = pConfig->getValue< uint16_t >( "Database", "Port", 3306 ); - info.user = pConfig->getValue< std::string >( "Database", "Username", "root" ); - info.syncThreads = pConfig->getValue< uint8_t >( "Database", "SyncThreads", 2 ); - info.asyncThreads = pConfig->getValue< uint8_t >( "Database", "AsyncThreads", 2 ); - auto pDb = std::make_shared< Db::DbWorkerPool< Db::ZoneDbConnection > >(); Sapphire::Db::DbLoader loader; - loader.addDb( *pDb, info ); + loader.addDb( *pDb, m_config.global.database ); if( !loader.initDbs() ) { Logger::fatal( "Database not initialized properly!" ); @@ -461,3 +480,8 @@ Sapphire::Entity::BNpcTemplatePtr Sapphire::World::ServerMgr::getBNpcTemplate( u return nullptr; } + +Sapphire::Common::Config::WorldConfig& Sapphire::World::ServerMgr::getConfig() +{ + return m_config; +} diff --git a/src/world/ServerMgr.h b/src/world/ServerMgr.h index a18e0c45..fa3cf5ea 100644 --- a/src/world/ServerMgr.h +++ b/src/world/ServerMgr.h @@ -7,6 +7,7 @@ #include #include "ForwardsZone.h" #include "Manager/BaseManager.h" +#include namespace Sapphire::World { @@ -18,6 +19,8 @@ namespace Sapphire::World ~ServerMgr() override; + using WorldConfigPtr = std::shared_ptr< Sapphire::Common::Config::WorldConfig >; + void run( int32_t argc, char* argv[] ); bool createSession( uint32_t sessionId ); @@ -48,6 +51,8 @@ namespace Sapphire::World std::string getPlayerNameFromDb( uint32_t playerId, bool forceDbLoad = false ); void updatePlayerName( uint32_t playerId, const std::string& playerNewName ); + Sapphire::Common::Config::WorldConfig& getConfig(); + private: uint16_t m_port; std::string m_ip; @@ -59,6 +64,8 @@ namespace Sapphire::World std::mutex m_sessionMutex; + Sapphire::Common::Config::WorldConfig m_config; + std::map< uint32_t, SessionPtr > m_sessionMapById; std::map< std::string, SessionPtr > m_sessionMapByName; std::map< uint32_t, std::string > m_playerNameMapById; diff --git a/src/world/mainGameServer.cpp b/src/world/mainGameServer.cpp index a39f068b..a0dcddac 100644 --- a/src/world/mainGameServer.cpp +++ b/src/world/mainGameServer.cpp @@ -9,7 +9,7 @@ using namespace Sapphire::World; int main( int32_t argc, char* argv[] ) { auto pFramework = Sapphire::make_Framework(); - auto pServer = std::make_shared< ServerMgr >( "config.ini", pFramework ); + auto pServer = std::make_shared< ServerMgr >( "world.ini", pFramework ); pFramework->set< ServerMgr >( pServer ); pServer->run( argc, argv ); return 0;