Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
ac1bfd9671
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -28,3 +28,6 @@
|
|||||||
[submodule "lib/libevent"]
|
[submodule "lib/libevent"]
|
||||||
path = lib/libevent
|
path = lib/libevent
|
||||||
url = https://github.com/mc-server/libevent.git
|
url = https://github.com/mc-server/libevent.git
|
||||||
|
[submodule "lib/TCLAP"]
|
||||||
|
path = lib/TCLAP
|
||||||
|
url = https://github.com/mc-server/TCLAP.git
|
||||||
|
@ -7,6 +7,7 @@ Diusrex
|
|||||||
Duralex
|
Duralex
|
||||||
FakeTruth (founder)
|
FakeTruth (founder)
|
||||||
Howaner
|
Howaner
|
||||||
|
jasperarmstrong
|
||||||
keyboard
|
keyboard
|
||||||
Lapayo
|
Lapayo
|
||||||
Luksor
|
Luksor
|
||||||
|
29
MCServer/Plugins/APIDump/Hooks/OnEntityChangeWorld.lua
Normal file
29
MCServer/Plugins/APIDump/Hooks/OnEntityChangeWorld.lua
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
return
|
||||||
|
{
|
||||||
|
HOOK_ENTITY_CHANGE_WORLD =
|
||||||
|
{
|
||||||
|
CalledWhen = "Before a entity is changing the world.",
|
||||||
|
DefaultFnName = "OnEntityChangeWorld", -- also used as pagename
|
||||||
|
Desc = [[
|
||||||
|
This hook is called before the server moves the {{cEntity|entity}} to the given world. Plugins may
|
||||||
|
refuse the changing of the entity to the new world.<p>
|
||||||
|
See also the {{OnEntityChangedWorld|HOOK_ENTITY_CHANGED_WORLD}} hook for a similar hook is called after the
|
||||||
|
entity has been moved to the world.
|
||||||
|
]],
|
||||||
|
Params =
|
||||||
|
{
|
||||||
|
{ Name = "Entity", Type = "{{cEntity}}", Notes = "The entity that wants to change the world" },
|
||||||
|
{ Name = "World", Type = "{{cWorld}}", Notes = "The world to which the entity wants to change" },
|
||||||
|
},
|
||||||
|
Returns = [[
|
||||||
|
If the function returns false or no value, the next plugin's callback is called. If the function
|
||||||
|
returns true, no other callback is called for this event and the change of the entity to the world is
|
||||||
|
cancelled.
|
||||||
|
]],
|
||||||
|
}, -- HOOK_ENTITY_CHANGE_WORLD
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
28
MCServer/Plugins/APIDump/Hooks/OnEntityChangedWorld.lua
Normal file
28
MCServer/Plugins/APIDump/Hooks/OnEntityChangedWorld.lua
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
return
|
||||||
|
{
|
||||||
|
HOOK_ENTITY_CHANGED_WORLD =
|
||||||
|
{
|
||||||
|
CalledWhen = "After a entity has changed the world.",
|
||||||
|
DefaultFnName = "OnEntityChangedWorld", -- also used as pagename
|
||||||
|
Desc = [[
|
||||||
|
This hook is called after the server has moved the {{cEntity|entity}} to the given world. This is an information-only
|
||||||
|
callback, the entity is already in the new world.<p>
|
||||||
|
See also the {{OnEntityChangeWorld|HOOK_ENTITY_CHANGE_WORLD}} hook for a similar hook called before the
|
||||||
|
entity is moved to the new world.
|
||||||
|
]],
|
||||||
|
Params =
|
||||||
|
{
|
||||||
|
{ Name = "Entity", Type = "{{cEntity}}", Notes = "The entity that has changed the world" },
|
||||||
|
{ Name = "World", Type = "{{cWorld}}", Notes = "The world from which the entity has come" },
|
||||||
|
},
|
||||||
|
Returns = [[
|
||||||
|
If the function returns false or no value, the next plugin's callback is called. If the function
|
||||||
|
returns true, no other callback is called for this event.
|
||||||
|
]],
|
||||||
|
}, -- HOOK_ENTITY_CHANGED_WORLD
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1 +1 @@
|
|||||||
Subproject commit ea0ab964d568630fd4f2b52954186f2851a769e1
|
Subproject commit 5171b43807ff699a6b239ad4969520730b3748a2
|
@ -36,9 +36,7 @@ Check out the [CONTRIBUTING.md](https://github.com/mc-server/MCServer/blob/maste
|
|||||||
Other Stuff
|
Other Stuff
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
For other stuff, including plugins and discussion, check the [forums](http://forum.mc-server.org) and [Plugin API](http://mc-server.xoft.cz/LuaAPI/).
|
For other stuff, including plugins and discussion, check out the [forums](http://forum.mc-server.org) and [Plugin API](http://mc-server.xoft.cz/LuaAPI/).
|
||||||
|
|
||||||
Earn bitcoins for commits or donate to reward the MCServer developers: [![tip for next commit](http://tip4commit.com/projects/74.svg)](http://tip4commit.com/projects/74)
|
|
||||||
|
|
||||||
Support Us on Gratipay: [![Support via Gratipay](http://img.shields.io/gittip/cuberite_team.svg)](https://www.gratipay.com/cuberite_team)
|
Support Us on Gratipay: [![Support via Gratipay](http://img.shields.io/gittip/cuberite_team.svg)](https://www.gratipay.com/cuberite_team)
|
||||||
|
|
||||||
|
1
lib/TCLAP
Submodule
1
lib/TCLAP
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 12cee38782897cfe60a1611615c200c45cd99eaf
|
@ -56,6 +56,8 @@ public:
|
|||||||
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) = 0;
|
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) = 0;
|
||||||
virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) = 0;
|
virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) = 0;
|
||||||
virtual bool OnEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) = 0;
|
virtual bool OnEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) = 0;
|
||||||
|
virtual bool OnEntityChangeWorld (cEntity & a_Entity, cWorld & a_World) = 0;
|
||||||
|
virtual bool OnEntityChangedWorld (cEntity & a_Entity, cWorld & a_World) = 0;
|
||||||
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) = 0;
|
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) = 0;
|
||||||
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
|
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
|
||||||
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
|
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
|
||||||
|
@ -534,6 +534,54 @@ bool cPluginLua::OnEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_E
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPluginLua::OnEntityChangeWorld(cEntity & a_Entity, cWorld & a_World)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CriticalSection);
|
||||||
|
if (!m_LuaState.IsValid())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool res = false;
|
||||||
|
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_ENTITY_CHANGE_WORLD];
|
||||||
|
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
m_LuaState.Call((int)(**itr), &a_Entity, &a_World, cLuaState::Return, res);
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPluginLua::OnEntityChangedWorld(cEntity & a_Entity, cWorld & a_World)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CriticalSection);
|
||||||
|
if (!m_LuaState.IsValid())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool res = false;
|
||||||
|
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_ENTITY_CHANGED_WORLD];
|
||||||
|
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
m_LuaState.Call((int)(**itr), &a_Entity, &a_World, res);
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result)
|
bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CriticalSection);
|
cCSLock Lock(m_CriticalSection);
|
||||||
@ -1884,6 +1932,8 @@ const char * cPluginLua::GetHookFnName(int a_HookType)
|
|||||||
case cPluginManager::HOOK_DISCONNECT: return "OnDisconnect";
|
case cPluginManager::HOOK_DISCONNECT: return "OnDisconnect";
|
||||||
case cPluginManager::HOOK_PLAYER_ANIMATION: return "OnPlayerAnimation";
|
case cPluginManager::HOOK_PLAYER_ANIMATION: return "OnPlayerAnimation";
|
||||||
case cPluginManager::HOOK_ENTITY_ADD_EFFECT: return "OnEntityAddEffect";
|
case cPluginManager::HOOK_ENTITY_ADD_EFFECT: return "OnEntityAddEffect";
|
||||||
|
case cPluginManager::HOOK_ENTITY_CHANGE_WORLD: return "OnEntityChangeWorld";
|
||||||
|
case cPluginManager::HOOK_ENTITY_CHANGED_WORLD: return "OnEntityChangedWorld";
|
||||||
case cPluginManager::HOOK_ENTITY_TELEPORT: return "OnEntityTeleport";
|
case cPluginManager::HOOK_ENTITY_TELEPORT: return "OnEntityTeleport";
|
||||||
case cPluginManager::HOOK_EXECUTE_COMMAND: return "OnExecuteCommand";
|
case cPluginManager::HOOK_EXECUTE_COMMAND: return "OnExecuteCommand";
|
||||||
case cPluginManager::HOOK_HANDSHAKE: return "OnHandshake";
|
case cPluginManager::HOOK_HANDSHAKE: return "OnHandshake";
|
||||||
|
@ -115,6 +115,8 @@ public:
|
|||||||
virtual bool OnCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) override;
|
virtual bool OnCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) override;
|
||||||
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) override;
|
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) override;
|
||||||
virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) override;
|
virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) override;
|
||||||
|
virtual bool OnEntityChangeWorld (cEntity & a_Entity, cWorld & a_World) override;
|
||||||
|
virtual bool OnEntityChangedWorld (cEntity & a_Entity, cWorld & a_World) override;
|
||||||
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) override;
|
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) override;
|
||||||
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
|
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
|
||||||
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
|
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -525,6 +525,42 @@ bool cPluginManager::CallHookEntityTeleport(cEntity & a_Entity, const Vector3d &
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPluginManager::CallHookEntityChangeWorld(cEntity & a_Entity, cWorld & a_World)
|
||||||
|
{
|
||||||
|
FIND_HOOK(HOOK_ENTITY_CHANGE_WORLD);
|
||||||
|
VERIFY_HOOK;
|
||||||
|
|
||||||
|
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
|
||||||
|
{
|
||||||
|
if ((*itr)->OnEntityChangeWorld(a_Entity, a_World))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPluginManager::CallHookEntityChangedWorld(cEntity & a_Entity, cWorld & a_World)
|
||||||
|
{
|
||||||
|
FIND_HOOK(HOOK_ENTITY_CHANGED_WORLD);
|
||||||
|
VERIFY_HOOK;
|
||||||
|
|
||||||
|
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
|
||||||
|
{
|
||||||
|
if ((*itr)->OnEntityChangedWorld(a_Entity, a_World))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::CallHookExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result)
|
bool cPluginManager::CallHookExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result)
|
||||||
{
|
{
|
||||||
FIND_HOOK(HOOK_EXECUTE_COMMAND);
|
FIND_HOOK(HOOK_EXECUTE_COMMAND);
|
||||||
@ -1896,25 +1932,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;
|
||||||
@ -85,6 +86,8 @@ public:
|
|||||||
HOOK_DISCONNECT,
|
HOOK_DISCONNECT,
|
||||||
HOOK_PLAYER_ANIMATION,
|
HOOK_PLAYER_ANIMATION,
|
||||||
HOOK_ENTITY_ADD_EFFECT,
|
HOOK_ENTITY_ADD_EFFECT,
|
||||||
|
HOOK_ENTITY_CHANGE_WORLD,
|
||||||
|
HOOK_ENTITY_CHANGED_WORLD,
|
||||||
HOOK_EXECUTE_COMMAND,
|
HOOK_EXECUTE_COMMAND,
|
||||||
HOOK_EXPLODED,
|
HOOK_EXPLODED,
|
||||||
HOOK_EXPLODING,
|
HOOK_EXPLODING,
|
||||||
@ -200,6 +203,8 @@ public:
|
|||||||
bool CallHookDisconnect (cClientHandle & a_Client, const AString & a_Reason);
|
bool CallHookDisconnect (cClientHandle & a_Client, const AString & a_Reason);
|
||||||
bool CallHookEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier);
|
bool CallHookEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier);
|
||||||
bool CallHookEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition);
|
bool CallHookEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition);
|
||||||
|
bool CallHookEntityChangeWorld (cEntity & a_Entity, cWorld & a_World);
|
||||||
|
bool CallHookEntityChangedWorld (cEntity & a_Entity, cWorld & a_World);
|
||||||
bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result); // If a_Player == nullptr, it is a console cmd
|
bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result); // If a_Player == nullptr, it is a console cmd
|
||||||
bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
|
bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
|
||||||
bool CallHookExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
|
bool CallHookExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
|
||||||
@ -364,20 +369,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
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,22 +40,34 @@ public:
|
|||||||
{
|
{
|
||||||
cFastRandom rand;
|
cFastRandom rand;
|
||||||
|
|
||||||
// Old leaves - 3 bits contain display; new leaves - 1st bit, shifted left two for saplings to understand
|
// There is a chance to drop a sapling that varies depending on the type of leaf broken.
|
||||||
if (rand.NextInt(20) == 0)
|
// TODO: Take into account fortune for sapling drops.
|
||||||
|
int chance;
|
||||||
|
if ((m_BlockType == E_BLOCK_LEAVES) && ((a_BlockMeta & 0x03) == E_META_LEAVES_JUNGLE))
|
||||||
|
{
|
||||||
|
// Jungle leaves have a 2.5% chance of dropping a sapling.
|
||||||
|
chance = rand.NextInt(40);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Other leaves have a 5% chance of dropping a sapling.
|
||||||
|
chance = rand.NextInt(20);
|
||||||
|
}
|
||||||
|
if (chance == 0)
|
||||||
{
|
{
|
||||||
a_Pickups.push_back(
|
a_Pickups.push_back(
|
||||||
cItem(
|
cItem(
|
||||||
E_BLOCK_SAPLING,
|
E_BLOCK_SAPLING,
|
||||||
1,
|
1,
|
||||||
(m_BlockType == E_BLOCK_LEAVES) ? (a_BlockMeta & 0x03) : (2 << (a_BlockMeta & 0x01))
|
(m_BlockType == E_BLOCK_LEAVES) ? (a_BlockMeta & 0x03) : (4 + (a_BlockMeta & 0x01))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1 % chance of dropping an apple, if the leaves' type is Apple Leaves
|
// 0.5 % chance of dropping an apple, if the leaves' type is Apple Leaves
|
||||||
if ((m_BlockType == E_BLOCK_LEAVES) && ((a_BlockMeta & 0x03) == E_META_LEAVES_APPLE))
|
if ((m_BlockType == E_BLOCK_LEAVES) && ((a_BlockMeta & 0x03) == E_META_LEAVES_APPLE))
|
||||||
{
|
{
|
||||||
if (rand.NextInt(101) == 0)
|
if (rand.NextInt(200) == 0)
|
||||||
{
|
{
|
||||||
a_Pickups.push_back(cItem(E_ITEM_RED_APPLE, 1, 0));
|
a_Pickups.push_back(cItem(E_ITEM_RED_APPLE, 1, 0));
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
@ -1403,14 +1403,25 @@ bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ask the plugins if the entity is allowed to change the world
|
||||||
|
if (cRoot::Get()->GetPluginManager()->CallHookEntityChangeWorld(*this, *a_World))
|
||||||
|
{
|
||||||
|
// A Plugin doesn't allow the entity to change the world
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove all links to the old world
|
// Remove all links to the old world
|
||||||
SetWorldTravellingFrom(GetWorld()); // cChunk::Tick() handles entity removal
|
SetWorldTravellingFrom(GetWorld()); // cChunk::Tick() handles entity removal
|
||||||
GetWorld()->BroadcastDestroyEntity(*this);
|
GetWorld()->BroadcastDestroyEntity(*this);
|
||||||
|
|
||||||
// Queue add to new world
|
// Queue add to new world
|
||||||
a_World->AddEntity(this);
|
a_World->AddEntity(this);
|
||||||
|
cWorld * OldWorld = cRoot::Get()->GetWorld(GetWorld()->GetName()); // Required for the hook HOOK_ENTITY_CHANGED_WORLD
|
||||||
SetWorld(a_World);
|
SetWorld(a_World);
|
||||||
|
|
||||||
|
// Entity changed the world, call the hook
|
||||||
|
cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, *OldWorld);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1606,6 +1606,12 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cRoot::Get()->GetPluginManager()->CallHookEntityChangeWorld(*this, *a_World))
|
||||||
|
{
|
||||||
|
// A Plugin doesn't allow the player to change the world
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Send the respawn packet:
|
// Send the respawn packet:
|
||||||
if (a_ShouldSendRespawn && (m_ClientHandle != nullptr))
|
if (a_ShouldSendRespawn && (m_ClientHandle != nullptr))
|
||||||
{
|
{
|
||||||
@ -1621,6 +1627,7 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
|
|||||||
|
|
||||||
// Queue adding player to the new world, including all the necessary adjustments to the object
|
// Queue adding player to the new world, including all the necessary adjustments to the object
|
||||||
a_World->AddPlayer(this);
|
a_World->AddPlayer(this);
|
||||||
|
cWorld * OldWorld = cRoot::Get()->GetWorld(GetWorld()->GetName()); // Required for the hook HOOK_ENTITY_CHANGED_WORLD
|
||||||
SetWorld(a_World); // Chunks may be streamed before cWorld::AddPlayer() sets the world to the new value
|
SetWorld(a_World); // Chunks may be streamed before cWorld::AddPlayer() sets the world to the new value
|
||||||
|
|
||||||
// Update the view distance.
|
// Update the view distance.
|
||||||
@ -1635,6 +1642,9 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
|
|||||||
// Broadcast the player into the new world.
|
// Broadcast the player into the new world.
|
||||||
a_World->BroadcastSpawnEntity(*this);
|
a_World->BroadcastSpawnEntity(*this);
|
||||||
|
|
||||||
|
// Player changed the world, call the hook
|
||||||
|
cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, *OldWorld);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1274,6 +1274,7 @@ bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX
|
|||||||
double AnimalZ = static_cast<double>(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ + 0.5);
|
double AnimalZ = static_cast<double>(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ + 0.5);
|
||||||
|
|
||||||
cMonster * NewMob = cMonster::NewMonsterFromType(AnimalToSpawn);
|
cMonster * NewMob = cMonster::NewMonsterFromType(AnimalToSpawn);
|
||||||
|
NewMob->SetHealth(NewMob->GetMaxHealth());
|
||||||
NewMob->SetPosition(AnimalX, AnimalY, AnimalZ);
|
NewMob->SetPosition(AnimalX, AnimalY, AnimalZ);
|
||||||
a_ChunkDesc.GetEntities().push_back(NewMob);
|
a_ChunkDesc.GetEntities().push_back(NewMob);
|
||||||
LOGD("Spawning %s #%i at {%.02f, %.02f, %.02f}", NewMob->GetClass(), NewMob->GetUniqueID(), AnimalX, AnimalY, AnimalZ);
|
LOGD("Spawning %s #%i at {%.02f, %.02f, %.02f}", NewMob->GetClass(), NewMob->GetUniqueID(), AnimalX, AnimalY, AnimalZ);
|
||||||
|
@ -433,10 +433,14 @@ typename std::enable_if<std::is_arithmetic<T>::value, C>::type CeilC(T a_Value)
|
|||||||
|
|
||||||
|
|
||||||
//temporary replacement for std::make_unique until we get c++14
|
//temporary replacement for std::make_unique until we get c++14
|
||||||
template <class T, class... Args>
|
|
||||||
std::unique_ptr<T> make_unique(Args&&... args)
|
namespace cpp14
|
||||||
{
|
{
|
||||||
return std::unique_ptr<T>(new T(args...));
|
template <class T, class... Args>
|
||||||
|
std::unique_ptr<T> make_unique(Args&&... 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;
|
||||||
@ -57,6 +60,7 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect)
|
|||||||
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,34 @@ 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;
|
||||||
|
|
||||||
|
for (auto pair : a_Settings.GetValues(a_KeyName))
|
||||||
|
{
|
||||||
|
if (pair.first != a_PortsValueName)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AStringVector temp = StringSplitAndTrim(pair.second, ";,");
|
||||||
|
Ports.insert(Ports.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
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 +966,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,11 +30,13 @@
|
|||||||
|
|
||||||
// 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
|
||||||
{
|
{
|
||||||
std::vector<AString> names;
|
std::vector<AString> names;
|
||||||
@ -54,14 +56,18 @@ private:
|
|||||||
|
|
||||||
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{};
|
||||||
|
};
|
||||||
|
|
@ -519,7 +519,7 @@ void cMonster::SetPitchAndYawFromDestination()
|
|||||||
double HeadRotation, HeadPitch;
|
double HeadRotation, HeadPitch;
|
||||||
Distance.Normalize();
|
Distance.Normalize();
|
||||||
VectorToEuler(Distance.x, Distance.y, Distance.z, HeadRotation, HeadPitch);
|
VectorToEuler(Distance.x, Distance.y, Distance.z, HeadRotation, HeadPitch);
|
||||||
if (abs(BodyRotation - HeadRotation) < 120)
|
if (std::abs(BodyRotation - HeadRotation) < 120)
|
||||||
{
|
{
|
||||||
SetHeadYaw(HeadRotation);
|
SetHeadYaw(HeadRotation);
|
||||||
SetPitch(-HeadPitch);
|
SetPitch(-HeadPitch);
|
||||||
|
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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -152,7 +152,7 @@ void cSslContext::SetCACerts(const cX509CertPtr & a_CACert, const AString & a_Ex
|
|||||||
m_CACerts = a_CACert;
|
m_CACerts = a_CACert;
|
||||||
|
|
||||||
// Set the trusted CA root cert store:
|
// Set the trusted CA root cert store:
|
||||||
ssl_set_authmode(&m_Ssl, SSL_VERIFY_REQUIRED);
|
ssl_set_authmode(&m_Ssl, SSL_VERIFY_OPTIONAL);
|
||||||
ssl_set_ca_chain(&m_Ssl, m_CACerts->GetInternal(), nullptr, m_ExpectedPeerName.empty() ? nullptr : m_ExpectedPeerName.c_str());
|
ssl_set_ca_chain(&m_Ssl, m_CACerts->GetInternal(), nullptr, m_ExpectedPeerName.empty() ? nullptr : m_ExpectedPeerName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 = cpp14::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 = cpp14::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
|
||||||
|
|
||||||
|
61
src/SettingsRepositoryInterface.h
Normal file
61
src/SettingsRepositoryInterface.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class cSettingsRepositoryInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum errors
|
||||||
|
{
|
||||||
|
noID = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~cSettingsRepositoryInterface() = default;
|
||||||
|
|
||||||
|
/** Returns true iff the specified key exists */
|
||||||
|
virtual bool KeyExists(const AString keyname) const = 0;
|
||||||
|
|
||||||
|
/** Returns true iff the specified value exists. */
|
||||||
|
virtual bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const = 0;
|
||||||
|
|
||||||
|
/** Add a key name. Return value is not required to mean anything **/
|
||||||
|
virtual int AddKeyName(const AString & keyname) = 0;
|
||||||
|
|
||||||
|
/** Add a key comment, will always fail if the repository does not support comments **/
|
||||||
|
virtual bool AddKeyComment(const AString & keyname, const AString & comment) = 0;
|
||||||
|
|
||||||
|
/** Return a key comment, returns "" for repositories that do not return comments **/
|
||||||
|
virtual AString GetKeyComment(const AString & keyname, const int commentID) const = 0;
|
||||||
|
|
||||||
|
/** Delete a key comment, will always fail if the repository does not support comments **/
|
||||||
|
virtual bool DeleteKeyComment(const AString & keyname, const int commentID) = 0;
|
||||||
|
|
||||||
|
/** Adds a new value to the specified key.
|
||||||
|
If a value of the same name already exists, creates another one **/
|
||||||
|
virtual void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) = 0;
|
||||||
|
|
||||||
|
/** returns a vector containing a name, value pair for each value under the key **/
|
||||||
|
virtual std::vector<std::pair<AString, AString>> GetValues(AString a_keyName) = 0;
|
||||||
|
|
||||||
|
/** Get the value at the specified key and value, returns defValue on failure **/
|
||||||
|
virtual AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const = 0;
|
||||||
|
|
||||||
|
/** Gets the value; if not found, write the default to the repository **/
|
||||||
|
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;
|
||||||
|
|
||||||
|
/** Overwrites the value of the key, value pair
|
||||||
|
Specify the optional parameter as false if you do not want the value created if it doesn't exist.
|
||||||
|
Returns true if value set, false otherwise. **/
|
||||||
|
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;
|
||||||
|
|
||||||
|
/** Deletes the specified key, value pair **/
|
||||||
|
virtual bool DeleteValue(const AString & keyname, const AString & valuename) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/** Writes the changes to the backing store, if the repository has one **/
|
||||||
|
virtual bool Flush() = 0;
|
||||||
|
};
|
@ -621,18 +621,18 @@ void cWorld::Start(void)
|
|||||||
InitialiseAndLoadMobSpawningValues(IniFile);
|
InitialiseAndLoadMobSpawningValues(IniFile);
|
||||||
SetTimeOfDay(IniFile.GetValueSetI("General", "TimeInTicks", GetTimeOfDay()));
|
SetTimeOfDay(IniFile.GetValueSetI("General", "TimeInTicks", GetTimeOfDay()));
|
||||||
|
|
||||||
m_ChunkMap = make_unique<cChunkMap>(this);
|
m_ChunkMap = cpp14::make_unique<cChunkMap>(this);
|
||||||
|
|
||||||
// preallocate some memory for ticking blocks so we don't need to allocate that often
|
// preallocate some memory for ticking blocks so we don't need to allocate that often
|
||||||
m_BlockTickQueue.reserve(1000);
|
m_BlockTickQueue.reserve(1000);
|
||||||
m_BlockTickQueueCopy.reserve(1000);
|
m_BlockTickQueueCopy.reserve(1000);
|
||||||
|
|
||||||
// Simulators:
|
// Simulators:
|
||||||
m_SimulatorManager = make_unique<cSimulatorManager>(*this);
|
m_SimulatorManager = cpp14::make_unique<cSimulatorManager>(*this);
|
||||||
m_WaterSimulator = InitializeFluidSimulator(IniFile, "Water", E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER);
|
m_WaterSimulator = InitializeFluidSimulator(IniFile, "Water", E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER);
|
||||||
m_LavaSimulator = InitializeFluidSimulator(IniFile, "Lava", E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA);
|
m_LavaSimulator = InitializeFluidSimulator(IniFile, "Lava", E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA);
|
||||||
m_SandSimulator = make_unique<cSandSimulator>(*this, IniFile);
|
m_SandSimulator = cpp14::make_unique<cSandSimulator>(*this, IniFile);
|
||||||
m_FireSimulator = make_unique<cFireSimulator>(*this, IniFile);
|
m_FireSimulator = cpp14::make_unique<cFireSimulator>(*this, IniFile);
|
||||||
m_RedstoneSimulator = InitializeRedstoneSimulator(IniFile);
|
m_RedstoneSimulator = InitializeRedstoneSimulator(IniFile);
|
||||||
|
|
||||||
// Water, Lava and Redstone simulators get registered in their initialize function.
|
// Water, Lava and Redstone simulators get registered in their initialize function.
|
||||||
@ -2680,7 +2680,7 @@ void cWorld::UnloadUnusedChunks(void)
|
|||||||
|
|
||||||
void cWorld::QueueUnloadUnusedChunks(void)
|
void cWorld::QueueUnloadUnusedChunks(void)
|
||||||
{
|
{
|
||||||
QueueTask(make_unique<cWorld::cTaskUnloadUnusedChunks>());
|
QueueTask(cpp14::make_unique<cWorld::cTaskUnloadUnusedChunks>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
60
src/main.cpp
60
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)
|
||||||
@ -257,7 +258,7 @@ DWORD WINAPI serviceWorkerThread(LPVOID lpParam)
|
|||||||
UNREFERENCED_PARAMETER(lpParam);
|
UNREFERENCED_PARAMETER(lpParam);
|
||||||
|
|
||||||
// Do the normal startup
|
// Do the normal startup
|
||||||
universalMain();
|
universalMain(cpp14::make_unique<cMemorySettingsRepository>());
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -363,14 +364,55 @@ 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);
|
||||||
|
|
||||||
|
TCLAP::MultiArg<int> portsArg("p", "port", "The port number the server should listen to", false, "port", cmd);
|
||||||
|
|
||||||
|
cmd.parse(argc, argv);
|
||||||
|
|
||||||
|
auto repo = cpp14::make_unique<cMemorySettingsRepository>();
|
||||||
|
|
||||||
|
if (slotsArg.isSet())
|
||||||
|
{
|
||||||
|
|
||||||
|
int slots = slotsArg.getValue();
|
||||||
|
|
||||||
|
repo->AddValue("Server", "MaxPlayers", static_cast<Int64>(slots));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portsArg.isSet())
|
||||||
|
{
|
||||||
|
std::vector<int> ports = portsArg.getValue();
|
||||||
|
for (auto port : ports)
|
||||||
|
{
|
||||||
|
repo->AddValue("Server", "Port", static_cast<Int64>(port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 cpp14::make_unique<cMemorySettingsRepository>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// 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 +467,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 +527,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