1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-29 23:07:48 +02:00

Settings: savefrequency is now configurable in launcher

* Client command-line can modify arbitrary settings now
* Only launcher auto-saves to settings.json
This commit is contained in:
Henning Koehler
2018-04-03 13:37:09 +12:00
committed by ArseniyShestakov
parent ce0b4b222d
commit 2ede3783dd
12 changed files with 119 additions and 24 deletions

View File

@@ -61,6 +61,7 @@
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "mainmenu/CPrologEpilogVideo.h" #include "mainmenu/CPrologEpilogVideo.h"
#include <vstd/StringUtils.h>
#ifdef VCMI_WINDOWS #ifdef VCMI_WINDOWS
#include "SDL_syswm.h" #include "SDL_syswm.h"
@@ -259,7 +260,29 @@ int main(int argc, char * argv[])
preinitDLL(::console); preinitDLL(::console);
settings.init(); settings.init();
Settings session = settings.write["session"]; Settings session = settings.write["session"];
session["onlyai"].Bool() = vm.count("onlyAI"); auto setSettingBool = [](std::string key, std::string arg) {
Settings s = settings.write(vstd::split(key, "/"));
if(::vm.count(arg))
s->Bool() = true;
else if(s->isNull())
s->Bool() = false;
};
auto setSettingInteger = [](std::string key, std::string arg, si64 defaultValue) {
Settings s = settings.write(vstd::split(key, "/"));
if(::vm.count(arg))
s->Integer() = ::vm[arg].as<si64>();
else if(s->isNull())
s->Integer() = defaultValue;
};
auto setSettingString = [](std::string key, std::string arg, std::string defaultValue) {
Settings s = settings.write(vstd::split(key, "/"));
if(::vm.count(arg))
s->String() = ::vm[arg].as<std::string>();
else if(s->isNull())
s->String() = defaultValue;
};
setSettingBool("session/onlyai", "onlyAI");
if(vm.count("headless")) if(vm.count("headless"))
{ {
session["headless"].Bool() = true; session["headless"].Bool() = true;
@@ -277,19 +300,20 @@ int main(int argc, char * argv[])
session["spectate-battle-speed"].Float() = vm["spectate-battle-speed"].as<int>(); session["spectate-battle-speed"].Float() = vm["spectate-battle-speed"].as<int>();
} }
// Server settings // Server settings
session["donotstartserver"].Bool() = vm.count("donotstartserver"); setSettingBool("session/donotstartserver", "donotstartserver");
// Shared memory options // Shared memory options
session["disable-shm"].Bool() = vm.count("disable-shm"); setSettingBool("session/disable-shm", "disable-shm");
session["enable-shm-uuid"].Bool() = vm.count("enable-shm-uuid"); setSettingBool("session/enable-shm-uuid", "enable-shm-uuid");
// Init special testing settings // Init special testing settings
session["serverport"].Integer() = vm.count("serverport") ? vm["serverport"].as<si64>() : 0; setSettingInteger("session/serverport", "serverport", 0);
session["saveprefix"].String() = vm.count("saveprefix") ? vm["saveprefix"].as<std::string>() : ""; setSettingString("session/saveprefix", "saveprefix", "");
session["savefrequency"].Integer() = vm.count("savefrequency") ? vm["savefrequency"].as<si64>() : 1; setSettingInteger("general/saveFrequency", "savefrequency", 1);
// Initialize logging based on settings // Initialize logging based on settings
logConfig.configure(); logConfig.configure();
logGlobal->debug("settings = %s", settings.toJsonNode().toJson());
// Some basic data validation to produce better error messages in cases of incorrect install // Some basic data validation to produce better error messages in cases of incorrect install
auto testFile = [](std::string filename, std::string message) -> bool auto testFile = [](std::string filename, std::string message) -> bool

View File

