Refactor preferences
This commit is contained in:
parent
220844521a
commit
afda2826bf
@ -32,6 +32,7 @@
|
||||
#include "X86KillDenormals.h"
|
||||
#include "Misc.h"
|
||||
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/GameSave.h"
|
||||
#include "client/SaveFile.h"
|
||||
@ -97,8 +98,9 @@ int GetModifiers()
|
||||
|
||||
void LoadWindowPosition()
|
||||
{
|
||||
int savedWindowX = Client::Ref().GetPrefInteger("WindowX", INT_MAX);
|
||||
int savedWindowY = Client::Ref().GetPrefInteger("WindowY", INT_MAX);
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
int savedWindowX = prefs.Get("WindowX", INT_MAX);
|
||||
int savedWindowY = prefs.Get("WindowY", INT_MAX);
|
||||
|
||||
int borderTop, borderLeft;
|
||||
SDL_GetWindowBordersSize(sdl_window, &borderTop, &borderLeft, nullptr, nullptr);
|
||||
@ -133,8 +135,9 @@ void SaveWindowPosition()
|
||||
int borderTop, borderLeft;
|
||||
SDL_GetWindowBordersSize(sdl_window, &borderTop, &borderLeft, nullptr, nullptr);
|
||||
|
||||
Client::Ref().SetPref("WindowX", x - borderLeft);
|
||||
Client::Ref().SetPref("WindowY", y - borderTop);
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
prefs.Set("WindowX", x - borderLeft);
|
||||
prefs.Set("WindowY", y - borderTop);
|
||||
}
|
||||
|
||||
void CalculateMousePosition(int *x, int *y)
|
||||
@ -453,7 +456,7 @@ void LargeScreenDialog()
|
||||
message << "\nTo undo this, hit Cancel. You can change this in settings at any time.";
|
||||
if (!ConfirmPrompt::Blocking("Large screen detected", message.Build()))
|
||||
{
|
||||
Client::Ref().SetPref("Scale", 1);
|
||||
GlobalPrefs::Ref().Set("Scale", 1);
|
||||
engine->SetScale(1);
|
||||
}
|
||||
}
|
||||
@ -603,8 +606,21 @@ int GuessBestScale()
|
||||
return guess;
|
||||
}
|
||||
|
||||
struct ExplicitSingletons
|
||||
{
|
||||
// These need to be listed in the order they are populated in main.
|
||||
std::unique_ptr<GlobalPrefs> globalPrefs;
|
||||
std::unique_ptr<Client> client;
|
||||
http::RequestManagerPtr requestManager;
|
||||
};
|
||||
static std::unique_ptr<ExplicitSingletons> explicitSingletons;
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
atexit([]() {
|
||||
explicitSingletons.reset();
|
||||
});
|
||||
explicitSingletons = std::make_unique<ExplicitSingletons>();
|
||||
#ifdef WIN
|
||||
if constexpr (DEBUG)
|
||||
{
|
||||
@ -710,14 +726,17 @@ int main(int argc, char * argv[])
|
||||
SDL_free(ddir);
|
||||
}
|
||||
}
|
||||
// We're now in the correct directory, time to get prefs.
|
||||
explicitSingletons->globalPrefs = std::make_unique<GlobalPrefs>();
|
||||
|
||||
scale = Client::Ref().GetPrefInteger("Scale", 1);
|
||||
resizable = Client::Ref().GetPrefBool("Resizable", false);
|
||||
fullscreen = Client::Ref().GetPrefBool("Fullscreen", false);
|
||||
altFullscreen = Client::Ref().GetPrefBool("AltFullscreen", false);
|
||||
forceIntegerScaling = Client::Ref().GetPrefBool("ForceIntegerScaling", true);
|
||||
momentumScroll = Client::Ref().GetPrefBool("MomentumScroll", true);
|
||||
showAvatars = Client::Ref().GetPrefBool("ShowAvatars", true);
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
scale = prefs.Get("Scale", 1);
|
||||
resizable = prefs.Get("Resizable", false);
|
||||
fullscreen = prefs.Get("Fullscreen", false);
|
||||
altFullscreen = prefs.Get("AltFullscreen", false);
|
||||
forceIntegerScaling = prefs.Get("ForceIntegerScaling", true);
|
||||
momentumScroll = prefs.Get("MomentumScroll", true);
|
||||
showAvatars = prefs.Get("ShowAvatars", true);
|
||||
|
||||
auto true_string = [](ByteString str) {
|
||||
str = str.ToLower();
|
||||
@ -736,7 +755,7 @@ int main(int argc, char * argv[])
|
||||
if (kioskArg.has_value())
|
||||
{
|
||||
fullscreen = true_string(kioskArg.value());
|
||||
Client::Ref().SetPref("Fullscreen", fullscreen);
|
||||
prefs.Set("Fullscreen", fullscreen);
|
||||
}
|
||||
|
||||
if (true_arg(arguments["redirect"]))
|
||||
@ -755,7 +774,7 @@ int main(int argc, char * argv[])
|
||||
try
|
||||
{
|
||||
scale = scaleArg.value().ToNumber<int>();
|
||||
Client::Ref().SetPref("Scale", scale);
|
||||
prefs.Set("Scale", scale);
|
||||
}
|
||||
catch (const std::runtime_error &e)
|
||||
{
|
||||
@ -763,7 +782,7 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
}
|
||||
|
||||
auto clientConfig = [](Argument arg, ByteString name, ByteString defaultValue) {
|
||||
auto clientConfig = [&prefs](Argument arg, ByteString name, ByteString defaultValue) {
|
||||
ByteString value;
|
||||
if (arg.has_value())
|
||||
{
|
||||
@ -772,11 +791,11 @@ int main(int argc, char * argv[])
|
||||
{
|
||||
value = defaultValue;
|
||||
}
|
||||
Client::Ref().SetPref(name, value);
|
||||
prefs.Set(name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = Client::Ref().GetPrefByteString(name, defaultValue);
|
||||
value = prefs.Get(name, defaultValue);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
@ -784,8 +803,9 @@ int main(int argc, char * argv[])
|
||||
ByteString cafileString = clientConfig(arguments["cafile"], "CAFile", "");
|
||||
ByteString capathString = clientConfig(arguments["capath"], "CAPath", "");
|
||||
bool disableNetwork = true_arg(arguments["disable-network"]);
|
||||
auto requestManager = http::RequestManager::Create(proxyString, cafileString, capathString, disableNetwork);
|
||||
explicitSingletons->requestManager = http::RequestManager::Create(proxyString, cafileString, capathString, disableNetwork);
|
||||
|
||||
explicitSingletons->client = std::make_unique<Client>();
|
||||
Client::Ref().Initialize();
|
||||
|
||||
// TODO: maybe bind the maximum allowed scale to screen size somehow
|
||||
@ -799,7 +819,7 @@ int main(int argc, char * argv[])
|
||||
scale = GuessBestScale();
|
||||
if (scale > 1)
|
||||
{
|
||||
Client::Ref().SetPref("Scale", scale);
|
||||
prefs.Set("Scale", scale);
|
||||
SDL_SetWindowSize(sdl_window, WINDOWW * scale, WINDOWH * scale);
|
||||
showLargeScreenDialog = true;
|
||||
}
|
||||
@ -819,7 +839,7 @@ int main(int argc, char * argv[])
|
||||
engine = &ui::Engine::Ref();
|
||||
engine->SetMaxSize(desktopWidth, desktopHeight);
|
||||
engine->Begin(WINDOWW, WINDOWH);
|
||||
engine->SetFastQuit(Client::Ref().GetPrefBool("FastQuit", true));
|
||||
engine->SetFastQuit(prefs.Get("FastQuit", true));
|
||||
|
||||
bool enableBluescreen = !DEBUG && !true_arg(arguments["disable-bluescreen"]);
|
||||
if (enableBluescreen)
|
||||
@ -949,7 +969,6 @@ int main(int argc, char * argv[])
|
||||
ui::Engine::Ref().CloseWindow();
|
||||
delete gameController;
|
||||
delete ui::Engine::Ref().g;
|
||||
Client::Ref().Shutdown();
|
||||
if (SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_OPENGL)
|
||||
{
|
||||
// * nvidia-460 egl registers callbacks with x11 that end up being called
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "Client.h"
|
||||
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
#include "client/http/Request.h" // includes curl.h, needs to come first to silence a warning on windows
|
||||
|
||||
#include <cstring>
|
||||
@ -65,48 +66,30 @@ Client::Client():
|
||||
updateAvailable(false),
|
||||
authUser(0, "")
|
||||
{
|
||||
//Read config
|
||||
std::ifstream configFile;
|
||||
configFile.open("powder.pref", std::ios::binary);
|
||||
if (configFile)
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
authUser.UserID = prefs.Get("User.ID", 0);
|
||||
authUser.Username = prefs.Get("User.Username", ByteString(""));
|
||||
authUser.SessionID = prefs.Get("User.SessionID", ByteString(""));
|
||||
authUser.SessionKey = prefs.Get("User.SessionKey", ByteString(""));
|
||||
auto elevation = prefs.Get("User.Elevation", ByteString(""));
|
||||
authUser.UserElevation = User::ElevationNone;
|
||||
if (elevation == "Admin")
|
||||
{
|
||||
try
|
||||
{
|
||||
preferences.clear();
|
||||
configFile >> preferences;
|
||||
int ID = preferences["User"]["ID"].asInt();
|
||||
ByteString Username = preferences["User"]["Username"].asString();
|
||||
ByteString SessionID = preferences["User"]["SessionID"].asString();
|
||||
ByteString SessionKey = preferences["User"]["SessionKey"].asString();
|
||||
ByteString Elevation = preferences["User"]["Elevation"].asString();
|
||||
|
||||
authUser.UserID = ID;
|
||||
authUser.Username = Username;
|
||||
authUser.SessionID = SessionID;
|
||||
authUser.SessionKey = SessionKey;
|
||||
if (Elevation == "Admin")
|
||||
authUser.UserElevation = User::ElevationAdmin;
|
||||
else if (Elevation == "Mod")
|
||||
authUser.UserElevation = User::ElevationModerator;
|
||||
else
|
||||
authUser.UserElevation = User::ElevationNone;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
|
||||
}
|
||||
configFile.close();
|
||||
firstRun = false;
|
||||
authUser.UserElevation = User::ElevationAdmin;
|
||||
}
|
||||
else
|
||||
firstRun = true;
|
||||
if (elevation == "Mod")
|
||||
{
|
||||
authUser.UserElevation = User::ElevationModerator;
|
||||
}
|
||||
firstRun = !prefs.BackedByFile();
|
||||
}
|
||||
|
||||
void Client::Initialize()
|
||||
{
|
||||
if (GetPrefBool("version.update", false))
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
if (prefs.Get("version.update", false))
|
||||
{
|
||||
SetPref("version.update", false);
|
||||
prefs.Set("version.update", false);
|
||||
update_finish();
|
||||
}
|
||||
|
||||
@ -412,51 +395,38 @@ void Client::RemoveListener(ClientListener * listener)
|
||||
}
|
||||
}
|
||||
|
||||
void Client::WritePrefs()
|
||||
{
|
||||
std::ofstream configFile;
|
||||
configFile.open("powder.pref", std::ios::trunc);
|
||||
|
||||
if (configFile)
|
||||
{
|
||||
if (authUser.UserID)
|
||||
{
|
||||
preferences["User"]["ID"] = authUser.UserID;
|
||||
preferences["User"]["SessionID"] = authUser.SessionID;
|
||||
preferences["User"]["SessionKey"] = authUser.SessionKey;
|
||||
preferences["User"]["Username"] = authUser.Username;
|
||||
if (authUser.UserElevation == User::ElevationAdmin)
|
||||
preferences["User"]["Elevation"] = "Admin";
|
||||
else if (authUser.UserElevation == User::ElevationModerator)
|
||||
preferences["User"]["Elevation"] = "Mod";
|
||||
else
|
||||
preferences["User"]["Elevation"] = "None";
|
||||
}
|
||||
else
|
||||
{
|
||||
preferences["User"] = Json::nullValue;
|
||||
}
|
||||
configFile << preferences;
|
||||
|
||||
configFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Shutdown()
|
||||
{
|
||||
//Save config
|
||||
WritePrefs();
|
||||
}
|
||||
|
||||
Client::~Client()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Client::SetAuthUser(User user)
|
||||
{
|
||||
authUser = user;
|
||||
WritePrefs();
|
||||
{
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
Prefs::DeferWrite dw(prefs);
|
||||
if (authUser.UserID)
|
||||
{
|
||||
prefs.Set("User.ID", authUser.UserID);
|
||||
prefs.Set("User.SessionID", authUser.SessionID);
|
||||
prefs.Set("User.SessionKey", authUser.SessionKey);
|
||||
prefs.Set("User.Username", authUser.Username);
|
||||
ByteString elevation = "None";
|
||||
if (authUser.UserElevation == User::ElevationAdmin)
|
||||
{
|
||||
elevation = "Admin";
|
||||
}
|
||||
if (authUser.UserElevation == User::ElevationModerator)
|
||||
{
|
||||
elevation = "Mod";
|
||||
}
|
||||
prefs.Set("User.Elevation", elevation);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefs.Clear("User");
|
||||
}
|
||||
}
|
||||
notifyAuthUserChanged();
|
||||
}
|
||||
|
||||
@ -1264,254 +1234,6 @@ void Client::SaveAuthorInfo(Json::Value *saveInto)
|
||||
}
|
||||
}
|
||||
|
||||
// powder.pref preference getting / setting functions
|
||||
|
||||
// Recursively go down the json to get the setting we want
|
||||
Json::Value Client::GetPref(Json::Value root, ByteString prop, Json::Value defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(ByteString::Split split = prop.SplitBy('.'))
|
||||
return GetPref(root[split.Before()], split.After(), defaultValue);
|
||||
else
|
||||
return root.get(prop, defaultValue);
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
ByteString Client::GetPrefByteString(ByteString prop, ByteString defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetPref(preferences, prop, defaultValue).asString();
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
String Client::GetPrefString(ByteString prop, String defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ByteString(GetPref(preferences, prop, defaultValue.ToUtf8()).asString()).FromUtf8(false);
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
double Client::GetPrefNumber(ByteString prop, double defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetPref(preferences, prop, defaultValue).asDouble();
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
int Client::GetPrefInteger(ByteString prop, int defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetPref(preferences, prop, defaultValue).asInt();
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Client::GetPrefUInteger(ByteString prop, unsigned int defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetPref(preferences, prop, defaultValue).asUInt();
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
bool Client::GetPrefBool(ByteString prop, bool defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetPref(preferences, prop, defaultValue).asBool();
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ByteString> Client::GetPrefByteStringArray(ByteString prop)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<ByteString> ret;
|
||||
Json::Value arr = GetPref(preferences, prop);
|
||||
for (int i = 0; i < (int)arr.size(); i++)
|
||||
ret.push_back(arr[i].asString());
|
||||
return ret;
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
|
||||
}
|
||||
return std::vector<ByteString>();
|
||||
}
|
||||
|
||||
std::vector<String> Client::GetPrefStringArray(ByteString prop)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<String> ret;
|
||||
Json::Value arr = GetPref(preferences, prop);
|
||||
for (int i = 0; i < (int)arr.size(); i++)
|
||||
ret.push_back(ByteString(arr[i].asString()).FromUtf8(false));
|
||||
return ret;
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
|
||||
}
|
||||
return std::vector<String>();
|
||||
}
|
||||
|
||||
std::vector<double> Client::GetPrefNumberArray(ByteString prop)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<double> ret;
|
||||
Json::Value arr = GetPref(preferences, prop);
|
||||
for (int i = 0; i < (int)arr.size(); i++)
|
||||
ret.push_back(arr[i].asDouble());
|
||||
return ret;
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
|
||||
}
|
||||
return std::vector<double>();
|
||||
}
|
||||
|
||||
std::vector<int> Client::GetPrefIntegerArray(ByteString prop)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<int> ret;
|
||||
Json::Value arr = GetPref(preferences, prop);
|
||||
for (int i = 0; i < (int)arr.size(); i++)
|
||||
ret.push_back(arr[i].asInt());
|
||||
return ret;
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
|
||||
}
|
||||
return std::vector<int>();
|
||||
}
|
||||
|
||||
std::vector<unsigned int> Client::GetPrefUIntegerArray(ByteString prop)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<unsigned int> ret;
|
||||
Json::Value arr = GetPref(preferences, prop);
|
||||
for (int i = 0; i < (int)arr.size(); i++)
|
||||
ret.push_back(arr[i].asUInt());
|
||||
return ret;
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
|
||||
}
|
||||
return std::vector<unsigned int>();
|
||||
}
|
||||
|
||||
std::vector<bool> Client::GetPrefBoolArray(ByteString prop)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<bool> ret;
|
||||
Json::Value arr = GetPref(preferences, prop);
|
||||
for (int i = 0; i < (int)arr.size(); i++)
|
||||
ret.push_back(arr[i].asBool());
|
||||
return ret;
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
|
||||
}
|
||||
return std::vector<bool>();
|
||||
}
|
||||
|
||||
// Helper preference setting function.
|
||||
// To actually save any changes to preferences, we need to directly do preferences[property] = thing
|
||||
// any other way will set the value of a copy of preferences, not the original
|
||||
// This function will recursively go through and create an object with the property we wanted set,
|
||||
// and return it to SetPref to do the actual setting
|
||||
Json::Value Client::SetPrefHelper(Json::Value root, ByteString prop, Json::Value value)
|
||||
{
|
||||
if(ByteString::Split split = prop.SplitBy('.'))
|
||||
{
|
||||
Json::Value toSet = GetPref(root, split.Before());
|
||||
toSet = SetPrefHelper(toSet, split.After(), value);
|
||||
root[split.Before()] = toSet;
|
||||
}
|
||||
else
|
||||
root[prop] = value;
|
||||
return root;
|
||||
}
|
||||
|
||||
void Client::SetPref(ByteString prop, Json::Value value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(ByteString::Split split = prop.SplitBy('.'))
|
||||
preferences[split.Before()] = SetPrefHelper(preferences[split.Before()], split.After(), value);
|
||||
else
|
||||
preferences[prop] = value;
|
||||
WritePrefs();
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SetPref(ByteString prop, std::vector<Json::Value> value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Json::Value arr;
|
||||
for (int i = 0; i < (int)value.size(); i++)
|
||||
{
|
||||
arr.append(value[i]);
|
||||
}
|
||||
SetPref(prop, arr);
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SetPrefUnicode(ByteString prop, String value)
|
||||
{
|
||||
SetPref(prop, value.ToUtf8());
|
||||
}
|
||||
|
||||
bool Client::DoInstallation()
|
||||
{
|
||||
bool ok = true;
|
||||
@ -1652,8 +1374,9 @@ bool Client::DoInstallation()
|
||||
|
||||
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor)
|
||||
{
|
||||
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
||||
Json::Value newCustomGOLTypes(Json::arrayValue);
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
auto customGOLTypes = prefs.Get("CustomGOL.Types", std::vector<ByteString>{});
|
||||
std::vector<ByteString> newCustomGOLTypes;
|
||||
bool nameTaken = false;
|
||||
for (auto gol : customGOLTypes)
|
||||
{
|
||||
@ -1665,14 +1388,147 @@ bool AddCustomGol(String ruleString, String nameString, unsigned int highColor,
|
||||
nameTaken = true;
|
||||
}
|
||||
}
|
||||
newCustomGOLTypes.append(gol);
|
||||
newCustomGOLTypes.push_back(gol);
|
||||
}
|
||||
if (nameTaken)
|
||||
return false;
|
||||
|
||||
StringBuilder sb;
|
||||
sb << nameString << " " << ruleString << " " << highColor << " " << lowColor;
|
||||
newCustomGOLTypes.append(sb.Build().ToUtf8());
|
||||
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
|
||||
newCustomGOLTypes.push_back(sb.Build().ToUtf8());
|
||||
prefs.Set("CustomGOL.Types", newCustomGOLTypes);
|
||||
return true;
|
||||
}
|
||||
|
||||
String Client::DoMigration(ByteString fromDir, ByteString toDir)
|
||||
{
|
||||
if (fromDir.at(fromDir.length() - 1) != '/')
|
||||
fromDir = fromDir + '/';
|
||||
if (toDir.at(toDir.length() - 1) != '/')
|
||||
toDir = toDir + '/';
|
||||
|
||||
std::ofstream logFile(fromDir + "/migrationlog.txt", std::ios::out);
|
||||
logFile << "Running migration of data from " << fromDir + " to " << toDir << std::endl;
|
||||
|
||||
// Get lists of files to migrate
|
||||
auto stamps = Platform::DirectorySearch(fromDir + "stamps", "", { ".stm" });
|
||||
auto saves = Platform::DirectorySearch(fromDir + "Saves", "", { ".cps", ".stm" });
|
||||
auto scripts = Platform::DirectorySearch(fromDir + "scripts", "", { ".lua", ".txt" });
|
||||
auto downloadedScripts = Platform::DirectorySearch(fromDir + "scripts/downloaded", "", { ".lua" });
|
||||
bool hasScriptinfo = Platform::FileExists(toDir + "scripts/downloaded/scriptinfo");
|
||||
auto screenshots = Platform::DirectorySearch(fromDir, "screenshot", { ".png" });
|
||||
bool hasAutorun = Platform::FileExists(fromDir + "autorun.lua");
|
||||
bool hasPref = Platform::FileExists(fromDir + "powder.pref");
|
||||
|
||||
if (stamps.empty() && saves.empty() && scripts.empty() && downloadedScripts.empty() && screenshots.empty() && !hasAutorun && !hasPref)
|
||||
{
|
||||
logFile << "Nothing to migrate.";
|
||||
return "Nothing to migrate. This button is used to migrate data from pre-96.0 TPT installations to the shared directory";
|
||||
}
|
||||
|
||||
StringBuilder result;
|
||||
std::stack<ByteString> dirsToDelete;
|
||||
|
||||
// Migrate a list of files
|
||||
auto migrateList = [&](std::vector<ByteString> list, ByteString directory, String niceName) {
|
||||
result << '\n' << niceName << ": ";
|
||||
if (!list.empty() && !directory.empty())
|
||||
Platform::MakeDirectory(toDir + directory);
|
||||
int migratedCount = 0, failedCount = 0;
|
||||
for (auto &item : list)
|
||||
{
|
||||
std::string from = fromDir + directory + "/" + item;
|
||||
std::string to = toDir + directory + "/" + item;
|
||||
if (!Platform::FileExists(to))
|
||||
{
|
||||
if (rename(from.c_str(), to.c_str()))
|
||||
{
|
||||
failedCount++;
|
||||
logFile << "failed to move " << from << " to " << to << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
migratedCount++;
|
||||
logFile << "moved " << from << " to " << to << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logFile << "skipping " << from << "(already exists)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
dirsToDelete.push(directory);
|
||||
result << "\bt" << migratedCount << " migratated\x0E, \br" << failedCount << " failed\x0E";
|
||||
int duplicates = list.size() - migratedCount - failedCount;
|
||||
if (duplicates)
|
||||
result << ", " << list.size() - migratedCount - failedCount << " skipped (duplicate)";
|
||||
};
|
||||
|
||||
// Migrate a single file
|
||||
auto migrateFile = [&fromDir, &toDir, &result, &logFile](ByteString filename) {
|
||||
ByteString from = fromDir + filename;
|
||||
ByteString to = toDir + filename;
|
||||
if (!Platform::FileExists(to))
|
||||
{
|
||||
if (rename(from.c_str(), to.c_str()))
|
||||
{
|
||||
logFile << "failed to move " << from << " to " << to << std::endl;
|
||||
result << "\n\br" << filename.FromUtf8() << " migration failed\x0E";
|
||||
}
|
||||
else
|
||||
{
|
||||
logFile << "moved " << from << " to " << to << std::endl;
|
||||
result << '\n' << filename.FromUtf8() << " migrated";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logFile << "skipping " << from << "(already exists)" << std::endl;
|
||||
result << '\n' << filename.FromUtf8() << " skipped (already exists)";
|
||||
}
|
||||
|
||||
if (!Platform::RemoveFile(fromDir + filename)) {
|
||||
logFile << "failed to delete " << filename << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
// Do actual migration
|
||||
Platform::RemoveFile(fromDir + "stamps/stamps.def");
|
||||
migrateList(stamps, "stamps", "Stamps");
|
||||
migrateList(saves, "Saves", "Saves");
|
||||
if (!scripts.empty())
|
||||
migrateList(scripts, "scripts", "Scripts");
|
||||
if (!hasScriptinfo && !downloadedScripts.empty())
|
||||
{
|
||||
migrateList(downloadedScripts, "scripts/downloaded", "Downloaded scripts");
|
||||
migrateFile("scripts/downloaded/scriptinfo");
|
||||
}
|
||||
if (!screenshots.empty())
|
||||
migrateList(screenshots, "", "Screenshots");
|
||||
if (hasAutorun)
|
||||
migrateFile("autorun.lua");
|
||||
if (hasPref)
|
||||
migrateFile("powder.pref");
|
||||
|
||||
// Delete leftover directories
|
||||
while (!dirsToDelete.empty())
|
||||
{
|
||||
ByteString toDelete = dirsToDelete.top();
|
||||
if (!Platform::DeleteDirectory(fromDir + toDelete)) {
|
||||
logFile << "failed to delete " << toDelete << std::endl;
|
||||
}
|
||||
dirsToDelete.pop();
|
||||
}
|
||||
|
||||
// chdir into the new directory
|
||||
chdir(toDir.c_str());
|
||||
|
||||
if (scripts.size())
|
||||
RescanStamps();
|
||||
|
||||
logFile << std::endl << std::endl << "Migration complete. Results: " << result.Build().ToUtf8();
|
||||
logFile.close();
|
||||
|
||||
return result.Build();
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "common/String.h"
|
||||
#include "common/Singleton.h"
|
||||
#include "common/ExplicitSingleton.h"
|
||||
#include <json/json.h>
|
||||
|
||||
#include "User.h"
|
||||
@ -47,7 +47,7 @@ namespace http
|
||||
{
|
||||
class Request;
|
||||
}
|
||||
class Client: public Singleton<Client> {
|
||||
class Client: public ExplicitSingleton<Client> {
|
||||
private:
|
||||
String messageOfTheDay;
|
||||
std::vector<std::pair<String, ByteString> > serverNotifications;
|
||||
@ -73,11 +73,6 @@ private:
|
||||
void notifyMessageOfTheDay();
|
||||
void notifyNewNotification(std::pair<String, ByteString> notification);
|
||||
|
||||
// internal preferences handling
|
||||
Json::Value preferences;
|
||||
Json::Value GetPref(Json::Value root, ByteString prop, Json::Value defaultValue = Json::nullValue);
|
||||
Json::Value SetPrefHelper(Json::Value root, ByteString prop, Json::Value value);
|
||||
|
||||
// Save stealing info
|
||||
Json::Value authors;
|
||||
|
||||
@ -155,27 +150,8 @@ public:
|
||||
RequestStatus ParseServerReturn(ByteString &result, int status, bool json);
|
||||
void Tick();
|
||||
void CheckUpdate(std::unique_ptr<http::Request> &updateRequest, bool checkSession);
|
||||
void Shutdown();
|
||||
|
||||
// preferences functions
|
||||
void WritePrefs();
|
||||
|
||||
ByteString GetPrefByteString(ByteString prop, ByteString defaultValue);
|
||||
String GetPrefString(ByteString prop, String defaultValue);
|
||||
double GetPrefNumber(ByteString prop, double defaultValue);
|
||||
int GetPrefInteger(ByteString prop, int defaultValue);
|
||||
unsigned int GetPrefUInteger(ByteString prop, unsigned int defaultValue);
|
||||
bool GetPrefBool(ByteString prop, bool defaultValue);
|
||||
std::vector<ByteString> GetPrefByteStringArray(ByteString prop);
|
||||
std::vector<String> GetPrefStringArray(ByteString prop);
|
||||
std::vector<double> GetPrefNumberArray(ByteString prop);
|
||||
std::vector<int> GetPrefIntegerArray(ByteString prop);
|
||||
std::vector<unsigned int> GetPrefUIntegerArray(ByteString prop);
|
||||
std::vector<bool> GetPrefBoolArray(ByteString prop);
|
||||
|
||||
void SetPref(ByteString prop, Json::Value value);
|
||||
void SetPref(ByteString property, std::vector<Json::Value> value);
|
||||
void SetPrefUnicode(ByteString prop, String value);
|
||||
|
||||
String DoMigration(ByteString fromDir, ByteString toDir);
|
||||
};
|
||||
|
||||
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor);
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "ImageRequest.h"
|
||||
|
||||
#include "common/Singleton.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "Config.h"
|
||||
|
||||
|
@ -318,8 +318,9 @@ bool ReadFile(std::vector<char> &fileData, ByteString filename)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteFile(std::vector<char> fileData, ByteString filename)
|
||||
bool WriteFile(std::vector<char> fileData, ByteString filename, bool replaceAtomically)
|
||||
{
|
||||
// TODO: replaceAtomically
|
||||
std::ofstream f(filename, std::ios::binary);
|
||||
if (f) f.write(&fileData[0], fileData.size());
|
||||
if (!f)
|
||||
@ -381,4 +382,31 @@ ByteString ExecutableName()
|
||||
#endif
|
||||
}
|
||||
|
||||
void DoRestart()
|
||||
{
|
||||
ByteString exename = ExecutableName();
|
||||
if (exename.length())
|
||||
{
|
||||
#ifdef WIN
|
||||
int ret = int(INT_PTR(ShellExecuteW(NULL, NULL, WinWiden(exename).c_str(), NULL, NULL, SW_SHOWNORMAL)));
|
||||
if (ret <= 32)
|
||||
{
|
||||
fprintf(stderr, "cannot restart: ShellExecute(...) failed: code %i\n", ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
#elif defined(LIN) || defined(MACOSX)
|
||||
execl(exename.c_str(), exename.c_str(), NULL);
|
||||
int ret = errno;
|
||||
fprintf(stderr, "cannot restart: execl(...) failed: code %i\n", ret);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "cannot restart: no executable name???\n");
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
@ -37,10 +37,9 @@ namespace Platform
|
||||
*/
|
||||
bool MakeDirectory(ByteString dir);
|
||||
std::vector<ByteString> DirectorySearch(ByteString directory, ByteString search, std::vector<ByteString> extensions);
|
||||
String DoMigration(ByteString fromDir, ByteString toDir);
|
||||
|
||||
bool ReadFile(std::vector<char> &fileData, ByteString filename);
|
||||
bool WriteFile(std::vector<char> fileData, ByteString filename);
|
||||
bool WriteFile(std::vector<char> fileData, ByteString filename, bool replaceAtomically = false); // TODO: Revisit call sites, remove default.
|
||||
|
||||
#ifdef WIN
|
||||
ByteString WinNarrow(const std::wstring &source);
|
||||
|
@ -1,187 +0,0 @@
|
||||
#include "Platform.h"
|
||||
#include "client/Client.h"
|
||||
#ifdef WIN
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include <direct.h>
|
||||
# include <io.h>
|
||||
# include <shlobj.h>
|
||||
# include <shlwapi.h>
|
||||
# include <shellapi.h>
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <ctime>
|
||||
# include <sys/time.h>
|
||||
# include <dirent.h>
|
||||
#endif
|
||||
#ifdef MACOSX
|
||||
# include <mach-o/dyld.h>
|
||||
#endif
|
||||
#include <fstream>
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
void DoRestart()
|
||||
{
|
||||
ByteString exename = ExecutableName();
|
||||
if (exename.length())
|
||||
{
|
||||
#ifdef WIN
|
||||
int ret = int(INT_PTR(ShellExecuteW(NULL, NULL, WinWiden(exename).c_str(), NULL, NULL, SW_SHOWNORMAL)));
|
||||
if (ret <= 32)
|
||||
{
|
||||
fprintf(stderr, "cannot restart: ShellExecute(...) failed: code %i\n", ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
Client::Ref().Shutdown(); // very ugly hack; will fix soon(tm)
|
||||
exit(0);
|
||||
}
|
||||
#elif defined(LIN) || defined(MACOSX)
|
||||
execl(exename.c_str(), exename.c_str(), NULL);
|
||||
int ret = errno;
|
||||
fprintf(stderr, "cannot restart: execl(...) failed: code %i\n", ret);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "cannot restart: no executable name???\n");
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
String DoMigration(ByteString fromDir, ByteString toDir)
|
||||
{
|
||||
if (fromDir.at(fromDir.length() - 1) != '/')
|
||||
fromDir = fromDir + '/';
|
||||
if (toDir.at(toDir.length() - 1) != '/')
|
||||
toDir = toDir + '/';
|
||||
|
||||
std::ofstream logFile(fromDir + "/migrationlog.txt", std::ios::out);
|
||||
logFile << "Running migration of data from " << fromDir + " to " << toDir << std::endl;
|
||||
|
||||
// Get lists of files to migrate
|
||||
auto stamps = DirectorySearch(fromDir + "stamps", "", { ".stm" });
|
||||
auto saves = DirectorySearch(fromDir + "Saves", "", { ".cps", ".stm" });
|
||||
auto scripts = DirectorySearch(fromDir + "scripts", "", { ".lua", ".txt" });
|
||||
auto downloadedScripts = DirectorySearch(fromDir + "scripts/downloaded", "", { ".lua" });
|
||||
bool hasScriptinfo = FileExists(toDir + "scripts/downloaded/scriptinfo");
|
||||
auto screenshots = DirectorySearch(fromDir, "screenshot", { ".png" });
|
||||
bool hasAutorun = FileExists(fromDir + "autorun.lua");
|
||||
bool hasPref = FileExists(fromDir + "powder.pref");
|
||||
|
||||
if (stamps.empty() && saves.empty() && scripts.empty() && downloadedScripts.empty() && screenshots.empty() && !hasAutorun && !hasPref)
|
||||
{
|
||||
logFile << "Nothing to migrate.";
|
||||
return "Nothing to migrate. This button is used to migrate data from pre-96.0 TPT installations to the shared directory";
|
||||
}
|
||||
|
||||
StringBuilder result;
|
||||
std::stack<ByteString> dirsToDelete;
|
||||
|
||||
// Migrate a list of files
|
||||
auto migrateList = [&](std::vector<ByteString> list, ByteString directory, String niceName) {
|
||||
result << '\n' << niceName << ": ";
|
||||
if (!list.empty() && !directory.empty())
|
||||
MakeDirectory(toDir + directory);
|
||||
int migratedCount = 0, failedCount = 0;
|
||||
for (auto &item : list)
|
||||
{
|
||||
std::string from = fromDir + directory + "/" + item;
|
||||
std::string to = toDir + directory + "/" + item;
|
||||
if (!FileExists(to))
|
||||
{
|
||||
if (rename(from.c_str(), to.c_str()))
|
||||
{
|
||||
failedCount++;
|
||||
logFile << "failed to move " << from << " to " << to << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
migratedCount++;
|
||||
logFile << "moved " << from << " to " << to << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logFile << "skipping " << from << "(already exists)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
dirsToDelete.push(directory);
|
||||
result << "\bt" << migratedCount << " migratated\x0E, \br" << failedCount << " failed\x0E";
|
||||
int duplicates = list.size() - migratedCount - failedCount;
|
||||
if (duplicates)
|
||||
result << ", " << list.size() - migratedCount - failedCount << " skipped (duplicate)";
|
||||
};
|
||||
|
||||
// Migrate a single file
|
||||
auto migrateFile = [&fromDir, &toDir, &result, &logFile](ByteString filename) {
|
||||
ByteString from = fromDir + filename;
|
||||
ByteString to = toDir + filename;
|
||||
if (!FileExists(to))
|
||||
{
|
||||
if (rename(from.c_str(), to.c_str()))
|
||||
{
|
||||
logFile << "failed to move " << from << " to " << to << std::endl;
|
||||
result << "\n\br" << filename.FromUtf8() << " migration failed\x0E";
|
||||
}
|
||||
else
|
||||
{
|
||||
logFile << "moved " << from << " to " << to << std::endl;
|
||||
result << '\n' << filename.FromUtf8() << " migrated";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logFile << "skipping " << from << "(already exists)" << std::endl;
|
||||
result << '\n' << filename.FromUtf8() << " skipped (already exists)";
|
||||
}
|
||||
|
||||
if (!RemoveFile(fromDir + filename)) {
|
||||
logFile << "failed to delete " << filename << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
// Do actual migration
|
||||
RemoveFile(fromDir + "stamps/stamps.def");
|
||||
migrateList(stamps, "stamps", "Stamps");
|
||||
migrateList(saves, "Saves", "Saves");
|
||||
if (!scripts.empty())
|
||||
migrateList(scripts, "scripts", "Scripts");
|
||||
if (!hasScriptinfo && !downloadedScripts.empty())
|
||||
{
|
||||
migrateList(downloadedScripts, "scripts/downloaded", "Downloaded scripts");
|
||||
migrateFile("scripts/downloaded/scriptinfo");
|
||||
}
|
||||
if (!screenshots.empty())
|
||||
migrateList(screenshots, "", "Screenshots");
|
||||
if (hasAutorun)
|
||||
migrateFile("autorun.lua");
|
||||
if (hasPref)
|
||||
migrateFile("powder.pref");
|
||||
|
||||
// Delete leftover directories
|
||||
while (!dirsToDelete.empty())
|
||||
{
|
||||
ByteString toDelete = dirsToDelete.top();
|
||||
if (!DeleteDirectory(fromDir + toDelete)) {
|
||||
logFile << "failed to delete " << toDelete << std::endl;
|
||||
}
|
||||
dirsToDelete.pop();
|
||||
}
|
||||
|
||||
// chdir into the new directory
|
||||
chdir(toDir.c_str());
|
||||
|
||||
if (scripts.size())
|
||||
Client::Ref().RescanStamps();
|
||||
|
||||
logFile << std::endl << std::endl << "Migration complete. Results: " << result.Build().ToUtf8();
|
||||
logFile.close();
|
||||
|
||||
return result.Build();
|
||||
}
|
||||
}
|
@ -4,7 +4,3 @@ common_files += files(
|
||||
'tpt-rand.cpp',
|
||||
'tpt-thread-local.cpp',
|
||||
)
|
||||
|
||||
powder_files += files(
|
||||
'PlatformPowder.cpp',
|
||||
)
|
||||
|
@ -13,9 +13,9 @@ public:
|
||||
int ReturnStatus;
|
||||
String ReturnValue;
|
||||
|
||||
operator ByteString() const
|
||||
operator String() const
|
||||
{
|
||||
return Command.ToUtf8();
|
||||
return Command;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
#include "ConsoleModel.h"
|
||||
|
||||
#include "ConsoleView.h"
|
||||
|
||||
#include "client/Client.h"
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
|
||||
ConsoleModel::ConsoleModel() {
|
||||
std::vector<String> previousHistory = Client::Ref().GetPrefStringArray("Console.History");
|
||||
std::vector<String> previousHistory = GlobalPrefs::Ref().Get("Console.History", std::vector<String>{});
|
||||
for(std::vector<String>::reverse_iterator iter = previousHistory.rbegin(), end = previousHistory.rend(); iter != end; ++iter)
|
||||
{
|
||||
if(previousCommands.size()<25)
|
||||
@ -48,7 +46,7 @@ void ConsoleModel::AddLastCommand(ConsoleCommand command)
|
||||
if(previousCommands.size()>25)
|
||||
previousCommands.pop_front();
|
||||
currentCommandIndex = previousCommands.size();
|
||||
Client::Ref().SetPref("Console.History", std::vector<Json::Value>(previousCommands.begin(), previousCommands.end()));
|
||||
GlobalPrefs::Ref().Set("Console.History", std::vector<String>(previousCommands.begin(), previousCommands.end()));
|
||||
notifyPreviousCommandsChanged();
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "Favorite.h"
|
||||
|
||||
#include <json/json.h>
|
||||
#include "client/Client.h"
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -42,10 +42,10 @@ void Favorite::RemoveFavorite(ByteString identifier)
|
||||
|
||||
void Favorite::SaveFavoritesToPrefs()
|
||||
{
|
||||
Client::Ref().SetPref("Favorites", std::vector<Json::Value>(favoritesList.begin(), favoritesList.end()));
|
||||
GlobalPrefs::Ref().Set("Favorites", favoritesList);
|
||||
}
|
||||
|
||||
void Favorite::LoadFavoritesFromPrefs()
|
||||
{
|
||||
favoritesList = Client::Ref().GetPrefByteStringArray("Favorites");
|
||||
favoritesList = GlobalPrefs::Ref().Get("Favorites", std::vector<ByteString>{});
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "Tool.h"
|
||||
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
#include "client/Client.h"
|
||||
#include "common/tpt-rand.h"
|
||||
#include "simulation/GOLString.h"
|
||||
@ -105,8 +106,9 @@ toolSelection(toolSelection)
|
||||
}
|
||||
else
|
||||
{
|
||||
ruleField->SetText(Client::Ref().GetPrefString("CustomGOL.Rule", "B3/S23"));
|
||||
nameField->SetText(Client::Ref().GetPrefString("CustomGOL.Name", "CGOL"));
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
ruleField->SetText(prefs.Get("CustomGOL.Rule", String("B3/S23")));
|
||||
nameField->SetText(prefs.Get("CustomGOL.Name", String("CGOL")));
|
||||
highColour.Red = RNG::Ref().between(0x80, 0xFF);
|
||||
highColour.Green = RNG::Ref().between(0x80, 0xFF);
|
||||
highColour.Blue = RNG::Ref().between(0x80, 0xFF);
|
||||
@ -152,8 +154,12 @@ void GOLWindow::Validate()
|
||||
}
|
||||
ruleString = SerialiseGOLRule(rule); // * Make it canonical.
|
||||
|
||||
Client::Ref().SetPrefUnicode("CustomGOL.Name", nameString);
|
||||
Client::Ref().SetPrefUnicode("CustomGOL.Rule", ruleString);
|
||||
{
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
Prefs::DeferWrite dw(prefs);
|
||||
prefs.Set("CustomGOL.Name", nameString);
|
||||
prefs.Set("CustomGOL.Rule", ruleString);
|
||||
}
|
||||
|
||||
auto color1 = (((highColour.Red << 8) | highColour.Green) << 8) | highColour.Blue;
|
||||
auto color2 = (((lowColour.Red << 8) | lowColour.Green) << 8) | lowColour.Blue;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "GameControllerEvents.h"
|
||||
#include "lua/CommandInterface.h"
|
||||
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/GameSave.h"
|
||||
#include "common/Platform.h"
|
||||
@ -88,7 +89,7 @@ GameController::GameController():
|
||||
gameView->AttachController(this);
|
||||
gameModel->AddObserver(gameView);
|
||||
|
||||
gameView->SetDebugHUD(Client::Ref().GetPrefBool("Renderer.DebugMode", false));
|
||||
gameView->SetDebugHUD(GlobalPrefs::Ref().Get("Renderer.DebugMode", false));
|
||||
|
||||
CommandInterface::Create(this, gameModel);
|
||||
|
||||
@ -1352,7 +1353,6 @@ void GameController::OpenOptions()
|
||||
{
|
||||
options = new OptionsController(gameModel, [this] {
|
||||
gameModel->UpdateQuickOptions();
|
||||
Client::Ref().WritePrefs(); // * I don't think there's a reason for this but I'm too lazy to check. -- LBPHacker
|
||||
});
|
||||
ui::Engine::Ref().ShowWindow(options->GetView());
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "QuickOptions.h"
|
||||
#include "lua/CommandInterface.h"
|
||||
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
#include "client/Client.h"
|
||||
#include "client/GameSave.h"
|
||||
#include "client/SaveFile.h"
|
||||
@ -67,56 +68,51 @@ GameModel::GameModel():
|
||||
std::fill(regularToolset, regularToolset+4, (Tool*)NULL);
|
||||
|
||||
//Default render prefs
|
||||
std::vector<unsigned int> tempArray;
|
||||
tempArray.push_back(RENDER_FIRE);
|
||||
tempArray.push_back(RENDER_EFFE);
|
||||
tempArray.push_back(RENDER_BASC);
|
||||
ren->SetRenderMode(tempArray);
|
||||
tempArray.clear();
|
||||
|
||||
ren->SetDisplayMode(tempArray);
|
||||
|
||||
ren->SetRenderMode({
|
||||
RENDER_FIRE,
|
||||
RENDER_EFFE,
|
||||
RENDER_BASC,
|
||||
});
|
||||
ren->SetDisplayMode({});
|
||||
ren->SetColourMode(0);
|
||||
|
||||
//Load config into renderer
|
||||
ren->SetColourMode(Client::Ref().GetPrefUInteger("Renderer.ColourMode", 0));
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
ren->SetColourMode(prefs.Get("Renderer.ColourMode", 0U));
|
||||
|
||||
tempArray = Client::Ref().GetPrefUIntegerArray("Renderer.DisplayModes");
|
||||
if(tempArray.size())
|
||||
auto displayModes = prefs.Get("Renderer.DisplayModes", std::vector<unsigned int>{});
|
||||
if (displayModes.size())
|
||||
{
|
||||
std::vector<unsigned int> displayModes(tempArray.begin(), tempArray.end());
|
||||
ren->SetDisplayMode(displayModes);
|
||||
}
|
||||
|
||||
tempArray = Client::Ref().GetPrefUIntegerArray("Renderer.RenderModes");
|
||||
if(tempArray.size())
|
||||
auto renderModes = prefs.Get("Renderer.RenderModes", std::vector<unsigned int>{});
|
||||
if (renderModes.size())
|
||||
{
|
||||
std::vector<unsigned int> renderModes(tempArray.begin(), tempArray.end());
|
||||
ren->SetRenderMode(renderModes);
|
||||
}
|
||||
|
||||
ren->gravityFieldEnabled = Client::Ref().GetPrefBool("Renderer.GravityField", false);
|
||||
ren->decorations_enable = Client::Ref().GetPrefBool("Renderer.Decorations", true);
|
||||
ren->gravityFieldEnabled = prefs.Get("Renderer.GravityField", false);
|
||||
ren->decorations_enable = prefs.Get("Renderer.Decorations", true);
|
||||
|
||||
//Load config into simulation
|
||||
edgeMode = Client::Ref().GetPrefInteger("Simulation.EdgeMode", 0);
|
||||
edgeMode = prefs.Get("Simulation.EdgeMode", 0); // TODO: EdgeMode enum
|
||||
sim->SetEdgeMode(edgeMode);
|
||||
ambientAirTemp = float(R_TEMP) + 273.15f;
|
||||
{
|
||||
auto temp = Client::Ref().GetPrefNumber("Simulation.AmbientAirTemp", ambientAirTemp);
|
||||
auto temp = prefs.Get("Simulation.AmbientAirTemp", ambientAirTemp);
|
||||
if (MIN_TEMP <= temp && MAX_TEMP >= temp)
|
||||
{
|
||||
ambientAirTemp = temp;
|
||||
}
|
||||
}
|
||||
sim->air->ambientAirTemp = ambientAirTemp;
|
||||
decoSpace = Client::Ref().GetPrefInteger("Simulation.DecoSpace", 0);
|
||||
decoSpace = prefs.Get("Simulation.DecoSpace", 0); // TODO: DecoSpace enum
|
||||
sim->SetDecoSpace(decoSpace);
|
||||
int ngrav_enable = Client::Ref().GetPrefInteger("Simulation.NewtonianGravity", 0);
|
||||
int ngrav_enable = prefs.Get("Simulation.NewtonianGravity", 0); // TODO: NewtonianGravity enum
|
||||
if (ngrav_enable)
|
||||
sim->grav->start_grav_async();
|
||||
sim->aheat_enable = Client::Ref().GetPrefInteger("Simulation.AmbientHeat", 0);
|
||||
sim->pretty_powder = Client::Ref().GetPrefInteger("Simulation.PrettyPowder", 0);
|
||||
sim->aheat_enable = prefs.Get("Simulation.AmbientHeat", 0); // TODO: AmbientHeat enum
|
||||
sim->pretty_powder = prefs.Get("Simulation.PrettyPowder", 0); // TODO: PrettyPowder enum
|
||||
|
||||
Favorite::Ref().LoadFavoritesFromPrefs();
|
||||
|
||||
@ -128,14 +124,14 @@ GameModel::GameModel():
|
||||
|
||||
BuildMenus();
|
||||
|
||||
perfectCircle = Client::Ref().GetPrefBool("PerfectCircleBrush", true);
|
||||
perfectCircle = prefs.Get("PerfectCircleBrush", true);
|
||||
BuildBrushList();
|
||||
|
||||
//Set default decoration colour
|
||||
unsigned char colourR = std::min(Client::Ref().GetPrefInteger("Decoration.Red", 200), 255);
|
||||
unsigned char colourG = std::min(Client::Ref().GetPrefInteger("Decoration.Green", 100), 255);
|
||||
unsigned char colourB = std::min(Client::Ref().GetPrefInteger("Decoration.Blue", 50), 255);
|
||||
unsigned char colourA = std::min(Client::Ref().GetPrefInteger("Decoration.Alpha", 255), 255);
|
||||
unsigned char colourR = std::max(std::min(prefs.Get("Decoration.Red", 200), 255), 0);
|
||||
unsigned char colourG = std::max(std::min(prefs.Get("Decoration.Green", 100), 255), 0);
|
||||
unsigned char colourB = std::max(std::min(prefs.Get("Decoration.Blue", 50), 255), 0);
|
||||
unsigned char colourA = std::max(std::min(prefs.Get("Decoration.Alpha", 255), 255), 0);
|
||||
|
||||
SetColourSelectorColour(ui::Colour(colourR, colourG, colourB, colourA));
|
||||
|
||||
@ -148,41 +144,38 @@ GameModel::GameModel():
|
||||
colourPresets.push_back(ui::Colour(0, 0, 255));
|
||||
colourPresets.push_back(ui::Colour(0, 0, 0));
|
||||
|
||||
undoHistoryLimit = Client::Ref().GetPrefInteger("Simulation.UndoHistoryLimit", 5);
|
||||
undoHistoryLimit = prefs.Get("Simulation.UndoHistoryLimit", 5U);
|
||||
// cap due to memory usage (this is about 3.4GB of RAM)
|
||||
if (undoHistoryLimit > 200)
|
||||
SetUndoHistoryLimit(200);
|
||||
|
||||
mouseClickRequired = Client::Ref().GetPrefBool("MouseClickRequired", false);
|
||||
includePressure = Client::Ref().GetPrefBool("Simulation.IncludePressure", true);
|
||||
temperatureScale = Client::Ref().GetPrefInteger("Renderer.TemperatureScale", 1);
|
||||
mouseClickRequired = prefs.Get("MouseClickRequired", false);
|
||||
includePressure = prefs.Get("Simulation.IncludePressure", true);
|
||||
temperatureScale = prefs.Get("Renderer.TemperatureScale", 1); // TODO: TemperatureScale enum
|
||||
|
||||
ClearSimulation();
|
||||
}
|
||||
|
||||
GameModel::~GameModel()
|
||||
{
|
||||
//Save to config:
|
||||
Client::Ref().SetPref("Renderer.ColourMode", ren->GetColourMode());
|
||||
|
||||
std::vector<unsigned int> displayModes = ren->GetDisplayMode();
|
||||
Client::Ref().SetPref("Renderer.DisplayModes", std::vector<Json::Value>(displayModes.begin(), displayModes.end()));
|
||||
|
||||
std::vector<unsigned int> renderModes = ren->GetRenderMode();
|
||||
Client::Ref().SetPref("Renderer.RenderModes", std::vector<Json::Value>(renderModes.begin(), renderModes.end()));
|
||||
|
||||
Client::Ref().SetPref("Renderer.GravityField", (bool)ren->gravityFieldEnabled);
|
||||
Client::Ref().SetPref("Renderer.Decorations", (bool)ren->decorations_enable);
|
||||
Client::Ref().SetPref("Renderer.DebugMode", ren->debugLines); //These two should always be equivalent, even though they are different things
|
||||
|
||||
Client::Ref().SetPref("Simulation.NewtonianGravity", sim->grav->IsEnabled());
|
||||
Client::Ref().SetPref("Simulation.AmbientHeat", sim->aheat_enable);
|
||||
Client::Ref().SetPref("Simulation.PrettyPowder", sim->pretty_powder);
|
||||
|
||||
Client::Ref().SetPref("Decoration.Red", (int)colour.Red);
|
||||
Client::Ref().SetPref("Decoration.Green", (int)colour.Green);
|
||||
Client::Ref().SetPref("Decoration.Blue", (int)colour.Blue);
|
||||
Client::Ref().SetPref("Decoration.Alpha", (int)colour.Alpha);
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
{
|
||||
//Save to config:
|
||||
Prefs::DeferWrite dw(prefs);
|
||||
prefs.Set("Renderer.ColourMode", ren->GetColourMode());
|
||||
prefs.Set("Renderer.DisplayModes", ren->GetDisplayMode());
|
||||
prefs.Set("Renderer.RenderModes", ren->GetRenderMode());
|
||||
prefs.Set("Renderer.GravityField", (bool)ren->gravityFieldEnabled);
|
||||
prefs.Set("Renderer.Decorations", (bool)ren->decorations_enable);
|
||||
prefs.Set("Renderer.DebugMode", ren->debugLines); //These two should always be equivalent, even though they are different things
|
||||
prefs.Set("Simulation.NewtonianGravity", sim->grav->IsEnabled());
|
||||
prefs.Set("Simulation.AmbientHeat", sim->aheat_enable);
|
||||
prefs.Set("Simulation.PrettyPowder", sim->pretty_powder);
|
||||
prefs.Set("Decoration.Red", (int)colour.Red);
|
||||
prefs.Set("Decoration.Green", (int)colour.Green);
|
||||
prefs.Set("Decoration.Blue", (int)colour.Blue);
|
||||
prefs.Set("Decoration.Alpha", (int)colour.Alpha);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < menuList.size(); i++)
|
||||
{
|
||||
@ -317,8 +310,9 @@ void GameModel::BuildMenus()
|
||||
menuList[SC_LIFE]->AddTool(tempTool);
|
||||
}
|
||||
{
|
||||
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
||||
Json::Value validatedCustomLifeTypes(Json::arrayValue);
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
auto customGOLTypes = prefs.Get("CustomGOL.Types", std::vector<ByteString>{});
|
||||
std::vector<ByteString> validatedCustomLifeTypes;
|
||||
std::vector<Simulation::CustomGOLData> newCustomGol;
|
||||
for (auto gol : customGOLTypes)
|
||||
{
|
||||
@ -351,10 +345,10 @@ void GameModel::BuildMenus()
|
||||
continue;
|
||||
}
|
||||
newCustomGol.push_back(gd);
|
||||
validatedCustomLifeTypes.append(gol);
|
||||
validatedCustomLifeTypes.push_back(gol);
|
||||
}
|
||||
// All custom rules that fail validation will be removed
|
||||
Client::Ref().SetPref("CustomGOL.Types", validatedCustomLifeTypes);
|
||||
prefs.Set("CustomGOL.Types", validatedCustomLifeTypes);
|
||||
for (auto &gd : newCustomGol)
|
||||
{
|
||||
Tool * tempTool = new ElementTool(PT_LIFE|PMAPID(gd.rule), gd.nameString, "Custom GOL type: " + gd.ruleString, PIXR(gd.colour1), PIXG(gd.colour1), PIXB(gd.colour1), "DEFAULT_PT_LIFECUST_"+gd.nameString.ToAscii(), NULL);
|
||||
@ -795,7 +789,7 @@ unsigned int GameModel::GetUndoHistoryLimit()
|
||||
void GameModel::SetUndoHistoryLimit(unsigned int undoHistoryLimit_)
|
||||
{
|
||||
undoHistoryLimit = undoHistoryLimit_;
|
||||
Client::Ref().SetPref("Simulation.UndoHistoryLimit", undoHistoryLimit);
|
||||
GlobalPrefs::Ref().Set("Simulation.UndoHistoryLimit", undoHistoryLimit);
|
||||
}
|
||||
|
||||
void GameModel::SetVote(int direction)
|
||||
@ -1653,17 +1647,18 @@ void GameModel::SetPerfectCircle(bool perfectCircle)
|
||||
bool GameModel::RemoveCustomGOLType(const ByteString &identifier)
|
||||
{
|
||||
bool removedAny = false;
|
||||
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
||||
Json::Value newCustomGOLTypes(Json::arrayValue);
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
auto customGOLTypes = prefs.Get("CustomGOL.Types", std::vector<ByteString>{});
|
||||
std::vector<ByteString> newCustomGOLTypes;
|
||||
for (auto gol : customGOLTypes)
|
||||
{
|
||||
auto parts = gol.PartitionBy(' ');
|
||||
if (parts.size() && "DEFAULT_PT_LIFECUST_" + parts[0] == identifier)
|
||||
removedAny = true;
|
||||
else
|
||||
newCustomGOLTypes.append(gol);
|
||||
newCustomGOLTypes.push_back(gol);
|
||||
}
|
||||
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
|
||||
prefs.Set("CustomGOL.Types", newCustomGOLTypes);
|
||||
BuildMenus();
|
||||
return removedAny;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "Tool.h"
|
||||
|
||||
#include "client/Client.h"
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
#include "Menu.h"
|
||||
#include "Format.h"
|
||||
|
||||
@ -75,12 +75,14 @@ sim(sim_)
|
||||
{
|
||||
property->AddOption(std::pair<String, int>(properties[i].Name.FromAscii(), i));
|
||||
}
|
||||
property->SetOption(Client::Ref().GetPrefInteger("Prop.Type", 0));
|
||||
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
property->SetOption(prefs.Get("Prop.Type", 0));
|
||||
|
||||
textField = new ui::Textbox(ui::Point(8, 46), ui::Point(Size.X-16, 16), "", "[value]");
|
||||
textField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||
textField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
||||
textField->SetText(Client::Ref().GetPrefString("Prop.Value", ""));
|
||||
textField->SetText(prefs.Get("Prop.Value", String("")));
|
||||
AddComponent(textField);
|
||||
FocusComponent(textField);
|
||||
SetProperty(false);
|
||||
@ -216,8 +218,12 @@ void PropertyWindow::SetProperty(bool warn)
|
||||
new ErrorMessage("Could not set property", "Invalid value provided");
|
||||
return;
|
||||
}
|
||||
Client::Ref().SetPref("Prop.Type", property->GetOption().second);
|
||||
Client::Ref().SetPrefUnicode("Prop.Value", textField->GetText());
|
||||
{
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
Prefs::DeferWrite dw(prefs);
|
||||
prefs.Set("Prop.Type", property->GetOption().second);
|
||||
prefs.Set("Prop.Value", textField->GetText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "simulation/Air.h"
|
||||
#include "simulation/Gravity.h"
|
||||
|
||||
#include "client/Client.h"
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
|
||||
#include "gui/interface/Engine.h"
|
||||
#include "gui/game/GameModel.h"
|
||||
@ -85,7 +85,7 @@ int OptionsModel::GetEdgeMode()
|
||||
}
|
||||
void OptionsModel::SetEdgeMode(int edgeMode)
|
||||
{
|
||||
Client::Ref().SetPref("Simulation.EdgeMode", edgeMode);
|
||||
GlobalPrefs::Ref().Set("Simulation.EdgeMode", edgeMode);
|
||||
gModel->SetEdgeMode(edgeMode);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
@ -96,7 +96,7 @@ int OptionsModel::GetTemperatureScale()
|
||||
}
|
||||
void OptionsModel::SetTemperatureScale(int temperatureScale)
|
||||
{
|
||||
Client::Ref().SetPref("Renderer.TemperatureScale", temperatureScale);
|
||||
GlobalPrefs::Ref().Set("Renderer.TemperatureScale", temperatureScale);
|
||||
gModel->SetTemperatureScale(temperatureScale);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
@ -107,7 +107,7 @@ float OptionsModel::GetAmbientAirTemperature()
|
||||
}
|
||||
void OptionsModel::SetAmbientAirTemperature(float ambientAirTemp)
|
||||
{
|
||||
Client::Ref().SetPref("Simulation.AmbientAirTemp", ambientAirTemp);
|
||||
GlobalPrefs::Ref().Set("Simulation.AmbientAirTemp", ambientAirTemp);
|
||||
gModel->SetAmbientAirTemperature(ambientAirTemp);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
@ -152,7 +152,7 @@ int OptionsModel::GetScale()
|
||||
void OptionsModel::SetScale(int scale)
|
||||
{
|
||||
ui::Engine::Ref().SetScale(scale);
|
||||
Client::Ref().SetPref("Scale", int(scale));
|
||||
GlobalPrefs::Ref().Set("Scale", int(scale));
|
||||
notifySettingsChanged();
|
||||
}
|
||||
|
||||
@ -164,7 +164,7 @@ bool OptionsModel::GetResizable()
|
||||
void OptionsModel::SetResizable(bool resizable)
|
||||
{
|
||||
ui::Engine::Ref().SetResizable(resizable);
|
||||
Client::Ref().SetPref("Resizable", resizable);
|
||||
GlobalPrefs::Ref().Set("Resizable", resizable);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ bool OptionsModel::GetFullscreen()
|
||||
void OptionsModel::SetFullscreen(bool fullscreen)
|
||||
{
|
||||
ui::Engine::Ref().SetFullscreen(fullscreen);
|
||||
Client::Ref().SetPref("Fullscreen", fullscreen);
|
||||
GlobalPrefs::Ref().Set("Fullscreen", fullscreen);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
|
||||
@ -187,7 +187,7 @@ bool OptionsModel::GetAltFullscreen()
|
||||
void OptionsModel::SetAltFullscreen(bool altFullscreen)
|
||||
{
|
||||
ui::Engine::Ref().SetAltFullscreen(altFullscreen);
|
||||
Client::Ref().SetPref("AltFullscreen", altFullscreen);
|
||||
GlobalPrefs::Ref().Set("AltFullscreen", altFullscreen);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ bool OptionsModel::GetForceIntegerScaling()
|
||||
void OptionsModel::SetForceIntegerScaling(bool forceIntegerScaling)
|
||||
{
|
||||
ui::Engine::Ref().SetForceIntegerScaling(forceIntegerScaling);
|
||||
Client::Ref().SetPref("ForceIntegerScaling", forceIntegerScaling);
|
||||
GlobalPrefs::Ref().Set("ForceIntegerScaling", forceIntegerScaling);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ bool OptionsModel::GetFastQuit()
|
||||
void OptionsModel::SetFastQuit(bool fastquit)
|
||||
{
|
||||
ui::Engine::Ref().SetFastQuit(fastquit);
|
||||
Client::Ref().SetPref("FastQuit", bool(fastquit));
|
||||
GlobalPrefs::Ref().Set("FastQuit", bool(fastquit));
|
||||
notifySettingsChanged();
|
||||
}
|
||||
|
||||
@ -220,7 +220,7 @@ int OptionsModel::GetDecoSpace()
|
||||
}
|
||||
void OptionsModel::SetDecoSpace(int decoSpace)
|
||||
{
|
||||
Client::Ref().SetPref("Simulation.DecoSpace", decoSpace);
|
||||
GlobalPrefs::Ref().Set("Simulation.DecoSpace", decoSpace);
|
||||
gModel->SetDecoSpace(decoSpace);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
@ -233,7 +233,7 @@ bool OptionsModel::GetShowAvatars()
|
||||
void OptionsModel::SetShowAvatars(bool state)
|
||||
{
|
||||
ui::Engine::Ref().ShowAvatars = state;
|
||||
Client::Ref().SetPref("ShowAvatars", state);
|
||||
GlobalPrefs::Ref().Set("ShowAvatars", state);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
|
||||
@ -244,7 +244,7 @@ bool OptionsModel::GetMouseClickRequired()
|
||||
|
||||
void OptionsModel::SetMouseClickRequired(bool mouseClickRequired)
|
||||
{
|
||||
Client::Ref().SetPref("MouseClickRequired", mouseClickRequired);
|
||||
GlobalPrefs::Ref().Set("MouseClickRequired", mouseClickRequired);
|
||||
gModel->SetMouseClickRequired(mouseClickRequired);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
@ -256,7 +256,7 @@ bool OptionsModel::GetIncludePressure()
|
||||
|
||||
void OptionsModel::SetIncludePressure(bool includePressure)
|
||||
{
|
||||
Client::Ref().SetPref("Simulation.IncludePressure", includePressure);
|
||||
GlobalPrefs::Ref().Set("Simulation.IncludePressure", includePressure);
|
||||
gModel->SetIncludePressure(includePressure);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
@ -268,7 +268,7 @@ bool OptionsModel::GetPerfectCircle()
|
||||
|
||||
void OptionsModel::SetPerfectCircle(bool perfectCircle)
|
||||
{
|
||||
Client::Ref().SetPref("PerfectCircleBrush", perfectCircle);
|
||||
GlobalPrefs::Ref().Set("PerfectCircleBrush", perfectCircle);
|
||||
gModel->SetPerfectCircle(perfectCircle);
|
||||
notifySettingsChanged();
|
||||
}
|
||||
@ -280,7 +280,7 @@ bool OptionsModel::GetMomentumScroll()
|
||||
|
||||
void OptionsModel::SetMomentumScroll(bool state)
|
||||
{
|
||||
Client::Ref().SetPref("MomentumScroll", state);
|
||||
GlobalPrefs::Ref().Set("MomentumScroll", state);
|
||||
ui::Engine::Ref().MomentumScroll = state;
|
||||
notifySettingsChanged();
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "graphics/Renderer.h"
|
||||
#include "gui/Style.h"
|
||||
#include "simulation/ElementDefs.h"
|
||||
#include "client/Client.h"
|
||||
|
||||
#include "gui/dialogues/ConfirmPrompt.h"
|
||||
#include "gui/dialogues/InformationMessage.h"
|
||||
@ -420,7 +421,7 @@ OptionsView::OptionsView():
|
||||
ByteString to = Platform::sharedCwd;
|
||||
new ConfirmPrompt("Do Migration?", "This will migrate all stamps, saves, and scripts from\n\bt" + from.FromUtf8() + "\bw\nto the shared data directory at\n\bt" + to.FromUtf8() + "\bw\n\n" +
|
||||
"Files that already exist will not be overwritten.", { [=] () {
|
||||
String ret = Platform::DoMigration(from, to);
|
||||
String ret = Client::Ref().DoMigration(from, to);
|
||||
new InformationMessage("Migration Complete", ret, false);
|
||||
} });
|
||||
} });
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "Config.h"
|
||||
#include "Update.h"
|
||||
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
#include "client/Client.h"
|
||||
#include "common/Platform.h"
|
||||
#include "tasks/Task.h"
|
||||
@ -32,7 +33,13 @@ private:
|
||||
}
|
||||
bool doWork() override
|
||||
{
|
||||
String error;
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
|
||||
auto niceNotifyError = [this](String error) {
|
||||
notifyError("Downloaded update is corrupted\n" + error);
|
||||
return false;
|
||||
};
|
||||
|
||||
auto request = std::make_unique<http::Request>(updateName);
|
||||
request->Start();
|
||||
notifyStatus("Downloading update");
|
||||
@ -48,15 +55,11 @@ private:
|
||||
auto [ status, data ] = request->Finish();
|
||||
if (status!=200)
|
||||
{
|
||||
error = String::Build("Server responded with Status ", status);
|
||||
notifyError("Could not download update: " + error);
|
||||
return false;
|
||||
return niceNotifyError("Could not download update: " + String::Build("Server responded with Status ", status));
|
||||
}
|
||||
if (!data.size())
|
||||
{
|
||||
error = "Server responded with nothing";
|
||||
notifyError("Server did not return any data");
|
||||
return false;
|
||||
return niceNotifyError("Server did not return any data");
|
||||
}
|
||||
|
||||
notifyStatus("Unpacking update");
|
||||
@ -66,13 +69,11 @@ private:
|
||||
|
||||
if(data.size()<16)
|
||||
{
|
||||
error = String::Build("Unsufficient data, got ", data.size(), " bytes");
|
||||
goto corrupt;
|
||||
return niceNotifyError(String::Build("Unsufficient data, got ", data.size(), " bytes"));
|
||||
}
|
||||
if (data[0]!=0x42 || data[1]!=0x75 || data[2]!=0x54 || data[3]!=0x54)
|
||||
{
|
||||
error = "Invalid update format";
|
||||
goto corrupt;
|
||||
return niceNotifyError("Invalid update format");
|
||||
}
|
||||
|
||||
uncompressedLength = (unsigned char)data[4];
|
||||
@ -80,40 +81,28 @@ private:
|
||||
uncompressedLength |= ((unsigned char)data[6])<<16;
|
||||
uncompressedLength |= ((unsigned char)data[7])<<24;
|
||||
|
||||
char * res;
|
||||
res = (char *)malloc(uncompressedLength);
|
||||
if (!res)
|
||||
{
|
||||
error = String::Build("Unable to allocate ", uncompressedLength, " bytes of memory for decompression");
|
||||
goto corrupt;
|
||||
}
|
||||
std::vector<char> res(uncompressedLength);
|
||||
|
||||
int dstate;
|
||||
dstate = BZ2_bzBuffToBuffDecompress((char *)res, (unsigned *)&uncompressedLength, &data[8], data.size()-8, 0, 0);
|
||||
dstate = BZ2_bzBuffToBuffDecompress(&res[0], (unsigned *)&uncompressedLength, &data[8], data.size()-8, 0, 0);
|
||||
if (dstate)
|
||||
{
|
||||
error = String::Build("Unable to decompress update: ", dstate);
|
||||
free(res);
|
||||
goto corrupt;
|
||||
return niceNotifyError(String::Build("Unable to decompress update: ", dstate));
|
||||
}
|
||||
|
||||
notifyStatus("Applying update");
|
||||
notifyProgress(-1);
|
||||
|
||||
Client::Ref().SetPref("version.update", true);
|
||||
if (update_start(res, uncompressedLength))
|
||||
prefs.Set("version.update", true);
|
||||
if (update_start(&res[0], uncompressedLength))
|
||||
{
|
||||
Client::Ref().SetPref("version.update", false);
|
||||
prefs.Set("version.update", false);
|
||||
update_cleanup();
|
||||
notifyError("Update failed - try downloading a new version.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
corrupt:
|
||||
notifyError("Downloaded update is corrupted\n" + error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "LuaSmartRef.h"
|
||||
#include "PowderToy.h"
|
||||
|
||||
#include "client/Client.h"
|
||||
#include "prefs/GlobalPrefs.h"
|
||||
#include "common/Platform.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Renderer.h"
|
||||
@ -1321,9 +1321,20 @@ int luatpt_setwindowsize(lua_State* l)
|
||||
int kiosk = luaL_optint(l,2,0);
|
||||
// TODO: handle this the same way as it's handled in PowderToySDL.cpp
|
||||
// > maybe bind the maximum allowed scale to screen size somehow
|
||||
if (scale < 1 || scale > 10) scale = 1;
|
||||
if (kiosk!=1) kiosk = 0;
|
||||
Client::Ref().SetPref("Scale", scale);
|
||||
if (scale < 1 || scale > 10)
|
||||
{
|
||||
scale = 1;
|
||||
}
|
||||
if (kiosk!=1)
|
||||
{
|
||||
kiosk = 0;
|
||||
}
|
||||
{
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
Prefs::DeferWrite dw(prefs);
|
||||
prefs.Set("Scale", scale);
|
||||
prefs.Set("Fullscreen", bool(kiosk));
|
||||
}
|
||||
ui::Engine::Ref().SetScale(scale);
|
||||
ui::Engine::Ref().SetFullscreen(kiosk);
|
||||
return 0;
|
||||
|
@ -44,6 +44,7 @@ else
|
||||
'lua/PlainCommandInterface.cpp',
|
||||
)
|
||||
endif
|
||||
subdir('prefs')
|
||||
subdir('resampler')
|
||||
subdir('simulation')
|
||||
subdir('tasks')
|
||||
|
11
src/prefs/GlobalPrefs.h
Normal file
11
src/prefs/GlobalPrefs.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "Prefs.h"
|
||||
#include "common/ExplicitSingleton.h"
|
||||
|
||||
class GlobalPrefs : public Prefs, public ExplicitSingleton<GlobalPrefs>
|
||||
{
|
||||
public:
|
||||
GlobalPrefs() : Prefs("powder.pref")
|
||||
{
|
||||
}
|
||||
};
|
153
src/prefs/Prefs.cpp
Normal file
153
src/prefs/Prefs.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
#include "Prefs.h"
|
||||
#include "common/Platform.h"
|
||||
#include "common/tpt-rand.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
Prefs::Prefs(ByteString newPath) : path(newPath)
|
||||
{
|
||||
Read();
|
||||
}
|
||||
|
||||
void Prefs::Read()
|
||||
{
|
||||
std::vector<char> data;
|
||||
if (!Platform::ReadFile(data, path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Json::CharReaderBuilder rbuilder;
|
||||
std::unique_ptr<Json::CharReader> const reader(rbuilder.newCharReader());
|
||||
ByteString errs;
|
||||
if (!reader->parse(&data[0], &data[0] + data.size(), &root, &errs))
|
||||
{
|
||||
std::cerr << errs << std::endl;
|
||||
return;
|
||||
}
|
||||
backedByFile = true;
|
||||
}
|
||||
|
||||
void Prefs::ShouldWrite()
|
||||
{
|
||||
shouldWrite = true;
|
||||
Write();
|
||||
}
|
||||
|
||||
void Prefs::Write()
|
||||
{
|
||||
if (deferWriteLevel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!shouldWrite)
|
||||
{
|
||||
return;
|
||||
}
|
||||
shouldWrite = false;
|
||||
Json::StreamWriterBuilder wbuilder;
|
||||
wbuilder["indentation"] = "\t";
|
||||
ByteString data = Json::writeString(wbuilder, root);
|
||||
if (!Platform::WriteFile(std::vector<char>(data.begin(), data.end()), path, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
backedByFile = true;
|
||||
}
|
||||
|
||||
void Prefs::GrabDeferWriteLevel(DeferWriteTag)
|
||||
{
|
||||
deferWriteLevel += 1;
|
||||
}
|
||||
|
||||
void Prefs::DropDeferWriteLevel(DeferWriteTag)
|
||||
{
|
||||
deferWriteLevel -= 1;
|
||||
Write();
|
||||
}
|
||||
|
||||
Json::Value Prefs::GetJson(const Json::Value &node, ByteString path)
|
||||
{
|
||||
if (node.type() != Json::objectValue)
|
||||
{
|
||||
return Json::nullValue;
|
||||
}
|
||||
auto split = path.SplitBy('.');
|
||||
if (!split)
|
||||
{
|
||||
return node[path];
|
||||
}
|
||||
return GetJson(node[split.Before()], split.After());
|
||||
}
|
||||
|
||||
void Prefs::SetJson(Json::Value &node, ByteString path, Json::Value value)
|
||||
{
|
||||
if (node.type() != Json::objectValue)
|
||||
{
|
||||
node = Json::objectValue;
|
||||
}
|
||||
auto split = path.SplitBy('.');
|
||||
if (!split)
|
||||
{
|
||||
node[path] = value;
|
||||
return;
|
||||
}
|
||||
SetJson(node[split.Before()], split.After(), value);
|
||||
}
|
||||
|
||||
template<> Json::Value Prefs::Bipacker<int>::Pack (const int &value) { return Json::Value(value); }
|
||||
template<> int Prefs::Bipacker<int>::Unpack(const Json::Value &value) { return value.asInt(); }
|
||||
|
||||
template<> Json::Value Prefs::Bipacker<unsigned int>::Pack (const unsigned int &value) { return Json::Value(value); }
|
||||
template<> unsigned int Prefs::Bipacker<unsigned int>::Unpack(const Json::Value &value) { return value.asUInt(); }
|
||||
|
||||
template<> Json::Value Prefs::Bipacker<uint64_t>::Pack (const uint64_t &value) { return Json::Value(Json::UInt64(value)); }
|
||||
template<> uint64_t Prefs::Bipacker<uint64_t>::Unpack(const Json::Value &value) { return value.asUInt64(); }
|
||||
|
||||
template<> Json::Value Prefs::Bipacker<float>::Pack (const float &value) { return Json::Value(value); }
|
||||
template<> float Prefs::Bipacker<float>::Unpack(const Json::Value &value) { return value.asFloat(); }
|
||||
|
||||
template<> Json::Value Prefs::Bipacker<bool>::Pack (const bool &value) { return Json::Value(value); }
|
||||
template<> bool Prefs::Bipacker<bool>::Unpack(const Json::Value &value) { return value.asBool(); }
|
||||
|
||||
template<> Json::Value Prefs::Bipacker<ByteString>::Pack (const ByteString &value) { return Json::Value(value); }
|
||||
template<> ByteString Prefs::Bipacker<ByteString>::Unpack(const Json::Value &value) { return value.asString(); }
|
||||
|
||||
template<> Json::Value Prefs::Bipacker<String>::Pack (const String &value) { return Json::Value(value.ToUtf8()); }
|
||||
template<> String Prefs::Bipacker<String>::Unpack(const Json::Value &value) { return ByteString(value.asString()).FromUtf8(); }
|
||||
|
||||
template<class Item>
|
||||
struct Prefs::Bipacker<std::vector<Item>>
|
||||
{
|
||||
static Json::Value Pack(const std::vector<Item> &value);
|
||||
static std::vector<Item> Unpack(const Json::Value &value);
|
||||
};
|
||||
|
||||
template<class Item>
|
||||
Json::Value Prefs::Bipacker<std::vector<Item>>::Pack(const std::vector<Item> &value)
|
||||
{
|
||||
Json::Value array = Json::arrayValue;
|
||||
for (auto item : value)
|
||||
{
|
||||
array.append(Bipacker<Item>::Pack(item));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
template<class Item>
|
||||
std::vector<Item> Prefs::Bipacker<std::vector<Item>>::Unpack(const Json::Value &value)
|
||||
{
|
||||
std::vector<Item> array;
|
||||
if (value.type() != Json::arrayValue)
|
||||
{
|
||||
throw std::exception();
|
||||
}
|
||||
for (auto &item : value)
|
||||
{
|
||||
array.push_back(Bipacker<Item>::Unpack(item));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
template struct Prefs::Bipacker<std::vector<String>>;
|
||||
template struct Prefs::Bipacker<std::vector<ByteString>>;
|
||||
template struct Prefs::Bipacker<std::vector<unsigned int>>;
|
104
src/prefs/Prefs.h
Normal file
104
src/prefs/Prefs.h
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
#include "Config.h"
|
||||
#include "common/String.h"
|
||||
#include <json/json.h>
|
||||
|
||||
class Prefs
|
||||
{
|
||||
struct DeferWriteTag
|
||||
{
|
||||
};
|
||||
|
||||
Json::Value root;
|
||||
static Json::Value GetJson(const Json::Value &node, ByteString path);
|
||||
static void SetJson(Json::Value &node, ByteString path, Json::Value value);
|
||||
|
||||
template<class Type>
|
||||
struct Bipacker
|
||||
{
|
||||
static Json::Value Pack(const Type &value);
|
||||
static Type Unpack(const Json::Value &value);
|
||||
};
|
||||
|
||||
void Read();
|
||||
void Write();
|
||||
void ShouldWrite();
|
||||
unsigned int deferWriteLevel = 0;
|
||||
bool backedByFile = false;
|
||||
bool shouldWrite = false;
|
||||
|
||||
ByteString path;
|
||||
|
||||
Prefs(const Prefs &) = delete;
|
||||
Prefs &operator =(const Prefs &) = delete;
|
||||
|
||||
public:
|
||||
Prefs(ByteString path);
|
||||
|
||||
template<class Type>
|
||||
Type Get(ByteString path, Type defaultValue) const
|
||||
{
|
||||
auto value = GetJson(root, path);
|
||||
if (value != Json::nullValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Bipacker<Type>::Unpack(value);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
template<class Enum, class EnumBase = int>
|
||||
Enum Get(ByteString path, Enum maxValue, Enum defaultValue) const
|
||||
{
|
||||
EnumBase value = Get(path, EnumBase(defaultValue));
|
||||
if (value < 0 || value >= EnumBase(maxValue))
|
||||
{
|
||||
value = EnumBase(defaultValue);
|
||||
}
|
||||
return Enum(value);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void Set(ByteString path, Type value)
|
||||
{
|
||||
SetJson(root, path, Bipacker<Type>::Pack(value));
|
||||
ShouldWrite();
|
||||
}
|
||||
|
||||
void Clear(ByteString path)
|
||||
{
|
||||
SetJson(root, path, Json::nullValue);
|
||||
ShouldWrite();
|
||||
}
|
||||
|
||||
void GrabDeferWriteLevel(DeferWriteTag);
|
||||
void DropDeferWriteLevel(DeferWriteTag);
|
||||
|
||||
struct DeferWrite
|
||||
{
|
||||
Prefs &prefs;
|
||||
|
||||
DeferWrite(const DeferWrite &) = delete;
|
||||
DeferWrite &operator =(const DeferWrite &) = delete;
|
||||
|
||||
DeferWrite(Prefs &newPrefs) : prefs(newPrefs)
|
||||
{
|
||||
prefs.GrabDeferWriteLevel({});
|
||||
}
|
||||
|
||||
~DeferWrite()
|
||||
{
|
||||
prefs.DropDeferWriteLevel({});
|
||||
}
|
||||
};
|
||||
|
||||
bool BackedByFile() const
|
||||
{
|
||||
return backedByFile;
|
||||
}
|
||||
};
|
3
src/prefs/meson.build
Normal file
3
src/prefs/meson.build
Normal file
@ -0,0 +1,3 @@
|
||||
powder_files += files(
|
||||
'Prefs.cpp',
|
||||
)
|
@ -1,5 +1,4 @@
|
||||
#include "Simulation.h"
|
||||
#include "client/Client.h"
|
||||
#include "ElementClasses.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "gui/game/Brush.h"
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "GOLString.h"
|
||||
#include "client/Client.h"
|
||||
|
||||
int ParseGOLString(const String &value)
|
||||
{
|
||||
|
Reference in New Issue
Block a user