mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-09 17:58:20 +00:00
Add support to reload the config (#868)
This commit is contained in:
parent
de3e53de6c
commit
e8ba3357e8
@ -1,61 +1,53 @@
|
||||
#include "dConfig.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "BinaryPathFinder.h"
|
||||
#include "GeneralUtils.h"
|
||||
|
||||
dConfig::dConfig(const std::string& filepath) {
|
||||
m_EmptyString = "";
|
||||
std::ifstream in(BinaryPathFinder::GetBinaryDir() / filepath);
|
||||
m_ConfigFilePath = filepath;
|
||||
LoadConfig();
|
||||
}
|
||||
|
||||
void dConfig::LoadConfig() {
|
||||
std::ifstream in(BinaryPathFinder::GetBinaryDir() / m_ConfigFilePath);
|
||||
if (!in.good()) return;
|
||||
|
||||
std::string line;
|
||||
std::string line{};
|
||||
while (std::getline(in, line)) {
|
||||
if (line.length() > 0) {
|
||||
if (line[0] != '#') ProcessLine(line);
|
||||
}
|
||||
if (!line.empty() && line.front() != '#') ProcessLine(line);
|
||||
}
|
||||
|
||||
std::ifstream sharedConfig(BinaryPathFinder::GetBinaryDir() / "sharedconfig.ini", std::ios::in);
|
||||
if (!sharedConfig.good()) return;
|
||||
|
||||
line.clear();
|
||||
while (std::getline(sharedConfig, line)) {
|
||||
if (line.length() > 0) {
|
||||
if (line[0] != '#') ProcessLine(line);
|
||||
}
|
||||
if (!line.empty() && line.front() != '#') ProcessLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
dConfig::~dConfig(void) {
|
||||
void dConfig::ReloadConfig() {
|
||||
this->m_ConfigValues.clear();
|
||||
LoadConfig();
|
||||
}
|
||||
|
||||
const std::string& dConfig::GetValue(std::string key) {
|
||||
for (size_t i = 0; i < m_Keys.size(); ++i) {
|
||||
if (m_Keys[i] == key) return m_Values[i];
|
||||
}
|
||||
|
||||
return m_EmptyString;
|
||||
return this->m_ConfigValues[key];
|
||||
}
|
||||
|
||||
void dConfig::ProcessLine(const std::string& line) {
|
||||
std::stringstream ss(line);
|
||||
std::string segment;
|
||||
std::vector<std::string> seglist;
|
||||
auto splitLine = GeneralUtils::SplitString(line, '=');
|
||||
|
||||
while (std::getline(ss, segment, '=')) {
|
||||
seglist.push_back(segment);
|
||||
}
|
||||
|
||||
if (seglist.size() != 2) return;
|
||||
if (splitLine.size() != 2) return;
|
||||
|
||||
//Make sure that on Linux, we remove special characters:
|
||||
if (!seglist[1].empty() && seglist[1][seglist[1].size() - 1] == '\r')
|
||||
seglist[1].erase(seglist[1].size() - 1);
|
||||
auto& key = splitLine.at(0);
|
||||
auto& value = splitLine.at(1);
|
||||
if (!value.empty() && value.at(value.size() - 1) == '\r') value.erase(value.size() - 1);
|
||||
|
||||
for (const auto& key : m_Keys) {
|
||||
if (seglist[0] == key) {
|
||||
return; // first loaded key is preferred due to loading shared config secondarily
|
||||
}
|
||||
}
|
||||
if (this->m_ConfigValues.find(key) != this->m_ConfigValues.end()) return;
|
||||
|
||||
m_Keys.push_back(seglist[0]);
|
||||
m_Values.push_back(seglist[1]);
|
||||
this->m_ConfigValues.insert(std::make_pair(key, value));
|
||||
}
|
||||
|
@ -1,20 +1,34 @@
|
||||
#pragma once
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class dConfig {
|
||||
public:
|
||||
dConfig(const std::string& filepath);
|
||||
~dConfig(void);
|
||||
|
||||
/**
|
||||
* Gets the specified key from the config. Returns an empty string if the value is not found.
|
||||
*
|
||||
* @param key Key to find
|
||||
* @return The keys value in the config
|
||||
*/
|
||||
const std::string& GetValue(std::string key);
|
||||
|
||||
/**
|
||||
* Loads the config from a file
|
||||
*/
|
||||
void LoadConfig();
|
||||
|
||||
/**
|
||||
* Reloads the config file to reset values
|
||||
*/
|
||||
void ReloadConfig();
|
||||
|
||||
private:
|
||||
void ProcessLine(const std::string& line);
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_Keys;
|
||||
std::vector<std::string> m_Values;
|
||||
std::string m_EmptyString;
|
||||
std::map<std::string, std::string> m_ConfigValues;
|
||||
std::string m_ConfigFilePath;
|
||||
};
|
||||
|
@ -19,8 +19,9 @@
|
||||
#include "DestroyableComponent.h"
|
||||
|
||||
ScriptedActivityComponent::ScriptedActivityComponent(Entity* parent, int activityID) : Component(parent) {
|
||||
m_ActivityID = activityID;
|
||||
CDActivitiesTable* activitiesTable = CDClientManager::Instance()->GetTable<CDActivitiesTable>("Activities");
|
||||
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == activityID); });
|
||||
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == m_ActivityID); });
|
||||
|
||||
for (CDActivities activity : activities) {
|
||||
m_ActivityInfo = activity;
|
||||
@ -88,6 +89,21 @@ void ScriptedActivityComponent::Serialize(RakNet::BitStream* outBitStream, bool
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptedActivityComponent::ReloadConfig() {
|
||||
CDActivitiesTable* activitiesTable = CDClientManager::Instance()->GetTable<CDActivitiesTable>("Activities");
|
||||
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == m_ActivityID); });
|
||||
for (auto activity : activities) {
|
||||
auto mapID = m_ActivityInfo.instanceMapID;
|
||||
if ((mapID == 1203 || mapID == 1261 || mapID == 1303 || mapID == 1403) && Game::config->GetValue("solo_racing") == "1") {
|
||||
m_ActivityInfo.minTeamSize = 1;
|
||||
m_ActivityInfo.minTeams = 1;
|
||||
} else {
|
||||
m_ActivityInfo.minTeamSize = activity.minTeamSize;
|
||||
m_ActivityInfo.minTeams = activity.minTeams;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptedActivityComponent::HandleMessageBoxResponse(Entity* player, const std::string& id) {
|
||||
if (m_ActivityInfo.ActivityID == 103) {
|
||||
return;
|
||||
|
@ -276,6 +276,12 @@ public:
|
||||
*/
|
||||
ActivityInstance* GetInstance(const LWOOBJID playerID);
|
||||
|
||||
/**
|
||||
* @brief Reloads the config settings for this component
|
||||
*
|
||||
*/
|
||||
void ReloadConfig();
|
||||
|
||||
/**
|
||||
* Removes all the instances
|
||||
*/
|
||||
@ -361,6 +367,12 @@ private:
|
||||
* LMIs for team sizes
|
||||
*/
|
||||
std::unordered_map<uint32_t, uint32_t> m_ActivityLootMatrices;
|
||||
|
||||
/**
|
||||
* The activity id
|
||||
*
|
||||
*/
|
||||
int32_t m_ActivityID;
|
||||
};
|
||||
|
||||
#endif // SCRIPTEDACTIVITYCOMPONENT_H
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include "LevelProgressionComponent.h"
|
||||
#include "AssetManager.h"
|
||||
#include "BinaryPathFinder.h"
|
||||
#include "dConfig.h"
|
||||
|
||||
void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr) {
|
||||
std::string chatCommand;
|
||||
@ -1766,6 +1767,20 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
||||
return;
|
||||
}
|
||||
|
||||
if (chatCommand == "reloadconfig" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
|
||||
Game::config->ReloadConfig();
|
||||
VanityUtilities::SpawnVanity();
|
||||
dpWorld::Instance().Reload();
|
||||
auto entities = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_SCRIPTED_ACTIVITY);
|
||||
for (auto entity : entities) {
|
||||
auto* scriptedActivityComponent = entity->GetComponent<ScriptedActivityComponent>();
|
||||
if (!scriptedActivityComponent) continue;
|
||||
|
||||
scriptedActivityComponent->ReloadConfig();
|
||||
}
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Successfully reloaded config for world!");
|
||||
}
|
||||
|
||||
if (chatCommand == "rollloot" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR && args.size() >= 3) {
|
||||
uint32_t lootMatrixIndex = 0;
|
||||
uint32_t targetLot = 0;
|
||||
|
@ -82,17 +82,15 @@ int main(int argc, char** argv) {
|
||||
Game::logger->Log("MasterServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
||||
Game::logger->Log("MasterServer", "Compiled on: %s", __TIMESTAMP__);
|
||||
|
||||
//Read our config:
|
||||
dConfig config("masterconfig.ini");
|
||||
Game::config = &config;
|
||||
Game::logger->SetLogToConsole(bool(std::stoi(config.GetValue("log_to_console"))));
|
||||
Game::logger->SetLogDebugStatements(config.GetValue("log_debug_statements") == "1");
|
||||
Game::config = new dConfig("masterconfig.ini");
|
||||
Game::logger->SetLogToConsole(bool(std::stoi(Game::config->GetValue("log_to_console"))));
|
||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
||||
|
||||
//Connect to the MySQL Database
|
||||
std::string mysql_host = config.GetValue("mysql_host");
|
||||
std::string mysql_database = config.GetValue("mysql_database");
|
||||
std::string mysql_username = config.GetValue("mysql_username");
|
||||
std::string mysql_password = config.GetValue("mysql_password");
|
||||
std::string mysql_host = Game::config->GetValue("mysql_host");
|
||||
std::string mysql_database = Game::config->GetValue("mysql_database");
|
||||
std::string mysql_username = Game::config->GetValue("mysql_username");
|
||||
std::string mysql_password = Game::config->GetValue("mysql_password");
|
||||
|
||||
try {
|
||||
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
||||
@ -103,7 +101,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
try {
|
||||
std::string clientPathStr = config.GetValue("client_location");
|
||||
std::string clientPathStr = Game::config->GetValue("client_location");
|
||||
if (clientPathStr.empty()) clientPathStr = "./res";
|
||||
std::filesystem::path clientPath = std::filesystem::path(clientPathStr);
|
||||
if (clientPath.is_relative()) {
|
||||
@ -223,16 +221,16 @@ int main(int argc, char** argv) {
|
||||
|
||||
int maxClients = 999;
|
||||
int ourPort = 1000;
|
||||
if (config.GetValue("max_clients") != "") maxClients = std::stoi(config.GetValue("max_clients"));
|
||||
if (config.GetValue("port") != "") ourPort = std::stoi(config.GetValue("port"));
|
||||
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
||||
if (Game::config->GetValue("port") != "") ourPort = std::stoi(Game::config->GetValue("port"));
|
||||
|
||||
Game::server = new dServer(config.GetValue("external_ip"), ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master);
|
||||
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master);
|
||||
|
||||
//Query for the database for a server labeled "master"
|
||||
auto* masterLookupStatement = Database::CreatePreppedStmt("SELECT id FROM `servers` WHERE `name` = 'master'");
|
||||
auto* result = masterLookupStatement->executeQuery();
|
||||
|
||||
auto master_server_ip = config.GetValue("master_ip");
|
||||
auto master_server_ip = Game::config->GetValue("master_ip");
|
||||
|
||||
if (master_server_ip == "") {
|
||||
master_server_ip = Game::server->GetIP();
|
||||
@ -260,7 +258,7 @@ int main(int argc, char** argv) {
|
||||
Game::im = new InstanceManager(Game::logger, Game::server->GetIP());
|
||||
|
||||
//Depending on the config, start up servers:
|
||||
if (config.GetValue("prestart_servers") != "" && config.GetValue("prestart_servers") == "1") {
|
||||
if (Game::config->GetValue("prestart_servers") != "" && Game::config->GetValue("prestart_servers") == "1") {
|
||||
StartChatServer();
|
||||
|
||||
Game::im->GetInstance(0, false, 0)->SetIsReady(true);
|
||||
@ -843,6 +841,7 @@ void ShutdownSequence() {
|
||||
int FinalizeShutdown() {
|
||||
//Delete our objects here:
|
||||
Database::Destroy("MasterServer");
|
||||
if (Game::config) delete Game::config;
|
||||
if (Game::im) delete Game::im;
|
||||
if (Game::server) delete Game::server;
|
||||
if (Game::logger) delete Game::logger;
|
||||
|
@ -6,6 +6,7 @@
|
||||
dpGrid::dpGrid(int numCells, int cellSize) {
|
||||
NUM_CELLS = numCells;
|
||||
CELL_SIZE = cellSize;
|
||||
m_DeleteGrid = true;
|
||||
|
||||
//dumb method but i can't be bothered
|
||||
|
||||
@ -23,6 +24,7 @@ dpGrid::dpGrid(int numCells, int cellSize) {
|
||||
}
|
||||
|
||||
dpGrid::~dpGrid() {
|
||||
if (!this->m_DeleteGrid) return;
|
||||
for (auto& x : m_Cells) { //x
|
||||
for (auto& y : x) { //y
|
||||
for (auto en : y) {
|
||||
|
@ -23,6 +23,15 @@ public:
|
||||
|
||||
void Update(float deltaTime);
|
||||
|
||||
/**
|
||||
* Sets the delete grid parameter to value. When false, the grid will not clean up memory.
|
||||
*
|
||||
* @param value Whether or not to delete entities on deletion of the grid.
|
||||
*/
|
||||
void SetDeleteGrid(bool value) { this->m_DeleteGrid = value; };
|
||||
|
||||
std::vector<std::vector<std::forward_list<dpEntity*>>> GetCells() { return this->m_Cells; };
|
||||
|
||||
private:
|
||||
void HandleEntity(dpEntity* entity, dpEntity* other);
|
||||
void HandleCell(int x, int z, float deltaTime);
|
||||
@ -31,4 +40,5 @@ private:
|
||||
//cells on X, cells on Y for that X, then another vector that contains the entities within that cell.
|
||||
std::vector<std::vector<std::forward_list<dpEntity*>>> m_Cells;
|
||||
std::map<LWOOBJID, dpEntity*> m_GargantuanObjects;
|
||||
bool m_DeleteGrid = true;
|
||||
};
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "dLogger.h"
|
||||
#include "dConfig.h"
|
||||
|
||||
void dpWorld::Initialize(unsigned int zoneID) {
|
||||
void dpWorld::Initialize(unsigned int zoneID, bool generateNewNavMesh) {
|
||||
phys_sp_tilecount = std::atoi(Game::config->GetValue("phys_sp_tilecount").c_str());
|
||||
phys_sp_tilesize = std::atoi(Game::config->GetValue("phys_sp_tilesize").c_str());
|
||||
|
||||
@ -21,13 +21,37 @@ void dpWorld::Initialize(unsigned int zoneID) {
|
||||
m_Grid = new dpGrid(phys_sp_tilecount, phys_sp_tilesize);
|
||||
}
|
||||
|
||||
m_NavMesh = new dNavMesh(zoneID);
|
||||
if (generateNewNavMesh) m_NavMesh = new dNavMesh(zoneID);
|
||||
|
||||
Game::logger->Log("dpWorld", "Physics world initialized!");
|
||||
m_ZoneID = zoneID;
|
||||
}
|
||||
|
||||
void dpWorld::Reload() {
|
||||
if (m_Grid) {
|
||||
m_Grid->SetDeleteGrid(false);
|
||||
auto oldGridCells = m_Grid->GetCells();
|
||||
delete m_Grid;
|
||||
m_Grid = nullptr;
|
||||
|
||||
Initialize(m_ZoneID, false);
|
||||
for (auto column : oldGridCells) {
|
||||
for (auto row : column) {
|
||||
for (auto entity : row) {
|
||||
AddEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
Game::logger->Log("dpWorld", "Successfully reloaded physics world!");
|
||||
} else {
|
||||
Game::logger->Log("dpWorld", "No physics world to reload!");
|
||||
}
|
||||
}
|
||||
|
||||
dpWorld::~dpWorld() {
|
||||
if (m_Grid) {
|
||||
// Triple check this is true
|
||||
m_Grid->SetDeleteGrid(true);
|
||||
delete m_Grid;
|
||||
m_Grid = nullptr;
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ class dpGrid;
|
||||
|
||||
class dpWorld : public Singleton<dpWorld> {
|
||||
public:
|
||||
void Initialize(unsigned int zoneID);
|
||||
void Initialize(unsigned int zoneID, bool generateNewNavMesh = true);
|
||||
void Reload();
|
||||
|
||||
~dpWorld();
|
||||
|
||||
@ -43,4 +44,5 @@ private:
|
||||
std::vector<dpEntity*> m_DynamicEntites;
|
||||
|
||||
dNavMesh* m_NavMesh = nullptr;
|
||||
uint32_t m_ZoneID = 0;
|
||||
};
|
||||
|
@ -250,7 +250,6 @@ int main(int argc, char** argv) {
|
||||
//Load our level:
|
||||
if (zoneID != 0) {
|
||||
dpWorld::Instance().Initialize(zoneID);
|
||||
Game::physicsWorld = &dpWorld::Instance(); //just in case some old code references it
|
||||
dZoneManager::Instance()->Initialize(LWOZONEID(zoneID, instanceID, cloneID));
|
||||
g_CloneID = cloneID;
|
||||
|
||||
@ -1281,7 +1280,6 @@ void WorldShutdownSequence() {
|
||||
|
||||
void FinalizeShutdown() {
|
||||
//Delete our objects here:
|
||||
if (Game::physicsWorld) Game::physicsWorld = nullptr;
|
||||
if (Game::zoneManager) delete Game::zoneManager;
|
||||
|
||||
Game::logger->Log("WorldServer", "Shutdown complete, zone (%i), instance (%i)", Game::server->GetZoneID(), instanceID);
|
||||
|
Loading…
Reference in New Issue
Block a user