@@ -165,6 +165,7 @@ void CPlayerInterface::yourTurn()
adventureInt->selection = nullptr; adventureInt->selection = nullptr;
std::string prefix = settings["session"]["saveprefix"].String(); std::string prefix = settings["session"]["saveprefix"].String();
int frequency = settings["general"]["saveFrequency"].Integer();
if (firstCall) if (firstCall)
{ {
if(CSH->howManyPlayerInterfaces() == 1) if(CSH->howManyPlayerInterfaces() == 1)
@@ -180,7 +181,7 @@ void CPlayerInterface::yourTurn()
} }
firstCall = 0; firstCall = 0;
} }
else if (cb->getDate() % static_cast<int>(settings["session"]["savefrequency"].Integer()) == 0) else if(frequency > 0 && cb->getDate() % frequency == 0)
{ {
LOCPLINT->cb->save("Saves/" + prefix + "Autosave_" + boost::lexical_cast<std::string>(autosaveCount++ + 1)); LOCPLINT->cb->save("Saves/" + prefix + "Autosave_" + boost::lexical_cast<std::string>(autosaveCount++ + 1));
autosaveCount %= 5; autosaveCount %= 5;

View File

@@ -17,7 +17,7 @@
"type" : "object", "type" : "object",
"default": {}, "default": {},
"additionalProperties" : false, "additionalProperties" : false,
"required" : [ "playerName", "showfps", "music", "sound", "encoding", "swipe", "saveRandomMaps" ], "required" : [ "playerName", "showfps", "music", "sound", "encoding", "swipe", "saveRandomMaps", "saveFrequency" ],
"properties" : { "properties" : {
"playerName" : { "playerName" : {
"type":"string", "type":"string",
@@ -58,6 +58,10 @@
"lastCampaign" : { "lastCampaign" : {
"type":"string", "type":"string",
"default" : "" "default" : ""
},
"saveFrequency" : {
"type" : "number",
"default" : 1
} }
} }
}, },

View File

@@ -0,0 +1,6 @@
namespace vstd
{
DLL_LINKAGE std::vector<std::string> split(std::string s, std::string separators);
}

View File

@@ -36,7 +36,7 @@ void MainWindow::load()
QDir::addSearchPath("icons", pathToQString(string / "launcher" / "icons")); QDir::addSearchPath("icons", pathToQString(string / "launcher" / "icons"));
QDir::addSearchPath("icons", pathToQString(VCMIDirs::get().userDataPath() / "launcher" / "icons")); QDir::addSearchPath("icons", pathToQString(VCMIDirs::get().userDataPath() / "launcher" / "icons"));
settings.init(); settings.init(true);
} }
MainWindow::MainWindow(QWidget * parent) : MainWindow::MainWindow(QWidget * parent) :

View File

@@ -94,6 +94,7 @@ void CSettingsView::loadSettings()
size_t encodingIndex = boost::range::find(knownEncodingsList, encoding) - knownEncodingsList; size_t encodingIndex = boost::range::find(knownEncodingsList, encoding) - knownEncodingsList;
if (encodingIndex < ui->comboBoxEncoding->count()) if (encodingIndex < ui->comboBoxEncoding->count())
ui->comboBoxEncoding->setCurrentIndex(encodingIndex); ui->comboBoxEncoding->setCurrentIndex(encodingIndex);
ui->comboBoxAutoSave->setCurrentIndex(settings["general"]["saveFrequency"].Integer() > 0 ? 1 : 0);
} }
CSettingsView::CSettingsView(QWidget *parent) : CSettingsView::CSettingsView(QWidget *parent) :
@@ -223,3 +224,9 @@ void CSettingsView::on_changeGameDataDir_clicked()
{ {
} }
void CSettingsView::on_comboBoxAutoSave_currentIndexChanged(int index)
{
Settings node = settings.write["general"]["saveFrequency"];
node->Integer() = index;
}

View File

