1
0

Initial implementation of IniFile overloading

This commit is contained in:
tycho 2015-05-14 15:47:51 +01:00 committed by tycho
parent da58620d45
commit b9efa02c80
22 changed files with 955 additions and 116 deletions

View File

@ -118,7 +118,7 @@ void cPluginManager::ReloadPluginsNow(void)
void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni) void cPluginManager::ReloadPluginsNow(cSettingsRepositoryInterface & a_Settings)
{ {
LOG("-- Loading Plugins --"); LOG("-- Loading Plugins --");
@ -130,7 +130,7 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
RefreshPluginList(); RefreshPluginList();
// Load the plugins: // Load the plugins:
AStringVector ToLoad = GetFoldersToLoad(a_SettingsIni); AStringVector ToLoad = GetFoldersToLoad(a_Settings);
for (auto & pluginFolder: ToLoad) for (auto & pluginFolder: ToLoad)
{ {
LoadPlugin(pluginFolder); LoadPlugin(pluginFolder);
@ -157,16 +157,16 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
void cPluginManager::InsertDefaultPlugins(cIniFile & a_SettingsIni) void cPluginManager::InsertDefaultPlugins(cSettingsRepositoryInterface & a_Settings)
{ {
a_SettingsIni.AddKeyName("Plugins"); a_Settings.AddKeyName("Plugins");
a_SettingsIni.AddKeyComment("Plugins", " Plugin=Debuggers"); a_Settings.AddKeyComment("Plugins", " Plugin=Debuggers");
a_SettingsIni.AddKeyComment("Plugins", " Plugin=HookNotify"); a_Settings.AddKeyComment("Plugins", " Plugin=HookNotify");
a_SettingsIni.AddKeyComment("Plugins", " Plugin=ChunkWorx"); a_Settings.AddKeyComment("Plugins", " Plugin=ChunkWorx");
a_SettingsIni.AddKeyComment("Plugins", " Plugin=APIDump"); a_Settings.AddKeyComment("Plugins", " Plugin=APIDump");
a_SettingsIni.AddValue("Plugins", "Plugin", "Core"); a_Settings.AddValue("Plugins", "Plugin", "Core");
a_SettingsIni.AddValue("Plugins", "Plugin", "TransAPI"); a_Settings.AddValue("Plugins", "Plugin", "TransAPI");
a_SettingsIni.AddValue("Plugins", "Plugin", "ChatLog"); a_Settings.AddValue("Plugins", "Plugin", "ChatLog");
} }
@ -1896,25 +1896,23 @@ size_t cPluginManager::GetNumLoadedPlugins(void) const
AStringVector cPluginManager::GetFoldersToLoad(cIniFile & a_SettingsIni) AStringVector cPluginManager::GetFoldersToLoad(cSettingsRepositoryInterface & a_Settings)
{ {
// Check if the Plugins section exists. // Check if the Plugins section exists.
int KeyNum = a_SettingsIni.FindKey("Plugins"); if (a_Settings.KeyExists("Plugins"))
if (KeyNum == -1)
{ {
InsertDefaultPlugins(a_SettingsIni); InsertDefaultPlugins(a_Settings);
KeyNum = a_SettingsIni.FindKey("Plugins");
} }
// Get the list of plugins to load: // Get the list of plugins to load:
AStringVector res; AStringVector res;
int NumPlugins = a_SettingsIni.GetNumValues(KeyNum); auto Values = a_Settings.GetValues("Plugins");
for (int i = 0; i < NumPlugins; i++) for (auto NameValue : Values)
{ {
AString ValueName = a_SettingsIni.GetValueName(KeyNum, i); AString ValueName = NameValue.first;
if (ValueName.compare("Plugin") == 0) if (ValueName.compare("Plugin") == 0)
{ {
AString PluginFile = a_SettingsIni.GetValue(KeyNum, i); AString PluginFile = NameValue.second;
if (!PluginFile.empty()) if (!PluginFile.empty())
{ {
res.push_back(PluginFile); res.push_back(PluginFile);

View File

@ -24,6 +24,7 @@ class cPlayer;
class cPlugin; class cPlugin;
class cProjectileEntity; class cProjectileEntity;
class cWorld; class cWorld;
class cSettingsRepositoryInterface;
struct TakeDamageInfo; struct TakeDamageInfo;
typedef SharedPtr<cPlugin> cPluginPtr; typedef SharedPtr<cPlugin> cPluginPtr;
@ -364,20 +365,20 @@ private:
/** Reloads all plugins, defaulting to settings.ini for settings location */ /** Reloads all plugins, defaulting to settings.ini for settings location */
void ReloadPluginsNow(void); void ReloadPluginsNow(void);
/** Reloads all plugins with a cIniFile object expected to be initialised to settings.ini */ /** Reloads all plugins with a settings repo expected to be initialised to settings.ini */
void ReloadPluginsNow(cIniFile & a_SettingsIni); void ReloadPluginsNow(cSettingsRepositoryInterface & a_Settings);
/** Unloads all plugins */ /** Unloads all plugins */
void UnloadPluginsNow(void); void UnloadPluginsNow(void);
/** Handles writing default plugins if 'Plugins' key not found using a cIniFile object expected to be intialised to settings.ini */ /** Handles writing default plugins if 'Plugins' key not found using a settings repo expected to be intialised to settings.ini */
void InsertDefaultPlugins(cIniFile & a_SettingsIni); void InsertDefaultPlugins(cSettingsRepositoryInterface & a_Settings);
/** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns crExecuted if the command is executed. */ /** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns crExecuted if the command is executed. */
CommandResult HandleCommand(cPlayer & a_Player, const AString & a_Command, bool a_ShouldCheckPermissions); CommandResult HandleCommand(cPlayer & a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
/** Returns the folders that are specified in the settings ini to load plugins from. */ /** Returns the folders that are specified in the settings ini to load plugins from. */
AStringVector GetFoldersToLoad(cIniFile & a_SettingsIni); AStringVector GetFoldersToLoad(cSettingsRepositoryInterface & a_Settings);
} ; // tolua_export } ; // tolua_export

View File

@ -48,11 +48,13 @@ SET (SRCS
Logger.cpp Logger.cpp
Map.cpp Map.cpp
MapManager.cpp MapManager.cpp
MemorySettingsRepository.cpp
MobCensus.cpp MobCensus.cpp
MobFamilyCollecter.cpp MobFamilyCollecter.cpp
MobProximityCounter.cpp MobProximityCounter.cpp
MobSpawner.cpp MobSpawner.cpp
MonsterConfig.cpp MonsterConfig.cpp
OverridesSettingsRepository.cpp
ProbabDistrib.cpp ProbabDistrib.cpp
RankManager.cpp RankManager.cpp
RCONServer.cpp RCONServer.cpp
@ -116,11 +118,13 @@ SET (HDRS
Map.h Map.h
MapManager.h MapManager.h
Matrix4.h Matrix4.h
MemorySettingsRepository.h
MobCensus.h MobCensus.h
MobFamilyCollecter.h MobFamilyCollecter.h
MobProximityCounter.h MobProximityCounter.h
MobSpawner.h MobSpawner.h
MonsterConfig.h MonsterConfig.h
OverridesSettingsRepository.h
ProbabDistrib.h ProbabDistrib.h
RankManager.h RankManager.h
RCONServer.h RCONServer.h
@ -128,6 +132,7 @@ SET (HDRS
Scoreboard.h Scoreboard.h
Server.h Server.h
SetChunkData.h SetChunkData.h
SettingsRepositoryInterface.h
Statistics.h Statistics.h
StringCompression.h StringCompression.h
StringUtils.h StringUtils.h
@ -142,6 +147,7 @@ SET (HDRS
include_directories(".") include_directories(".")
include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/sqlite") include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/sqlite")
include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/SQLiteCpp/include") include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/SQLiteCpp/include")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/TCLAP/include")
configure_file("BuildInfo.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/BuildInfo.h") configure_file("BuildInfo.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/BuildInfo.h")

View File

@ -436,7 +436,7 @@ typename std::enable_if<std::is_arithmetic<T>::value, C>::type CeilC(T a_Value)
template <class T, class... Args> template <class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args) std::unique_ptr<T> make_unique(Args&&... args)
{ {
return std::unique_ptr<T>(new T(args...)); return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
} }
// a tick is 50 ms // a tick is 50 ms

View File

@ -49,6 +49,9 @@ cIniFile::cIniFile(void) :
bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect)
{ {
m_Filename = a_FileName;
// Normally you would use ifstream, but the SGI CC compiler has // Normally you would use ifstream, but the SGI CC compiler has
// a few bugs with ifstream. So ... fstream used. // a few bugs with ifstream. So ... fstream used.
fstream f; fstream f;
@ -56,7 +59,8 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect)
AString keyname, valuename, value; AString keyname, valuename, value;
AString::size_type pLeft, pRight; AString::size_type pLeft, pRight;
bool IsFromExampleRedirect = false; bool IsFromExampleRedirect = false;
f.open((FILE_IO_PREFIX + a_FileName).c_str(), ios::in); f.open((FILE_IO_PREFIX + a_FileName).c_str(), ios::in);
if (f.fail()) if (f.fail())
{ {
@ -650,7 +654,7 @@ void cIniFile::Clear(void)
bool cIniFile::HasValue(const AString & a_KeyName, const AString & a_ValueName) bool cIniFile::HasValue(const AString & a_KeyName, const AString & a_ValueName) const
{ {
// Find the key: // Find the key:
int keyID = FindKey(a_KeyName); int keyID = FindKey(a_KeyName);
@ -889,8 +893,36 @@ void cIniFile::RemoveBom(AString & a_line) const
bool cIniFile::KeyExists(AString a_keyname) const
{
return FindKey(a_keyname) != noID;
}
std::vector<std::pair<AString, AString>> cIniFile::GetValues(AString a_keyName)
{
std::vector<std::pair<AString, AString>> ret;
int keyID = FindKey(a_keyName);
if (keyID == noID)
{
return ret;
}
for (size_t valueID = 0; valueID < keys[keyID].names.size(); ++valueID)
{
ret.emplace_back(keys[keyID].names[valueID], keys[keyID].values[valueID]);
}
return ret;
}
AStringVector ReadUpgradeIniPorts( AStringVector ReadUpgradeIniPorts(
cIniFile & a_IniFile, cSettingsRepositoryInterface & a_Settings,
const AString & a_KeyName, const AString & a_KeyName,
const AString & a_PortsValueName, const AString & a_PortsValueName,
const AString & a_OldIPv4ValueName, const AString & a_OldIPv4ValueName,
@ -899,23 +931,23 @@ AStringVector ReadUpgradeIniPorts(
) )
{ {
// Read the regular value, but don't use the default (in order to detect missing value for upgrade): // Read the regular value, but don't use the default (in order to detect missing value for upgrade):
AStringVector Ports = StringSplitAndTrim(a_IniFile.GetValue(a_KeyName, a_PortsValueName), ";,"); AStringVector Ports = StringSplitAndTrim(a_Settings.GetValue(a_KeyName, a_PortsValueName), ";,");
if (Ports.empty()) if (Ports.empty())
{ {
// Historically there were two separate entries for IPv4 and IPv6, merge them and migrate: // Historically there were two separate entries for IPv4 and IPv6, merge them and migrate:
AString Ports4 = a_IniFile.GetValue(a_KeyName, a_OldIPv4ValueName, a_DefaultValue); AString Ports4 = a_Settings.GetValue(a_KeyName, a_OldIPv4ValueName, a_DefaultValue);
AString Ports6 = a_IniFile.GetValue(a_KeyName, a_OldIPv6ValueName); AString Ports6 = a_Settings.GetValue(a_KeyName, a_OldIPv6ValueName);
Ports = MergeStringVectors(StringSplitAndTrim(Ports4, ";,"), StringSplitAndTrim(Ports6, ";,")); Ports = MergeStringVectors(StringSplitAndTrim(Ports4, ";,"), StringSplitAndTrim(Ports6, ";,"));
a_IniFile.DeleteValue(a_KeyName, a_OldIPv4ValueName); a_Settings.DeleteValue(a_KeyName, a_OldIPv4ValueName);
a_IniFile.DeleteValue(a_KeyName, a_OldIPv6ValueName); a_Settings.DeleteValue(a_KeyName, a_OldIPv6ValueName);
// If those weren't present or were empty, use the default:" // If those weren't present or were empty, use the default:"
if (Ports.empty()) if (Ports.empty())
{ {
Ports = StringSplitAndTrim(a_DefaultValue, ";,"); Ports = StringSplitAndTrim(a_DefaultValue, ";,");
} }
a_IniFile.SetValue(a_KeyName, a_PortsValueName, StringsConcat(Ports, ',')); a_Settings.SetValue(a_KeyName, a_PortsValueName, StringsConcat(Ports, ','));
} }
return Ports; return Ports;
@ -923,4 +955,3 @@ AStringVector ReadUpgradeIniPorts(

View File

@ -18,7 +18,7 @@
#pragma once #pragma once
#include "SettingsRepositoryInterface.h"
#define MAX_KEYNAME 128 #define MAX_KEYNAME 128
#define MAX_VALUENAME 128 #define MAX_VALUENAME 128
@ -30,10 +30,12 @@
// tolua_begin // tolua_begin
class cIniFile class cIniFile : public cSettingsRepositoryInterface
{ {
private: private:
bool m_IsCaseInsensitive; bool m_IsCaseInsensitive;
AString m_Filename;
struct key struct key
{ {
@ -53,15 +55,19 @@ private:
void RemoveBom(AString & a_line) const; void RemoveBom(AString & a_line) const;
public: public:
enum errors
{
noID = -1,
};
/// Creates a new instance with no data /// Creates a new instance with no data
cIniFile(void); cIniFile(void);
// tolua_end
virtual ~cIniFile() = default;
virtual std::vector<std::pair<AString, AString>> GetValues(AString a_keyName) override;
virtual bool KeyExists(const AString a_keyName) const override;
// tolua_begin
// Sets whether or not keynames and valuenames should be case sensitive. // Sets whether or not keynames and valuenames should be case sensitive.
// The default is case insensitive. // The default is case insensitive.
void CaseSensitive (void) { m_IsCaseInsensitive = false; } void CaseSensitive (void) { m_IsCaseInsensitive = false; }
@ -77,11 +83,13 @@ public:
/// Writes data stored in class to the specified ini file /// Writes data stored in class to the specified ini file
bool WriteFile(const AString & a_FileName) const; bool WriteFile(const AString & a_FileName) const;
virtual bool Flush() override { return WriteFile(m_Filename); }
/// Deletes all stored ini data (but doesn't touch the file) /// Deletes all stored ini data (but doesn't touch the file)
void Clear(void); void Clear(void);
/** Returns true iff the specified value exists. */ /** Returns true iff the specified value exists. */
bool HasValue(const AString & a_KeyName, const AString & a_ValueName); bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const;
/// Returns index of specified key, or noID if not found /// Returns index of specified key, or noID if not found
int FindKey(const AString & keyname) const; int FindKey(const AString & keyname) const;
@ -222,7 +230,7 @@ Reads the list of ports from a_PortsValueName. If that value doesn't exist or is
in a_OldIPv4ValueName and a_OldIPv6ValueName; in this case the old values are removed from the INI file. in a_OldIPv4ValueName and a_OldIPv6ValueName; in this case the old values are removed from the INI file.
If there is none of the three values or they are all empty, the default is used and stored in the Ports value. */ If there is none of the three values or they are all empty, the default is used and stored in the Ports value. */
AStringVector ReadUpgradeIniPorts( AStringVector ReadUpgradeIniPorts(
cIniFile & a_IniFile, cSettingsRepositoryInterface & a_Settings,
const AString & a_KeyName, const AString & a_KeyName,
const AString & a_PortsValueName, const AString & a_PortsValueName,
const AString & a_OldIPv4ValueName, const AString & a_OldIPv4ValueName,

View File

@ -0,0 +1,312 @@
#include "Globals.h"
#include "MemorySettingsRepository.h"
bool cMemorySettingsRepository::KeyExists(const AString keyname) const
{
return m_Map.count(keyname) != 0;
}
bool cMemorySettingsRepository::HasValue(const AString & a_KeyName, const AString & a_ValueName) const
{
auto outerIter = m_Map.find(a_KeyName);
if (outerIter == m_Map.end())
{
return false;
}
auto iter = outerIter->second.find(a_ValueName);
if (iter == outerIter->second.end())
{
return false;
}
return true;
}
int cMemorySettingsRepository::AddKeyName(const AString & a_keyname)
{
m_Map.emplace(a_keyname, std::unordered_multimap<AString, sValue>{});
return 0;
}
bool cMemorySettingsRepository::AddKeyComment(const AString & keyname, const AString & comment)
{
return false;
}
AString cMemorySettingsRepository::GetKeyComment(const AString & keyname, const int commentID) const
{
return "";
}
bool cMemorySettingsRepository::DeleteKeyComment(const AString & keyname, const int commentID)
{
return false;
}
void cMemorySettingsRepository::AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value)
{
if (m_Writable)
{
m_Map[a_KeyName].emplace(a_ValueName, sValue(a_Value));
}
}
void cMemorySettingsRepository::AddValue (const AString & a_KeyName, const AString & a_ValueName, Int64 a_Value)
{
if (m_Writable)
{
m_Map[a_KeyName].emplace(a_ValueName, sValue(a_Value));
}
}
void cMemorySettingsRepository::AddValue (const AString & a_KeyName, const AString & a_ValueName, bool a_Value)
{
if (m_Writable)
{
m_Map[a_KeyName].emplace(a_ValueName, sValue(a_Value));
}
}
std::vector<std::pair<AString, AString>> cMemorySettingsRepository::GetValues(AString a_keyName)
{
std::vector<std::pair<AString, AString>> ret;
for (auto pair : m_Map[a_keyName])
{
ret.emplace_back(pair.first, pair.second.getStringValue());
}
return ret;
}
AString cMemorySettingsRepository::GetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & defValue) const
{
auto outerIter = m_Map.find(a_KeyName);
if (outerIter == m_Map.end())
{
return defValue;
}
auto iter = outerIter->second.find(a_ValueName);
if (iter == outerIter->second.end())
{
return defValue;
}
return iter->second.getStringValue();
}
AString cMemorySettingsRepository::GetValueSet (const AString & a_KeyName, const AString & a_ValueName, const AString & defValue)
{
auto outerIter = m_Map.find(a_KeyName);
if (outerIter == m_Map.end())
{
AddValue(a_KeyName, a_ValueName, defValue);
return defValue;
}
auto iter = outerIter->second.find(a_ValueName);
if (iter == outerIter->second.end())
{
AddValue(a_KeyName, a_ValueName, defValue);
return defValue;
}
return iter->second.getStringValue();
}
int cMemorySettingsRepository::GetValueSetI(const AString & a_KeyName, const AString & a_ValueName, const int defValue)
{
auto outerIter = m_Map.find(a_KeyName);
if (outerIter == m_Map.end())
{
AddValue(a_KeyName, a_ValueName, static_cast<Int64>(defValue));
return defValue;
}
auto iter = outerIter->second.find(a_ValueName);
if (iter == outerIter->second.end())
{
AddValue(a_KeyName, a_ValueName, static_cast<Int64>(defValue));
return defValue;
}
return static_cast<int>(iter->second.getIntValue());
}
Int64 cMemorySettingsRepository::GetValueSetI(const AString & a_KeyName, const AString & a_ValueName, const Int64 defValue)
{
auto outerIter = m_Map.find(a_KeyName);
if (outerIter == m_Map.end())
{
AddValue(a_KeyName, a_ValueName, defValue);
return defValue;
}
auto iter = outerIter->second.find(a_ValueName);
if (iter == outerIter->second.end())
{
AddValue(a_KeyName, a_ValueName, defValue);
return defValue;
}
return iter->second.getIntValue();
}
bool cMemorySettingsRepository::GetValueSetB(const AString & a_KeyName, const AString & a_ValueName, const bool defValue)
{
auto outerIter = m_Map.find(a_KeyName);
if (outerIter == m_Map.end())
{
AddValue(a_KeyName, a_ValueName, defValue);
return defValue;
}
auto iter = outerIter->second.find(a_ValueName);
if (iter == outerIter->second.end())
{
AddValue(a_KeyName, a_ValueName, defValue);
return defValue;
}
return iter->second.getBoolValue();
}
bool cMemorySettingsRepository::SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists)
{
if (!m_Writable)
{
return false;
}
auto outerIter = m_Map.find(a_KeyName);
if (outerIter == m_Map.end())
{
if (a_CreateIfNotExists)
{
AddValue(a_KeyName, a_ValueName, a_Value);
}
return a_CreateIfNotExists;
}
auto iter = outerIter->second.find(a_ValueName);
if (iter == outerIter->second.end())
{
if (a_CreateIfNotExists)
{
AddValue(a_KeyName, a_ValueName, a_Value);
}
return a_CreateIfNotExists;
}
iter->second = sValue(a_Value);
return true;
}
bool cMemorySettingsRepository::SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists)
{
if (!m_Writable)
{
return false;
}
auto outerIter = m_Map.find(a_KeyName);
if (outerIter == m_Map.end())
{
if (a_CreateIfNotExists)
{
AddValue(a_KeyName, a_ValueName, static_cast<Int64>(a_Value));
}
return a_CreateIfNotExists;
}
auto iter = outerIter->second.find(a_ValueName);
if (iter == outerIter->second.end())
{
if (a_CreateIfNotExists)
{
AddValue(a_KeyName, a_ValueName, static_cast<Int64>(a_Value));
}
return a_CreateIfNotExists;
}
iter->second = sValue(static_cast<Int64>(a_Value));
return true;
}
bool cMemorySettingsRepository::DeleteValue(const AString & a_KeyName, const AString & a_ValueName)
{
if (!m_Writable)
{
return false;
}
auto outerIter = m_Map.find(a_KeyName);
if (outerIter == m_Map.end())
{
return false;
}
auto iter = outerIter->second.find(a_ValueName);
if (iter == outerIter->second.end())
{
return false;
}
outerIter->second.erase(iter);
return true;
}
bool cMemorySettingsRepository::Flush()
{
return true;
}

View File

@ -0,0 +1,80 @@
#pragma once
#include "SettingsRepositoryInterface.h"
#include <unordered_map>
class cMemorySettingsRepository : public cSettingsRepositoryInterface
{
public:
virtual bool KeyExists(const AString keyname) const override;
virtual bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const override;
virtual int AddKeyName(const AString & keyname) override;
virtual bool AddKeyComment(const AString & keyname, const AString & comment) override;
virtual AString GetKeyComment(const AString & keyname, const int commentID) const override;
virtual bool DeleteKeyComment(const AString & keyname, const int commentID) override;
virtual void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) override;
void AddValue (const AString & a_KeyName, const AString & a_ValueName, const Int64 a_Value);
void AddValue (const AString & a_KeyName, const AString & a_ValueName, const bool a_Value);
virtual std::vector<std::pair<AString, AString>> GetValues(AString a_keyName) override;
virtual AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const override;
virtual AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "") override;
virtual int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0) override;
virtual Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0) override;
virtual bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) override;
virtual bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true) override;
virtual bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true) override;
virtual bool DeleteValue(const AString & keyname, const AString & valuename) override;
virtual bool Flush() override;
void SetReadOnly()
{
m_Writable = false;
}
private:
bool m_Writable = true;
struct sValue
{
sValue(AString value) : m_Type(eType::String), m_stringValue (value) {}
sValue(Int64 value) : m_Type(eType::Int64), m_intValue(value) {}
sValue(bool value) : m_Type(eType::Bool), m_boolValue(value) {}
AString getStringValue() const { ASSERT(m_Type == eType::String); return m_stringValue; }
Int64 getIntValue() const { ASSERT(m_Type == eType::Int64); return m_intValue; }
bool getBoolValue() const { ASSERT(m_Type == eType::Bool); return m_boolValue; }
private:
enum class eType
{
String,
Int64,
Bool
} m_Type;
AString m_stringValue;
union
{
Int64 m_intValue;
bool m_boolValue;
};
};
std::unordered_map<AString, std::unordered_multimap<AString, sValue>> m_Map{};
};

View File

@ -0,0 +1,273 @@
#include "Globals.h"
#include "OverridesSettingsRepository.h"
cOverridesSettingsRepository::cOverridesSettingsRepository(std::unique_ptr<cSettingsRepositoryInterface> a_Main, std::unique_ptr<cSettingsRepositoryInterface> a_Overrides) :
m_Main(std::move(a_Main)),
m_Overrides(std::move(a_Overrides))
{
}
bool cOverridesSettingsRepository::KeyExists(const AString a_keyName) const
{
return m_Overrides->KeyExists(a_keyName) || m_Main->KeyExists(a_keyName);
}
bool cOverridesSettingsRepository::HasValue(const AString & a_KeyName, const AString & a_ValueName) const
{
return m_Overrides->HasValue(a_KeyName, a_ValueName) || m_Main->HasValue(a_KeyName, a_ValueName);
}
int cOverridesSettingsRepository::AddKeyName(const AString & a_keyname)
{
if (m_Overrides->KeyExists(a_keyname))
{
m_Overrides->AddKeyName(a_keyname);
return 0;
}
return m_Main->AddKeyName(a_keyname);
}
bool cOverridesSettingsRepository::AddKeyComment(const AString & a_keyname, const AString & a_comment)
{
if (m_Overrides->KeyExists(a_keyname))
{
return m_Overrides->AddKeyComment(a_keyname, a_comment);
}
return m_Main->AddKeyComment(a_keyname, a_comment);
}
AString cOverridesSettingsRepository::GetKeyComment(const AString & a_keyname, const int a_commentID) const
{
if (m_Overrides->KeyExists(a_keyname))
{
return m_Overrides->GetKeyComment(a_keyname, a_commentID);
}
return m_Main->GetKeyComment(a_keyname, a_commentID);
}
bool cOverridesSettingsRepository::DeleteKeyComment(const AString & a_keyname, const int a_commentID)
{
if (m_Overrides->KeyExists(a_keyname))
{
return m_Overrides->DeleteKeyComment(a_keyname, a_commentID);
}
return m_Main->DeleteKeyComment(a_keyname, a_commentID);
}
void cOverridesSettingsRepository::AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value)
{
if (m_Overrides->HasValue(a_KeyName, a_ValueName))
{
m_Overrides->AddValue(a_KeyName, a_ValueName, a_Value);
}
else
{
m_Main->AddValue(a_KeyName, a_ValueName, a_Value);
}
}
std::vector<std::pair<AString, AString>> cOverridesSettingsRepository::GetValues(AString a_keyName)
{
auto overrides = m_Overrides->GetValues(a_keyName);
auto main = m_Main->GetValues(a_keyName);
std::sort(overrides.begin(), overrides.end(), [](std::pair<AString, AString> a, std::pair<AString, AString> b) -> bool { return a < b ;});
std::sort(main.begin(), main.end(), [](std::pair<AString, AString> a, std::pair<AString, AString> b) -> bool { return a < b ;});
std::vector<std::pair<AString, AString>> ret;
size_t overridesIndex = 0;
for (auto pair : main)
{
if (overridesIndex >= overrides.size())
{
ret.push_back(pair);
continue;
}
if (pair.first == overrides[overridesIndex].first)
{
continue;
}
while (pair.first > overrides[overridesIndex].first)
{
ret.push_back(overrides[overridesIndex]);
overridesIndex++;
}
ret.push_back(pair);
}
return ret;
}
AString cOverridesSettingsRepository::GetValue(const AString & a_KeyName, const AString & a_ValueName, const AString & defValue) const
{
if (m_Overrides->HasValue(a_KeyName, a_ValueName))
{
return m_Overrides->GetValue(a_KeyName, a_ValueName, defValue);
}
else
{
return m_Main->GetValue(a_KeyName, a_ValueName, defValue);
}
}
AString cOverridesSettingsRepository::GetValueSet (const AString & a_KeyName, const AString & a_ValueName, const AString & defValue)
{
if (m_Overrides->HasValue(a_KeyName, a_ValueName))
{
return m_Overrides->GetValueSet(a_KeyName, a_ValueName, defValue);
}
else
{
return m_Main->GetValueSet(a_KeyName, a_ValueName, defValue);
}
}
int cOverridesSettingsRepository::GetValueSetI(const AString & a_KeyName, const AString & a_ValueName, const int defValue)
{
if (m_Overrides->HasValue(a_KeyName, a_ValueName))
{
return m_Overrides->GetValueSetI(a_KeyName, a_ValueName, defValue);
}
else
{
return m_Main->GetValueSetI(a_KeyName, a_ValueName, defValue);
}
}
Int64 cOverridesSettingsRepository::GetValueSetI(const AString & a_KeyName, const AString & a_ValueName, const Int64 defValue)
{
if (m_Overrides->HasValue(a_KeyName, a_ValueName))
{
return m_Overrides->GetValueSetI(a_KeyName, a_ValueName, defValue);
}
else
{
return m_Main->GetValueSetI(a_KeyName, a_ValueName, defValue);
}
}
bool cOverridesSettingsRepository::GetValueSetB(const AString & a_KeyName, const AString & a_ValueName, const bool defValue)
{
if (m_Overrides->HasValue(a_KeyName, a_ValueName))
{
return m_Overrides->GetValueSetB(a_KeyName, a_ValueName, defValue);
}
else
{
return m_Main->GetValueSetB(a_KeyName, a_ValueName, defValue);
}
}
bool cOverridesSettingsRepository::SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists)
{
if (m_Overrides->HasValue(a_KeyName, a_ValueName))
{
return m_Overrides->SetValue(a_KeyName, a_ValueName, a_Value, a_CreateIfNotExists);
}
else
{
return m_Main->SetValue(a_KeyName, a_ValueName, a_Value, a_CreateIfNotExists);
}
}
bool cOverridesSettingsRepository::SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists)
{
if (m_Overrides->HasValue(a_KeyName, a_ValueName))
{
return m_Overrides->SetValueI(a_KeyName, a_ValueName, a_Value, a_CreateIfNotExists);
}
else
{
return m_Main->SetValueI(a_KeyName, a_ValueName, a_Value, a_CreateIfNotExists);
}
}
bool cOverridesSettingsRepository::DeleteValue(const AString & a_KeyName, const AString & a_ValueName)
{
if (m_Overrides->HasValue(a_KeyName, a_ValueName))
{
return m_Overrides->DeleteValue(a_KeyName, a_ValueName);
}
else
{
return m_Overrides->DeleteValue(a_KeyName, a_ValueName);
}
}
bool cOverridesSettingsRepository::Flush()
{
return m_Overrides->Flush() && m_Main->Flush();
}

View File

@ -0,0 +1,52 @@
#pragma once
#include "SettingsRepositoryInterface.h"
#include <unordered_map>
class cOverridesSettingsRepository : public cSettingsRepositoryInterface
{
public:
cOverridesSettingsRepository(std::unique_ptr<cSettingsRepositoryInterface> a_Main, std::unique_ptr<cSettingsRepositoryInterface> a_Overrides);
virtual ~cOverridesSettingsRepository() = default;
virtual bool KeyExists(const AString keyname) const override;
virtual bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const override;
virtual int AddKeyName(const AString & keyname) override;
virtual bool AddKeyComment(const AString & keyname, const AString & comment) override;
virtual AString GetKeyComment(const AString & keyname, const int commentID) const override;
virtual bool DeleteKeyComment(const AString & keyname, const int commentID) override;
virtual void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) override;
virtual std::vector<std::pair<AString, AString>> GetValues(AString a_keyName) override;
virtual AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const override;
virtual AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "") override;
virtual int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0) override;
virtual Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0) override;
virtual bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) override;
virtual bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true) override;
virtual bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true) override;
virtual bool DeleteValue(const AString & keyname, const AString & valuename) override;
virtual bool Flush() override;
private:
std::unique_ptr<cSettingsRepositoryInterface> m_Main;
std::unique_ptr<cSettingsRepositoryInterface> m_Overrides;
};

View File

@ -40,11 +40,11 @@ cAuthenticator::~cAuthenticator()
void cAuthenticator::ReadINI(cIniFile & IniFile) void cAuthenticator::ReadSettings(cSettingsRepositoryInterface & a_Settings)
{ {
m_Server = IniFile.GetValueSet ("Authentication", "Server", DEFAULT_AUTH_SERVER); m_Server = a_Settings.GetValueSet ("Authentication", "Server", DEFAULT_AUTH_SERVER);
m_Address = IniFile.GetValueSet ("Authentication", "Address", DEFAULT_AUTH_ADDRESS); m_Address = a_Settings.GetValueSet ("Authentication", "Address", DEFAULT_AUTH_ADDRESS);
m_ShouldAuthenticate = IniFile.GetValueSetB("Authentication", "Authenticate", true); m_ShouldAuthenticate = a_Settings.GetValueSetB("Authentication", "Authenticate", true);
} }
@ -69,9 +69,9 @@ void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, co
void cAuthenticator::Start(cIniFile & IniFile) void cAuthenticator::Start(cSettingsRepositoryInterface & a_Settings)
{ {
ReadINI(IniFile); ReadSettings(a_Settings);
m_ShouldTerminate = false; m_ShouldTerminate = false;
super::Start(); super::Start();
} }

View File

@ -14,7 +14,7 @@
#include "../OSSupport/IsThread.h" #include "../OSSupport/IsThread.h"
class cSettingsRepositoryInterface;
@ -40,13 +40,13 @@ public:
~cAuthenticator(); ~cAuthenticator();
/** (Re-)read server and address from INI: */ /** (Re-)read server and address from INI: */
void ReadINI(cIniFile & IniFile); void ReadSettings(cSettingsRepositoryInterface & a_Settings);
/** Queues a request for authenticating a user. If the auth fails, the user will be kicked */ /** Queues a request for authenticating a user. If the auth fails, the user will be kicked */
void Authenticate(int a_ClientID, const AString & a_UserName, const AString & a_ServerHash); void Authenticate(int a_ClientID, const AString & a_UserName, const AString & a_ServerHash);
/** Starts the authenticator thread. The thread may be started and stopped repeatedly */ /** Starts the authenticator thread. The thread may be started and stopped repeatedly */
void Start(cIniFile & IniFile); void Start(cSettingsRepositoryInterface & a_Settings);
/** Stops the authenticator thread. The thread may be started and stopped repeatedly */ /** Stops the authenticator thread. The thread may be started and stopped repeatedly */
void Stop(void); void Stop(void);

View File

@ -226,12 +226,12 @@ cMojangAPI::~cMojangAPI()
void cMojangAPI::Start(cIniFile & a_SettingsIni, bool a_ShouldAuth) void cMojangAPI::Start(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth)
{ {
m_NameToUUIDServer = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDServer", DEFAULT_NAME_TO_UUID_SERVER); m_NameToUUIDServer = a_Settings.GetValueSet("MojangAPI", "NameToUUIDServer", DEFAULT_NAME_TO_UUID_SERVER);
m_NameToUUIDAddress = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDAddress", DEFAULT_NAME_TO_UUID_ADDRESS); m_NameToUUIDAddress = a_Settings.GetValueSet("MojangAPI", "NameToUUIDAddress", DEFAULT_NAME_TO_UUID_ADDRESS);
m_UUIDToProfileServer = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileServer", DEFAULT_UUID_TO_PROFILE_SERVER); m_UUIDToProfileServer = a_Settings.GetValueSet("MojangAPI", "UUIDToProfileServer", DEFAULT_UUID_TO_PROFILE_SERVER);
m_UUIDToProfileAddress = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileAddress", DEFAULT_UUID_TO_PROFILE_ADDRESS); m_UUIDToProfileAddress = a_Settings.GetValueSet("MojangAPI", "UUIDToProfileAddress", DEFAULT_UUID_TO_PROFILE_ADDRESS);
LoadCachesFromDisk(); LoadCachesFromDisk();
if (a_ShouldAuth) if (a_ShouldAuth)
{ {

View File

@ -25,7 +25,7 @@ namespace Json
class cSettingsRepositoryInterface;
// tolua_begin // tolua_begin
class cMojangAPI class cMojangAPI
@ -38,7 +38,7 @@ public:
/** Initializes the API; reads the settings from the specified ini file. /** Initializes the API; reads the settings from the specified ini file.
Loads cached results from disk. */ Loads cached results from disk. */
void Start(cIniFile & a_SettingsIni, bool a_ShouldAuth); void Start(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth);
/** Connects to the specified server using SSL, sends the given request and receives the response. /** Connects to the specified server using SSL, sends the given request and receives the response.
Checks Mojang certificates using the hard-coded Starfield root CA certificate. Checks Mojang certificates using the hard-coded Starfield root CA certificate.

View File

@ -134,15 +134,15 @@ cRCONServer::~cRCONServer()
void cRCONServer::Initialize(cIniFile & a_IniFile) void cRCONServer::Initialize(cSettingsRepositoryInterface & a_Settings)
{ {
if (!a_IniFile.GetValueSetB("RCON", "Enabled", false)) if (!a_Settings.GetValueSetB("RCON", "Enabled", false))
{ {
return; return;
} }
// Read the password, don't allow an empty one: // Read the password, don't allow an empty one:
m_Password = a_IniFile.GetValueSet("RCON", "Password", ""); m_Password = a_Settings.GetValueSet("RCON", "Password", "");
if (m_Password.empty()) if (m_Password.empty())
{ {
LOGWARNING("RCON is requested, but the password is not set. RCON is now disabled."); LOGWARNING("RCON is requested, but the password is not set. RCON is now disabled.");
@ -150,7 +150,7 @@ void cRCONServer::Initialize(cIniFile & a_IniFile)
} }
// Read the listening ports for RCON from config: // Read the listening ports for RCON from config:
AStringVector Ports = ReadUpgradeIniPorts(a_IniFile, "RCON", "Ports", "PortsIPv4", "PortsIPv6", "25575"); AStringVector Ports = ReadUpgradeIniPorts(a_Settings, "RCON", "Ports", "PortsIPv4", "PortsIPv6", "25575");
// Start listening on each specified port: // Start listening on each specified port:
for (auto port: Ports) for (auto port: Ports)

View File

@ -17,7 +17,7 @@
// fwd: // fwd:
class cServer; class cServer;
class cIniFile; class cSettingsRepositoryInterface;
@ -29,7 +29,7 @@ public:
cRCONServer(cServer & a_Server); cRCONServer(cServer & a_Server);
virtual ~cRCONServer(); virtual ~cRCONServer();
void Initialize(cIniFile & a_IniFile); void Initialize(cSettingsRepositoryInterface & a_Settings);
protected: protected:
friend class cRCONCommandOutput; friend class cRCONCommandOutput;

View File

@ -19,6 +19,8 @@
#include "LoggerListeners.h" #include "LoggerListeners.h"
#include "BuildInfo.h" #include "BuildInfo.h"
#include "IniFile.h" #include "IniFile.h"
#include "SettingsRepositoryInterface.h"
#include "OverridesSettingsRepository.h"
#ifdef _WIN32 #ifdef _WIN32
#include <conio.h> #include <conio.h>
@ -96,7 +98,7 @@ void cRoot::InputThread(cRoot & a_Params)
void cRoot::Start(void) void cRoot::Start(std::unique_ptr<cSettingsRepositoryInterface> overridesRepo)
{ {
#ifdef _WIN32 #ifdef _WIN32
HWND hwnd = GetConsoleWindow(); HWND hwnd = GetConsoleWindow();
@ -130,22 +132,24 @@ void cRoot::Start(void)
m_Server = new cServer(); m_Server = new cServer();
LOG("Reading server config..."); LOG("Reading server config...");
cIniFile IniFile;
if (!IniFile.ReadFile("settings.ini")) auto IniFile = make_unique<cIniFile>();
if (!IniFile->ReadFile("settings.ini"))
{ {
LOGWARN("Regenerating settings.ini, all settings will be reset"); LOGWARN("Regenerating settings.ini, all settings will be reset");
IniFile.AddHeaderComment(" This is the main server configuration"); IniFile->AddHeaderComment(" This is the main server configuration");
IniFile.AddHeaderComment(" Most of the settings here can be configured using the webadmin interface, if enabled in webadmin.ini"); IniFile->AddHeaderComment(" Most of the settings here can be configured using the webadmin interface, if enabled in webadmin.ini");
IniFile.AddHeaderComment(" See: http://wiki.mc-server.org/doku.php?id=configure:settings.ini for further configuration help"); IniFile->AddHeaderComment(" See: http://wiki.mc-server.org/doku.php?id=configure:settings.ini for further configuration help");
} }
auto settingsRepo = make_unique<cOverridesSettingsRepository>(std::move(IniFile), std::move(overridesRepo));
LOG("Starting server..."); LOG("Starting server...");
m_MojangAPI = new cMojangAPI; m_MojangAPI = new cMojangAPI;
bool ShouldAuthenticate = IniFile.GetValueSetB("Authentication", "Authenticate", true); bool ShouldAuthenticate = settingsRepo->GetValueSetB("Authentication", "Authenticate", true);
m_MojangAPI->Start(IniFile, ShouldAuthenticate); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init m_MojangAPI->Start(*settingsRepo, ShouldAuthenticate); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init
if (!m_Server->InitServer(IniFile, ShouldAuthenticate)) if (!m_Server->InitServer(*settingsRepo, ShouldAuthenticate))
{ {
IniFile.WriteFile("settings.ini"); settingsRepo->Flush();
LOGERROR("Failure starting server, aborting..."); LOGERROR("Failure starting server, aborting...");
return; return;
} }
@ -160,29 +164,29 @@ void cRoot::Start(void)
m_FurnaceRecipe = new cFurnaceRecipe(); m_FurnaceRecipe = new cFurnaceRecipe();
LOGD("Loading worlds..."); LOGD("Loading worlds...");
LoadWorlds(IniFile); LoadWorlds(*settingsRepo);
LOGD("Loading plugin manager..."); LOGD("Loading plugin manager...");
m_PluginManager = new cPluginManager(); m_PluginManager = new cPluginManager();
m_PluginManager->ReloadPluginsNow(IniFile); m_PluginManager->ReloadPluginsNow(*settingsRepo);
LOGD("Loading MonsterConfig..."); LOGD("Loading MonsterConfig...");
m_MonsterConfig = new cMonsterConfig; m_MonsterConfig = new cMonsterConfig;
// This sets stuff in motion // This sets stuff in motion
LOGD("Starting Authenticator..."); LOGD("Starting Authenticator...");
m_Authenticator.Start(IniFile); m_Authenticator.Start(*settingsRepo);
LOGD("Starting worlds..."); LOGD("Starting worlds...");
StartWorlds(); StartWorlds();
if (IniFile.GetValueSetB("DeadlockDetect", "Enabled", true)) if (settingsRepo->GetValueSetB("DeadlockDetect", "Enabled", true))
{ {
LOGD("Starting deadlock detector..."); LOGD("Starting deadlock detector...");
dd.Start(IniFile.GetValueSetI("DeadlockDetect", "IntervalSec", 20)); dd.Start(settingsRepo->GetValueSetI("DeadlockDetect", "IntervalSec", 20));
} }
IniFile.WriteFile("settings.ini"); settingsRepo->Flush();
LOGD("Finalising startup..."); LOGD("Finalising startup...");
if (m_Server->Start()) if (m_Server->Start())
@ -282,30 +286,29 @@ void cRoot::LoadGlobalSettings()
void cRoot::LoadWorlds(cIniFile & IniFile) void cRoot::LoadWorlds(cSettingsRepositoryInterface & a_Settings)
{ {
// First get the default world // First get the default world
AString DefaultWorldName = IniFile.GetValueSet("Worlds", "DefaultWorld", "world"); AString DefaultWorldName = a_Settings.GetValueSet("Worlds", "DefaultWorld", "world");
m_pDefaultWorld = new cWorld(DefaultWorldName.c_str()); m_pDefaultWorld = new cWorld(DefaultWorldName.c_str());
m_WorldsByName[ DefaultWorldName ] = m_pDefaultWorld; m_WorldsByName[ DefaultWorldName ] = m_pDefaultWorld;
// Then load the other worlds // Then load the other worlds
int KeyNum = IniFile.FindKey("Worlds"); auto Worlds = a_Settings.GetValues("Worlds");
int NumWorlds = IniFile.GetNumValues(KeyNum); if (Worlds.size() <= 0)
if (NumWorlds <= 0)
{ {
return; return;
} }
bool FoundAdditionalWorlds = false; bool FoundAdditionalWorlds = false;
for (int i = 0; i < NumWorlds; i++) for (auto WorldNameValue : Worlds)
{ {
AString ValueName = IniFile.GetValueName(KeyNum, i); AString ValueName = WorldNameValue.first;
if (ValueName.compare("World") != 0) if (ValueName.compare("World") != 0)
{ {
continue; continue;
} }
AString WorldName = IniFile.GetValue(KeyNum, i); AString WorldName = WorldNameValue.second;
if (WorldName.empty()) if (WorldName.empty())
{ {
continue; continue;
@ -317,10 +320,10 @@ void cRoot::LoadWorlds(cIniFile & IniFile)
if (!FoundAdditionalWorlds) if (!FoundAdditionalWorlds)
{ {
if (IniFile.GetKeyComment("Worlds", 0) != " World=secondworld") if (a_Settings.GetKeyComment("Worlds", 0) != " World=secondworld")
{ {
IniFile.DeleteKeyComment("Worlds", 0); a_Settings.DeleteKeyComment("Worlds", 0);
IniFile.AddKeyComment("Worlds", " World=secondworld"); a_Settings.AddKeyComment("Worlds", " World=secondworld");
} }
} }
} }

View File

@ -24,6 +24,7 @@ class cWorld;
class cPlayer; class cPlayer;
class cCommandOutputCallback; class cCommandOutputCallback;
class cCompositeChat; class cCompositeChat;
class cSettingsRepositoryInterface;
typedef cItemCallback<cPlayer> cPlayerListCallback; typedef cItemCallback<cPlayer> cPlayerListCallback;
typedef cItemCallback<cWorld> cWorldListCallback; typedef cItemCallback<cWorld> cWorldListCallback;
@ -53,7 +54,7 @@ public:
cRoot(void); cRoot(void);
~cRoot(); ~cRoot();
void Start(void); void Start(std::unique_ptr<cSettingsRepositoryInterface> overridesRepo);
// tolua_begin // tolua_begin
cServer * GetServer(void) { return m_Server; } cServer * GetServer(void) { return m_Server; }
@ -204,7 +205,7 @@ private:
void LoadGlobalSettings(); void LoadGlobalSettings();
/// Loads the worlds from settings.ini, creates the worldmap /// Loads the worlds from settings.ini, creates the worldmap
void LoadWorlds(cIniFile & IniFile); void LoadWorlds(cSettingsRepositoryInterface & a_Settings);
/// Starts each world's life /// Starts each world's life
void StartWorlds(void); void StartWorlds(void);

View File

@ -185,12 +185,12 @@ void cServer::PlayerDestroying(const cPlayer * a_Player)
bool cServer::InitServer(cIniFile & a_SettingsIni, bool a_ShouldAuth) bool cServer::InitServer(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth)
{ {
m_Description = a_SettingsIni.GetValueSet("Server", "Description", "MCServer - in C++!"); m_Description = a_Settings.GetValueSet("Server", "Description", "MCServer - in C++!");
m_MaxPlayers = a_SettingsIni.GetValueSetI("Server", "MaxPlayers", 100); m_MaxPlayers = a_Settings.GetValueSetI("Server", "MaxPlayers", 100);
m_bIsHardcore = a_SettingsIni.GetValueSetB("Server", "HardcoreEnabled", false); m_bIsHardcore = a_Settings.GetValueSetB("Server", "HardcoreEnabled", false);
m_bAllowMultiLogin = a_SettingsIni.GetValueSetB("Server", "AllowMultiLogin", false); m_bAllowMultiLogin = a_Settings.GetValueSetB("Server", "AllowMultiLogin", false);
m_PlayerCount = 0; m_PlayerCount = 0;
m_PlayerCountDiff = 0; m_PlayerCountDiff = 0;
@ -205,9 +205,9 @@ bool cServer::InitServer(cIniFile & a_SettingsIni, bool a_ShouldAuth)
LOGINFO("Compatible clients: %s", MCS_CLIENT_VERSIONS); LOGINFO("Compatible clients: %s", MCS_CLIENT_VERSIONS);
LOGINFO("Compatible protocol versions %s", MCS_PROTOCOL_VERSIONS); LOGINFO("Compatible protocol versions %s", MCS_PROTOCOL_VERSIONS);
m_Ports = ReadUpgradeIniPorts(a_SettingsIni, "Server", "Ports", "Port", "PortsIPv6", "25565"); m_Ports = ReadUpgradeIniPorts(a_Settings, "Server", "Ports", "Port", "PortsIPv6", "25565");
m_RCONServer.Initialize(a_SettingsIni); m_RCONServer.Initialize(a_Settings);
m_bIsConnected = true; m_bIsConnected = true;
@ -226,16 +226,16 @@ bool cServer::InitServer(cIniFile & a_SettingsIni, bool a_ShouldAuth)
} }
// Check if both BungeeCord and online mode are on, if so, warn the admin: // Check if both BungeeCord and online mode are on, if so, warn the admin:
m_ShouldAllowBungeeCord = a_SettingsIni.GetValueSetB("Authentication", "AllowBungeeCord", false); m_ShouldAllowBungeeCord = a_Settings.GetValueSetB("Authentication", "AllowBungeeCord", false);
if (m_ShouldAllowBungeeCord && m_ShouldAuthenticate) if (m_ShouldAllowBungeeCord && m_ShouldAuthenticate)
{ {
LOGWARNING("WARNING: BungeeCord is allowed and server set to online mode. This is unsafe and will not work properly. Disable either authentication or BungeeCord in settings.ini."); LOGWARNING("WARNING: BungeeCord is allowed and server set to online mode. This is unsafe and will not work properly. Disable either authentication or BungeeCord in settings.ini.");
} }
m_ShouldLoadOfflinePlayerData = a_SettingsIni.GetValueSetB("PlayerData", "LoadOfflinePlayerData", false); m_ShouldLoadOfflinePlayerData = a_Settings.GetValueSetB("PlayerData", "LoadOfflinePlayerData", false);
m_ShouldLoadNamedPlayerData = a_SettingsIni.GetValueSetB("PlayerData", "LoadNamedPlayerData", true); m_ShouldLoadNamedPlayerData = a_Settings.GetValueSetB("PlayerData", "LoadNamedPlayerData", true);
m_ClientViewDistance = a_SettingsIni.GetValueSetI("Server", "DefaultViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE); m_ClientViewDistance = a_Settings.GetValueSetI("Server", "DefaultViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE);
if (m_ClientViewDistance < cClientHandle::MIN_VIEW_DISTANCE) if (m_ClientViewDistance < cClientHandle::MIN_VIEW_DISTANCE)
{ {
m_ClientViewDistance = cClientHandle::MIN_VIEW_DISTANCE; m_ClientViewDistance = cClientHandle::MIN_VIEW_DISTANCE;

View File

@ -38,8 +38,8 @@ class cClientHandle;
typedef SharedPtr<cClientHandle> cClientHandlePtr; typedef SharedPtr<cClientHandle> cClientHandlePtr;
typedef std::list<cClientHandlePtr> cClientHandlePtrs; typedef std::list<cClientHandlePtr> cClientHandlePtrs;
typedef std::list<cClientHandle *> cClientHandles; typedef std::list<cClientHandle *> cClientHandles;
class cIniFile;
class cCommandOutputCallback; class cCommandOutputCallback;
class cSettingsRepositoryInterface;
namespace Json namespace Json
@ -58,7 +58,7 @@ public:
// tolua_end // tolua_end
virtual ~cServer() {} virtual ~cServer() {}
bool InitServer(cIniFile & a_SettingsIni, bool a_ShouldAuth); bool InitServer(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth);
// tolua_begin // tolua_begin

View File

@ -0,0 +1,46 @@
#pragma once
class cSettingsRepositoryInterface
{
public:
enum errors
{
noID = -1,
};
virtual ~cSettingsRepositoryInterface() = default;
virtual bool KeyExists(const AString keyname) const = 0;
virtual bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const = 0;
virtual int AddKeyName(const AString & keyname) = 0;
virtual bool AddKeyComment(const AString & keyname, const AString & comment) = 0;
virtual AString GetKeyComment(const AString & keyname, const int commentID) const = 0;
virtual bool DeleteKeyComment(const AString & keyname, const int commentID) = 0;
virtual void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) = 0;
virtual std::vector<std::pair<AString, AString>> GetValues(AString a_keyName) = 0;
virtual AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const = 0;
virtual AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "") = 0;
virtual int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0) = 0;
virtual Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0) = 0;
virtual bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) = 0;
virtual bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true) = 0;
virtual bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true) = 0;
virtual bool DeleteValue(const AString & keyname, const AString & valuename) = 0;
virtual bool Flush() = 0;
};

View File

@ -2,6 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Root.h" #include "Root.h"
#include "tclap/CmdLine.h"
#include <exception> #include <exception>
#include <csignal> #include <csignal>
@ -14,7 +15,7 @@
#include "OSSupport/NetworkSingleton.h" #include "OSSupport/NetworkSingleton.h"
#include "BuildInfo.h" #include "BuildInfo.h"
#include "MemorySettingsRepository.h"
@ -206,7 +207,7 @@ BOOL CtrlHandler(DWORD fdwCtrlType)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// universalMain - Main startup logic for both standard running and as a service // universalMain - Main startup logic for both standard running and as a service
void universalMain() void universalMain(std::unique_ptr<cSettingsRepositoryInterface> overridesRepo)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE)) if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE))
@ -226,7 +227,7 @@ void universalMain()
#endif #endif
{ {
cRoot Root; cRoot Root;
Root.Start(); Root.Start(std::move(overridesRepo));
} }
#if !defined(ANDROID_NDK) #if !defined(ANDROID_NDK)
catch (std::exception & e) catch (std::exception & e)
@ -363,14 +364,39 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
std::unique_ptr<cMemorySettingsRepository> parseArguments(int argc, char **argv)
{
try
{
TCLAP::CmdLine cmd("MCServer");
TCLAP::ValueArg<int> slotsArg("s", "max-players", "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd);
cmd.parse(argc, argv);
int slots = slotsArg.getValue();
auto repo = make_unique<cMemorySettingsRepository>();
repo->SetValueI("Server", "MaxPlayers", slots);
repo->SetReadOnly();
return repo;
}
catch (TCLAP::ArgException &e)
{
printf("error reading command line %s for arg %s", e.error().c_str(), e.argId().c_str());
return nullptr;
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// main: // main:
int main( int argc, char **argv) int main(int argc, char **argv)
{ {
UNUSED(argc);
UNUSED(argv);
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER) #if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
InitLeakFinder(); InitLeakFinder();
@ -425,6 +451,8 @@ int main( int argc, char **argv)
// DEBUG: test the dumpfile creation: // DEBUG: test the dumpfile creation:
// *((int *)0) = 0; // *((int *)0) = 0;
auto argsRepo = parseArguments(argc, argv);
// Check if comm logging is to be enabled: // Check if comm logging is to be enabled:
for (int i = 0; i < argc; i++) for (int i = 0; i < argc; i++)
{ {
@ -483,7 +511,7 @@ int main( int argc, char **argv)
#endif #endif
{ {
// Not running as a service, do normal startup // Not running as a service, do normal startup
universalMain(); universalMain(std::move(argsRepo));
} }
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER) #if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)