Initial implementation of IniFile overloading
This commit is contained in:
parent
da58620d45
commit
b9efa02c80
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
312
src/MemorySettingsRepository.cpp
Normal file
312
src/MemorySettingsRepository.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
80
src/MemorySettingsRepository.h
Normal file
80
src/MemorySettingsRepository.h
Normal 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{};
|
||||||
|
};
|
||||||
|
|
273
src/OverridesSettingsRepository.cpp
Normal file
273
src/OverridesSettingsRepository.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
|
52
src/OverridesSettingsRepository.h
Normal file
52
src/OverridesSettingsRepository.h
Normal 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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
57
src/Root.cpp
57
src/Root.cpp
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
46
src/SettingsRepositoryInterface.h
Normal file
46
src/SettingsRepositoryInterface.h
Normal 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;
|
||||||
|
};
|
42
src/main.cpp
42
src/main.cpp
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user