@@ -59,6 +59,8 @@ private slots:
void on_comboBoxDisplayIndex_currentIndexChanged(int index); void on_comboBoxDisplayIndex_currentIndexChanged(int index);
void on_comboBoxAutoSave_currentIndexChanged(int index);
private: private:
Ui::CSettingsView *ui; Ui::CSettingsView *ui;
}; };

View File

@@ -603,6 +603,30 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="6">
<widget class="QLabel" name="labelAutoSave">
<property name="text">
<string>Autosave</string>
</property>
</widget>
</item>
<item row="11" column="7">
<widget class="QComboBox" name="comboBoxAutoSave">
<property name="currentIndex">
<number>1</number>
</property>
<item>
<property name="text">
<string>Off</string>
</property>
</item>
<item>
<property name="text">
<string>On</string>
</property>
</item>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@@ -42,7 +42,7 @@ SettingsStorage::NodeAccessor<Accessor>::operator Accessor() const
} }
template<typename Accessor> template<typename Accessor>
SettingsStorage::NodeAccessor<Accessor> SettingsStorage::NodeAccessor<Accessor>::operator () (std::vector<std::string> _path) SettingsStorage::NodeAccessor<Accessor> SettingsStorage::NodeAccessor<Accessor>::operator () (std::vector<std::string> _path) const
{ {
std::vector<std::string> newPath = path; std::vector<std::string> newPath = path;
newPath.insert( newPath.end(), _path.begin(), _path.end()); newPath.insert( newPath.end(), _path.begin(), _path.end());
@@ -51,11 +51,12 @@ SettingsStorage::NodeAccessor<Accessor> SettingsStorage::NodeAccessor<Accessor>:
SettingsStorage::SettingsStorage(): SettingsStorage::SettingsStorage():
write(NodeAccessor<Settings>(*this, std::vector<std::string>() )), write(NodeAccessor<Settings>(*this, std::vector<std::string>() )),
listen(NodeAccessor<SettingsListener>(*this, std::vector<std::string>() )) listen(NodeAccessor<SettingsListener>(*this, std::vector<std::string>() )),
autoSaveConfig(false)
{ {
} }
void SettingsStorage::init() void SettingsStorage::init(bool autoSave)
{ {
std::string confName = "config/settings.json"; std::string confName = "config/settings.json";
@@ -67,6 +68,7 @@ void SettingsStorage::init()
JsonUtils::maximize(config, "vcmi:settings"); JsonUtils::maximize(config, "vcmi:settings");
JsonUtils::validate(config, "vcmi:settings", "settings"); JsonUtils::validate(config, "vcmi:settings", "settings");
autoSaveConfig = autoSave;
} }
void SettingsStorage::invalidateNode(const std::vector<std::string> &changedPath) void SettingsStorage::invalidateNode(const std::vector<std::string> &changedPath)
@@ -74,14 +76,14 @@ void SettingsStorage::invalidateNode(const std::vector<std::string> &changedPath
for(SettingsListener * listener : listeners) for(SettingsListener * listener : listeners)
listener->nodeInvalidated(changedPath); listener->nodeInvalidated(changedPath);
JsonNode savedConf = config; if(autoSaveConfig)
JsonNode schema(ResourceID("config/schemas/settings.json")); {
JsonNode savedConf = config;
JsonUtils::minimize(savedConf, "vcmi:settings");
savedConf.Struct().erase("session"); FileStream file(*CResourceHandler::get()->getResourceName(ResourceID("config/settings.json")), std::ofstream::out | std::ofstream::trunc);
JsonUtils::minimize(savedConf, "vcmi:settings"); file << savedConf.toJson();
}
FileStream file(*CResourceHandler::get()->getResourceName(ResourceID("config/settings.json")), std::ofstream::out | std::ofstream::trunc);
file << savedConf.toJson();
} }
JsonNode & SettingsStorage::getNode(std::vector<std::string> path) JsonNode & SettingsStorage::getNode(std::vector<std::string> path)
@@ -98,11 +100,16 @@ Settings SettingsStorage::get(std::vector<std::string> path)
return Settings(*this, path); return Settings(*this, path);
} }
const JsonNode& SettingsStorage::operator [](std::string value) const JsonNode & SettingsStorage::operator [](std::string value) const
{ {
return config[value]; return config[value];
} }
const JsonNode & SettingsStorage::toJsonNode() const
{
return config;
}
SettingsListener::SettingsListener(SettingsStorage &_parent, const std::vector<std::string> &_path): SettingsListener::SettingsListener(SettingsStorage &_parent, const std::vector<std::string> &_path):
parent(_parent), parent(_parent),
path(_path) path(_path)

View File

@@ -26,12 +26,14 @@ class DLL_LINKAGE SettingsStorage
NodeAccessor(SettingsStorage & _parent, std::vector<std::string> _path); NodeAccessor(SettingsStorage & _parent, std::vector<std::string> _path);
NodeAccessor<Accessor> operator [] (std::string nextNode) const; NodeAccessor<Accessor> operator [] (std::string nextNode) const;
NodeAccessor<Accessor> operator () (std::vector<std::string> _path); NodeAccessor<Accessor> operator () (std::vector<std::string> _path) const;
operator Accessor() const; operator Accessor() const;
}; };
std::set<SettingsListener*> listeners; std::set<SettingsListener*> listeners;
JsonNode config; JsonNode config;
bool autoSaveConfig;
JsonNode & getNode(std::vector<std::string> path); JsonNode & getNode(std::vector<std::string> path);
// Calls all required listeners // Calls all required listeners
@@ -41,7 +43,7 @@ class DLL_LINKAGE SettingsStorage
public: public:
// Initialize config structure // Initialize config structure
SettingsStorage(); SettingsStorage();
void init(); void init(bool autoSave=false);
// Get write access to config node at path // Get write access to config node at path
const NodeAccessor<Settings> write; const NodeAccessor<Settings> write;
@@ -50,7 +52,8 @@ public:
const NodeAccessor<SettingsListener> listen; const NodeAccessor<SettingsListener> listen;
//Read access, see JsonNode::operator[] //Read access, see JsonNode::operator[]
const JsonNode& operator [](std::string value); const JsonNode & operator [](std::string value) const;
const JsonNode & toJsonNode() const;
friend class SettingsListener; friend class SettingsListener;
friend class Settings; friend class Settings;

View File

@@ -124,6 +124,8 @@ set(lib_SRCS
spells/effects/RemoveObstacle.cpp spells/effects/RemoveObstacle.cpp
spells/effects/Sacrifice.cpp spells/effects/Sacrifice.cpp
vstd/StringUtils.cpp
CAndroidVMHelper.cpp CAndroidVMHelper.cpp
CArtHandler.cpp CArtHandler.cpp
CBonusTypeHandler.cpp CBonusTypeHandler.cpp
@@ -169,6 +171,7 @@ set(lib_HEADERS
${CMAKE_HOME_DIRECTORY}/include/vstd/CLoggerBase.h ${CMAKE_HOME_DIRECTORY}/include/vstd/CLoggerBase.h
${CMAKE_HOME_DIRECTORY}/include/vstd/ContainerUtils.h ${CMAKE_HOME_DIRECTORY}/include/vstd/ContainerUtils.h
${CMAKE_HOME_DIRECTORY}/include/vstd/RNG.h ${CMAKE_HOME_DIRECTORY}/include/vstd/RNG.h
${CMAKE_HOME_DIRECTORY}/include/vstd/StringUtils.h
StdInc.h StdInc.h
../Global.h ../Global.h

14
lib/vstd/StringUtils.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include "StdInc.h"
#include <vstd/StringUtils.h>
namespace vstd
{
DLL_LINKAGE std::vector<std::string> split(std::string s, std::string separators)
{
std::vector<std::string> result;
boost::split(result, s, boost::is_any_of(separators));
return result;
}
}