Refactor preferences
This commit is contained in:
parent
220844521a
commit
afda2826bf
@ -32,6 +32,7 @@
|
|||||||
#include "X86KillDenormals.h"
|
#include "X86KillDenormals.h"
|
||||||
#include "Misc.h"
|
#include "Misc.h"
|
||||||
|
|
||||||
|
#include "prefs/GlobalPrefs.h"
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
#include "client/GameSave.h"
|
#include "client/GameSave.h"
|
||||||
#include "client/SaveFile.h"
|
#include "client/SaveFile.h"
|
||||||
@ -97,8 +98,9 @@ int GetModifiers()
|
|||||||
|
|
||||||
void LoadWindowPosition()
|
void LoadWindowPosition()
|
||||||
{
|
{
|
||||||
int savedWindowX = Client::Ref().GetPrefInteger("WindowX", INT_MAX);
|
auto &prefs = GlobalPrefs::Ref();
|
||||||
int savedWindowY = Client::Ref().GetPrefInteger("WindowY", INT_MAX);
|
int savedWindowX = prefs.Get("WindowX", INT_MAX);
|
||||||
|
int savedWindowY = prefs.Get("WindowY", INT_MAX);
|
||||||
|
|
||||||
int borderTop, borderLeft;
|
int borderTop, borderLeft;
|
||||||
SDL_GetWindowBordersSize(sdl_window, &borderTop, &borderLeft, nullptr, nullptr);
|
SDL_GetWindowBordersSize(sdl_window, &borderTop, &borderLeft, nullptr, nullptr);
|
||||||
@ -133,8 +135,9 @@ void SaveWindowPosition()
|
|||||||
int borderTop, borderLeft;
|
int borderTop, borderLeft;
|
||||||
SDL_GetWindowBordersSize(sdl_window, &borderTop, &borderLeft, nullptr, nullptr);
|
SDL_GetWindowBordersSize(sdl_window, &borderTop, &borderLeft, nullptr, nullptr);
|
||||||
|
|
||||||
Client::Ref().SetPref("WindowX", x - borderLeft);
|
auto &prefs = GlobalPrefs::Ref();
|
||||||
Client::Ref().SetPref("WindowY", y - borderTop);
|
prefs.Set("WindowX", x - borderLeft);
|
||||||
|
prefs.Set("WindowY", y - borderTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalculateMousePosition(int *x, int *y)
|
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.";
|
message << "\nTo undo this, hit Cancel. You can change this in settings at any time.";
|
||||||
if (!ConfirmPrompt::Blocking("Large screen detected", message.Build()))
|
if (!ConfirmPrompt::Blocking("Large screen detected", message.Build()))
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("Scale", 1);
|
GlobalPrefs::Ref().Set("Scale", 1);
|
||||||
engine->SetScale(1);
|
engine->SetScale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -603,8 +606,21 @@ int GuessBestScale()
|
|||||||
return guess;
|
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[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
|
atexit([]() {
|
||||||
|
explicitSingletons.reset();
|
||||||
|
});
|
||||||
|
explicitSingletons = std::make_unique<ExplicitSingletons>();
|
||||||
#ifdef WIN
|
#ifdef WIN
|
||||||
if constexpr (DEBUG)
|
if constexpr (DEBUG)
|
||||||
{
|
{
|
||||||
@ -710,14 +726,17 @@ int main(int argc, char * argv[])
|
|||||||
SDL_free(ddir);
|
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);
|
auto &prefs = GlobalPrefs::Ref();
|
||||||
resizable = Client::Ref().GetPrefBool("Resizable", false);
|
scale = prefs.Get("Scale", 1);
|
||||||
fullscreen = Client::Ref().GetPrefBool("Fullscreen", false);
|
resizable = prefs.Get("Resizable", false);
|
||||||
altFullscreen = Client::Ref().GetPrefBool("AltFullscreen", false);
|
fullscreen = prefs.Get("Fullscreen", false);
|
||||||
forceIntegerScaling = Client::Ref().GetPrefBool("ForceIntegerScaling", true);
|
altFullscreen = prefs.Get("AltFullscreen", false);
|
||||||
momentumScroll = Client::Ref().GetPrefBool("MomentumScroll", true);
|
forceIntegerScaling = prefs.Get("ForceIntegerScaling", true);
|
||||||
showAvatars = Client::Ref().GetPrefBool("ShowAvatars", true);
|
momentumScroll = prefs.Get("MomentumScroll", true);
|
||||||
|
showAvatars = prefs.Get("ShowAvatars", true);
|
||||||
|
|
||||||
auto true_string = [](ByteString str) {
|
auto true_string = [](ByteString str) {
|
||||||
str = str.ToLower();
|
str = str.ToLower();
|
||||||
@ -736,7 +755,7 @@ int main(int argc, char * argv[])
|
|||||||
if (kioskArg.has_value())
|
if (kioskArg.has_value())
|
||||||
{
|
{
|
||||||
fullscreen = true_string(kioskArg.value());
|
fullscreen = true_string(kioskArg.value());
|
||||||
Client::Ref().SetPref("Fullscreen", fullscreen);
|
prefs.Set("Fullscreen", fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (true_arg(arguments["redirect"]))
|
if (true_arg(arguments["redirect"]))
|
||||||
@ -755,7 +774,7 @@ int main(int argc, char * argv[])
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
scale = scaleArg.value().ToNumber<int>();
|
scale = scaleArg.value().ToNumber<int>();
|
||||||
Client::Ref().SetPref("Scale", scale);
|
prefs.Set("Scale", scale);
|
||||||
}
|
}
|
||||||
catch (const std::runtime_error &e)
|
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;
|
ByteString value;
|
||||||
if (arg.has_value())
|
if (arg.has_value())
|
||||||
{
|
{
|
||||||
@ -772,11 +791,11 @@ int main(int argc, char * argv[])
|
|||||||
{
|
{
|
||||||
value = defaultValue;
|
value = defaultValue;
|
||||||
}
|
}
|
||||||
Client::Ref().SetPref(name, value);
|
prefs.Set(name, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value = Client::Ref().GetPrefByteString(name, defaultValue);
|
value = prefs.Get(name, defaultValue);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -784,8 +803,9 @@ int main(int argc, char * argv[])
|
|||||||
ByteString cafileString = clientConfig(arguments["cafile"], "CAFile", "");
|
ByteString cafileString = clientConfig(arguments["cafile"], "CAFile", "");
|
||||||
ByteString capathString = clientConfig(arguments["capath"], "CAPath", "");
|
ByteString capathString = clientConfig(arguments["capath"], "CAPath", "");
|
||||||
bool disableNetwork = true_arg(arguments["disable-network"]);
|
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();
|
Client::Ref().Initialize();
|
||||||
|
|
||||||
// TODO: maybe bind the maximum allowed scale to screen size somehow
|
// TODO: maybe bind the maximum allowed scale to screen size somehow
|
||||||
@ -799,7 +819,7 @@ int main(int argc, char * argv[])
|
|||||||
scale = GuessBestScale();
|
scale = GuessBestScale();
|
||||||
if (scale > 1)
|
if (scale > 1)
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("Scale", scale);
|
prefs.Set("Scale", scale);
|
||||||
SDL_SetWindowSize(sdl_window, WINDOWW * scale, WINDOWH * scale);
|
SDL_SetWindowSize(sdl_window, WINDOWW * scale, WINDOWH * scale);
|
||||||
showLargeScreenDialog = true;
|
showLargeScreenDialog = true;
|
||||||
}
|
}
|
||||||
@ -819,7 +839,7 @@ int main(int argc, char * argv[])
|
|||||||
engine = &ui::Engine::Ref();
|
engine = &ui::Engine::Ref();
|
||||||
engine->SetMaxSize(desktopWidth, desktopHeight);
|
engine->SetMaxSize(desktopWidth, desktopHeight);
|
||||||
engine->Begin(WINDOWW, WINDOWH);
|
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"]);
|
bool enableBluescreen = !DEBUG && !true_arg(arguments["disable-bluescreen"]);
|
||||||
if (enableBluescreen)
|
if (enableBluescreen)
|
||||||
@ -949,7 +969,6 @@ int main(int argc, char * argv[])
|
|||||||
ui::Engine::Ref().CloseWindow();
|
ui::Engine::Ref().CloseWindow();
|
||||||
delete gameController;
|
delete gameController;
|
||||||
delete ui::Engine::Ref().g;
|
delete ui::Engine::Ref().g;
|
||||||
Client::Ref().Shutdown();
|
|
||||||
if (SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_OPENGL)
|
if (SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_OPENGL)
|
||||||
{
|
{
|
||||||
// * nvidia-460 egl registers callbacks with x11 that end up being called
|
// * nvidia-460 egl registers callbacks with x11 that end up being called
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "Client.h"
|
#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 "client/http/Request.h" // includes curl.h, needs to come first to silence a warning on windows
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -65,48 +66,30 @@ Client::Client():
|
|||||||
updateAvailable(false),
|
updateAvailable(false),
|
||||||
authUser(0, "")
|
authUser(0, "")
|
||||||
{
|
{
|
||||||
//Read config
|
auto &prefs = GlobalPrefs::Ref();
|
||||||
std::ifstream configFile;
|
authUser.UserID = prefs.Get("User.ID", 0);
|
||||||
configFile.open("powder.pref", std::ios::binary);
|
authUser.Username = prefs.Get("User.Username", ByteString(""));
|
||||||
if (configFile)
|
authUser.SessionID = prefs.Get("User.SessionID", ByteString(""));
|
||||||
{
|
authUser.SessionKey = prefs.Get("User.SessionKey", ByteString(""));
|
||||||
try
|
auto elevation = prefs.Get("User.Elevation", ByteString(""));
|
||||||
{
|
|
||||||
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;
|
authUser.UserElevation = User::ElevationNone;
|
||||||
}
|
if (elevation == "Admin")
|
||||||
catch (std::exception &e)
|
|
||||||
{
|
{
|
||||||
|
authUser.UserElevation = User::ElevationAdmin;
|
||||||
}
|
}
|
||||||
configFile.close();
|
if (elevation == "Mod")
|
||||||
firstRun = false;
|
{
|
||||||
|
authUser.UserElevation = User::ElevationModerator;
|
||||||
}
|
}
|
||||||
else
|
firstRun = !prefs.BackedByFile();
|
||||||
firstRun = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::Initialize()
|
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();
|
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()
|
Client::~Client()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Client::SetAuthUser(User user)
|
void Client::SetAuthUser(User user)
|
||||||
{
|
{
|
||||||
authUser = 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();
|
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 Client::DoInstallation()
|
||||||
{
|
{
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
@ -1652,8 +1374,9 @@ bool Client::DoInstallation()
|
|||||||
|
|
||||||
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor)
|
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor)
|
||||||
{
|
{
|
||||||
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
auto &prefs = GlobalPrefs::Ref();
|
||||||
Json::Value newCustomGOLTypes(Json::arrayValue);
|
auto customGOLTypes = prefs.Get("CustomGOL.Types", std::vector<ByteString>{});
|
||||||
|
std::vector<ByteString> newCustomGOLTypes;
|
||||||
bool nameTaken = false;
|
bool nameTaken = false;
|
||||||
for (auto gol : customGOLTypes)
|
for (auto gol : customGOLTypes)
|
||||||
{
|
{
|
||||||
@ -1665,14 +1388,147 @@ bool AddCustomGol(String ruleString, String nameString, unsigned int highColor,
|
|||||||
nameTaken = true;
|
nameTaken = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newCustomGOLTypes.append(gol);
|
newCustomGOLTypes.push_back(gol);
|
||||||
}
|
}
|
||||||
if (nameTaken)
|
if (nameTaken)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb << nameString << " " << ruleString << " " << highColor << " " << lowColor;
|
sb << nameString << " " << ruleString << " " << highColor << " " << lowColor;
|
||||||
newCustomGOLTypes.append(sb.Build().ToUtf8());
|
newCustomGOLTypes.push_back(sb.Build().ToUtf8());
|
||||||
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
|
prefs.Set("CustomGOL.Types", newCustomGOLTypes);
|
||||||
return true;
|
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 <memory>
|
||||||
|
|
||||||
#include "common/String.h"
|
#include "common/String.h"
|
||||||
#include "common/Singleton.h"
|
#include "common/ExplicitSingleton.h"
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
|
|
||||||
#include "User.h"
|
#include "User.h"
|
||||||
@ -47,7 +47,7 @@ namespace http
|
|||||||
{
|
{
|
||||||
class Request;
|
class Request;
|
||||||
}
|
}
|
||||||
class Client: public Singleton<Client> {
|
class Client: public ExplicitSingleton<Client> {
|
||||||
private:
|
private:
|
||||||
String messageOfTheDay;
|
String messageOfTheDay;
|
||||||
std::vector<std::pair<String, ByteString> > serverNotifications;
|
std::vector<std::pair<String, ByteString> > serverNotifications;
|
||||||
@ -73,11 +73,6 @@ private:
|
|||||||
void notifyMessageOfTheDay();
|
void notifyMessageOfTheDay();
|
||||||
void notifyNewNotification(std::pair<String, ByteString> notification);
|
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
|
// Save stealing info
|
||||||
Json::Value authors;
|
Json::Value authors;
|
||||||
|
|
||||||
@ -155,27 +150,8 @@ public:
|
|||||||
RequestStatus ParseServerReturn(ByteString &result, int status, bool json);
|
RequestStatus ParseServerReturn(ByteString &result, int status, bool json);
|
||||||
void Tick();
|
void Tick();
|
||||||
void CheckUpdate(std::unique_ptr<http::Request> &updateRequest, bool checkSession);
|
void CheckUpdate(std::unique_ptr<http::Request> &updateRequest, bool checkSession);
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
// preferences functions
|
String DoMigration(ByteString fromDir, ByteString toDir);
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor);
|
bool AddCustomGol(String ruleString, String nameString, unsigned int highColor, unsigned int lowColor);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "ImageRequest.h"
|
#include "ImageRequest.h"
|
||||||
|
|
||||||
#include "common/Singleton.h"
|
|
||||||
#include "graphics/Graphics.h"
|
#include "graphics/Graphics.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
|
@ -318,8 +318,9 @@ bool ReadFile(std::vector<char> &fileData, ByteString filename)
|
|||||||
return true;
|
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);
|
std::ofstream f(filename, std::ios::binary);
|
||||||
if (f) f.write(&fileData[0], fileData.size());
|
if (f) f.write(&fileData[0], fileData.size());
|
||||||
if (!f)
|
if (!f)
|
||||||
@ -381,4 +382,31 @@ ByteString ExecutableName()
|
|||||||
#endif
|
#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);
|
bool MakeDirectory(ByteString dir);
|
||||||
std::vector<ByteString> DirectorySearch(ByteString directory, ByteString search, std::vector<ByteString> extensions);
|
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 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
|
#ifdef WIN
|
||||||
ByteString WinNarrow(const std::wstring &source);
|
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-rand.cpp',
|
||||||
'tpt-thread-local.cpp',
|
'tpt-thread-local.cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
powder_files += files(
|
|
||||||
'PlatformPowder.cpp',
|
|
||||||
)
|
|
||||||
|
@ -13,9 +13,9 @@ public:
|
|||||||
int ReturnStatus;
|
int ReturnStatus;
|
||||||
String ReturnValue;
|
String ReturnValue;
|
||||||
|
|
||||||
operator ByteString() const
|
operator String() const
|
||||||
{
|
{
|
||||||
return Command.ToUtf8();
|
return Command;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
#include "ConsoleModel.h"
|
#include "ConsoleModel.h"
|
||||||
|
|
||||||
#include "ConsoleView.h"
|
#include "ConsoleView.h"
|
||||||
|
#include "prefs/GlobalPrefs.h"
|
||||||
#include "client/Client.h"
|
|
||||||
|
|
||||||
ConsoleModel::ConsoleModel() {
|
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)
|
for(std::vector<String>::reverse_iterator iter = previousHistory.rbegin(), end = previousHistory.rend(); iter != end; ++iter)
|
||||||
{
|
{
|
||||||
if(previousCommands.size()<25)
|
if(previousCommands.size()<25)
|
||||||
@ -48,7 +46,7 @@ void ConsoleModel::AddLastCommand(ConsoleCommand command)
|
|||||||
if(previousCommands.size()>25)
|
if(previousCommands.size()>25)
|
||||||
previousCommands.pop_front();
|
previousCommands.pop_front();
|
||||||
currentCommandIndex = previousCommands.size();
|
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();
|
notifyPreviousCommandsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "Favorite.h"
|
#include "Favorite.h"
|
||||||
|
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include "client/Client.h"
|
#include "prefs/GlobalPrefs.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -42,10 +42,10 @@ void Favorite::RemoveFavorite(ByteString identifier)
|
|||||||
|
|
||||||
void Favorite::SaveFavoritesToPrefs()
|
void Favorite::SaveFavoritesToPrefs()
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("Favorites", std::vector<Json::Value>(favoritesList.begin(), favoritesList.end()));
|
GlobalPrefs::Ref().Set("Favorites", favoritesList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Favorite::LoadFavoritesFromPrefs()
|
void Favorite::LoadFavoritesFromPrefs()
|
||||||
{
|
{
|
||||||
favoritesList = Client::Ref().GetPrefByteStringArray("Favorites");
|
favoritesList = GlobalPrefs::Ref().Get("Favorites", std::vector<ByteString>{});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "Tool.h"
|
#include "Tool.h"
|
||||||
|
|
||||||
|
#include "prefs/GlobalPrefs.h"
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
#include "common/tpt-rand.h"
|
#include "common/tpt-rand.h"
|
||||||
#include "simulation/GOLString.h"
|
#include "simulation/GOLString.h"
|
||||||
@ -105,8 +106,9 @@ toolSelection(toolSelection)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ruleField->SetText(Client::Ref().GetPrefString("CustomGOL.Rule", "B3/S23"));
|
auto &prefs = GlobalPrefs::Ref();
|
||||||
nameField->SetText(Client::Ref().GetPrefString("CustomGOL.Name", "CGOL"));
|
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.Red = RNG::Ref().between(0x80, 0xFF);
|
||||||
highColour.Green = RNG::Ref().between(0x80, 0xFF);
|
highColour.Green = RNG::Ref().between(0x80, 0xFF);
|
||||||
highColour.Blue = 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.
|
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 color1 = (((highColour.Red << 8) | highColour.Green) << 8) | highColour.Blue;
|
||||||
auto color2 = (((lowColour.Red << 8) | lowColour.Green) << 8) | lowColour.Blue;
|
auto color2 = (((lowColour.Red << 8) | lowColour.Green) << 8) | lowColour.Blue;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "GameControllerEvents.h"
|
#include "GameControllerEvents.h"
|
||||||
#include "lua/CommandInterface.h"
|
#include "lua/CommandInterface.h"
|
||||||
|
|
||||||
|
#include "prefs/GlobalPrefs.h"
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
#include "client/GameSave.h"
|
#include "client/GameSave.h"
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
@ -88,7 +89,7 @@ GameController::GameController():
|
|||||||
gameView->AttachController(this);
|
gameView->AttachController(this);
|
||||||
gameModel->AddObserver(gameView);
|
gameModel->AddObserver(gameView);
|
||||||
|
|
||||||
gameView->SetDebugHUD(Client::Ref().GetPrefBool("Renderer.DebugMode", false));
|
gameView->SetDebugHUD(GlobalPrefs::Ref().Get("Renderer.DebugMode", false));
|
||||||
|
|
||||||
CommandInterface::Create(this, gameModel);
|
CommandInterface::Create(this, gameModel);
|
||||||
|
|
||||||
@ -1352,7 +1353,6 @@ void GameController::OpenOptions()
|
|||||||
{
|
{
|
||||||
options = new OptionsController(gameModel, [this] {
|
options = new OptionsController(gameModel, [this] {
|
||||||
gameModel->UpdateQuickOptions();
|
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());
|
ui::Engine::Ref().ShowWindow(options->GetView());
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "QuickOptions.h"
|
#include "QuickOptions.h"
|
||||||
#include "lua/CommandInterface.h"
|
#include "lua/CommandInterface.h"
|
||||||
|
|
||||||
|
#include "prefs/GlobalPrefs.h"
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
#include "client/GameSave.h"
|
#include "client/GameSave.h"
|
||||||
#include "client/SaveFile.h"
|
#include "client/SaveFile.h"
|
||||||
@ -67,56 +68,51 @@ GameModel::GameModel():
|
|||||||
std::fill(regularToolset, regularToolset+4, (Tool*)NULL);
|
std::fill(regularToolset, regularToolset+4, (Tool*)NULL);
|
||||||
|
|
||||||
//Default render prefs
|
//Default render prefs
|
||||||
std::vector<unsigned int> tempArray;
|
ren->SetRenderMode({
|
||||||
tempArray.push_back(RENDER_FIRE);
|
RENDER_FIRE,
|
||||||
tempArray.push_back(RENDER_EFFE);
|
RENDER_EFFE,
|
||||||
tempArray.push_back(RENDER_BASC);
|
RENDER_BASC,
|
||||||
ren->SetRenderMode(tempArray);
|
});
|
||||||
tempArray.clear();
|
ren->SetDisplayMode({});
|
||||||
|
|
||||||
ren->SetDisplayMode(tempArray);
|
|
||||||
|
|
||||||
ren->SetColourMode(0);
|
ren->SetColourMode(0);
|
||||||
|
|
||||||
//Load config into renderer
|
//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");
|
auto displayModes = prefs.Get("Renderer.DisplayModes", std::vector<unsigned int>{});
|
||||||
if(tempArray.size())
|
if (displayModes.size())
|
||||||
{
|
{
|
||||||
std::vector<unsigned int> displayModes(tempArray.begin(), tempArray.end());
|
|
||||||
ren->SetDisplayMode(displayModes);
|
ren->SetDisplayMode(displayModes);
|
||||||
}
|
}
|
||||||
|
auto renderModes = prefs.Get("Renderer.RenderModes", std::vector<unsigned int>{});
|
||||||
tempArray = Client::Ref().GetPrefUIntegerArray("Renderer.RenderModes");
|
if (renderModes.size())
|
||||||
if(tempArray.size())
|
|
||||||
{
|
{
|
||||||
std::vector<unsigned int> renderModes(tempArray.begin(), tempArray.end());
|
|
||||||
ren->SetRenderMode(renderModes);
|
ren->SetRenderMode(renderModes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ren->gravityFieldEnabled = Client::Ref().GetPrefBool("Renderer.GravityField", false);
|
ren->gravityFieldEnabled = prefs.Get("Renderer.GravityField", false);
|
||||||
ren->decorations_enable = Client::Ref().GetPrefBool("Renderer.Decorations", true);
|
ren->decorations_enable = prefs.Get("Renderer.Decorations", true);
|
||||||
|
|
||||||
//Load config into simulation
|
//Load config into simulation
|
||||||
edgeMode = Client::Ref().GetPrefInteger("Simulation.EdgeMode", 0);
|
edgeMode = prefs.Get("Simulation.EdgeMode", 0); // TODO: EdgeMode enum
|
||||||
sim->SetEdgeMode(edgeMode);
|
sim->SetEdgeMode(edgeMode);
|
||||||
ambientAirTemp = float(R_TEMP) + 273.15f;
|
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)
|
if (MIN_TEMP <= temp && MAX_TEMP >= temp)
|
||||||
{
|
{
|
||||||
ambientAirTemp = temp;
|
ambientAirTemp = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sim->air->ambientAirTemp = ambientAirTemp;
|
sim->air->ambientAirTemp = ambientAirTemp;
|
||||||
decoSpace = Client::Ref().GetPrefInteger("Simulation.DecoSpace", 0);
|
decoSpace = prefs.Get("Simulation.DecoSpace", 0); // TODO: DecoSpace enum
|
||||||
sim->SetDecoSpace(decoSpace);
|
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)
|
if (ngrav_enable)
|
||||||
sim->grav->start_grav_async();
|
sim->grav->start_grav_async();
|
||||||
sim->aheat_enable = Client::Ref().GetPrefInteger("Simulation.AmbientHeat", 0);
|
sim->aheat_enable = prefs.Get("Simulation.AmbientHeat", 0); // TODO: AmbientHeat enum
|
||||||
sim->pretty_powder = Client::Ref().GetPrefInteger("Simulation.PrettyPowder", 0);
|
sim->pretty_powder = prefs.Get("Simulation.PrettyPowder", 0); // TODO: PrettyPowder enum
|
||||||
|
|
||||||
Favorite::Ref().LoadFavoritesFromPrefs();
|
Favorite::Ref().LoadFavoritesFromPrefs();
|
||||||
|
|
||||||
@ -128,14 +124,14 @@ GameModel::GameModel():
|
|||||||
|
|
||||||
BuildMenus();
|
BuildMenus();
|
||||||
|
|
||||||
perfectCircle = Client::Ref().GetPrefBool("PerfectCircleBrush", true);
|
perfectCircle = prefs.Get("PerfectCircleBrush", true);
|
||||||
BuildBrushList();
|
BuildBrushList();
|
||||||
|
|
||||||
//Set default decoration colour
|
//Set default decoration colour
|
||||||
unsigned char colourR = std::min(Client::Ref().GetPrefInteger("Decoration.Red", 200), 255);
|
unsigned char colourR = std::max(std::min(prefs.Get("Decoration.Red", 200), 255), 0);
|
||||||
unsigned char colourG = std::min(Client::Ref().GetPrefInteger("Decoration.Green", 100), 255);
|
unsigned char colourG = std::max(std::min(prefs.Get("Decoration.Green", 100), 255), 0);
|
||||||
unsigned char colourB = std::min(Client::Ref().GetPrefInteger("Decoration.Blue", 50), 255);
|
unsigned char colourB = std::max(std::min(prefs.Get("Decoration.Blue", 50), 255), 0);
|
||||||
unsigned char colourA = std::min(Client::Ref().GetPrefInteger("Decoration.Alpha", 255), 255);
|
unsigned char colourA = std::max(std::min(prefs.Get("Decoration.Alpha", 255), 255), 0);
|
||||||
|
|
||||||
SetColourSelectorColour(ui::Colour(colourR, colourG, colourB, colourA));
|
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, 255));
|
||||||
colourPresets.push_back(ui::Colour(0, 0, 0));
|
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)
|
// cap due to memory usage (this is about 3.4GB of RAM)
|
||||||
if (undoHistoryLimit > 200)
|
if (undoHistoryLimit > 200)
|
||||||
SetUndoHistoryLimit(200);
|
SetUndoHistoryLimit(200);
|
||||||
|
|
||||||
mouseClickRequired = Client::Ref().GetPrefBool("MouseClickRequired", false);
|
mouseClickRequired = prefs.Get("MouseClickRequired", false);
|
||||||
includePressure = Client::Ref().GetPrefBool("Simulation.IncludePressure", true);
|
includePressure = prefs.Get("Simulation.IncludePressure", true);
|
||||||
temperatureScale = Client::Ref().GetPrefInteger("Renderer.TemperatureScale", 1);
|
temperatureScale = prefs.Get("Renderer.TemperatureScale", 1); // TODO: TemperatureScale enum
|
||||||
|
|
||||||
ClearSimulation();
|
ClearSimulation();
|
||||||
}
|
}
|
||||||
|
|
||||||
GameModel::~GameModel()
|
GameModel::~GameModel()
|
||||||
|
{
|
||||||
|
auto &prefs = GlobalPrefs::Ref();
|
||||||
{
|
{
|
||||||
//Save to config:
|
//Save to config:
|
||||||
Client::Ref().SetPref("Renderer.ColourMode", ren->GetColourMode());
|
Prefs::DeferWrite dw(prefs);
|
||||||
|
prefs.Set("Renderer.ColourMode", ren->GetColourMode());
|
||||||
std::vector<unsigned int> displayModes = ren->GetDisplayMode();
|
prefs.Set("Renderer.DisplayModes", ren->GetDisplayMode());
|
||||||
Client::Ref().SetPref("Renderer.DisplayModes", std::vector<Json::Value>(displayModes.begin(), displayModes.end()));
|
prefs.Set("Renderer.RenderModes", ren->GetRenderMode());
|
||||||
|
prefs.Set("Renderer.GravityField", (bool)ren->gravityFieldEnabled);
|
||||||
std::vector<unsigned int> renderModes = ren->GetRenderMode();
|
prefs.Set("Renderer.Decorations", (bool)ren->decorations_enable);
|
||||||
Client::Ref().SetPref("Renderer.RenderModes", std::vector<Json::Value>(renderModes.begin(), renderModes.end()));
|
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());
|
||||||
Client::Ref().SetPref("Renderer.GravityField", (bool)ren->gravityFieldEnabled);
|
prefs.Set("Simulation.AmbientHeat", sim->aheat_enable);
|
||||||
Client::Ref().SetPref("Renderer.Decorations", (bool)ren->decorations_enable);
|
prefs.Set("Simulation.PrettyPowder", sim->pretty_powder);
|
||||||
Client::Ref().SetPref("Renderer.DebugMode", ren->debugLines); //These two should always be equivalent, even though they are different things
|
prefs.Set("Decoration.Red", (int)colour.Red);
|
||||||
|
prefs.Set("Decoration.Green", (int)colour.Green);
|
||||||
Client::Ref().SetPref("Simulation.NewtonianGravity", sim->grav->IsEnabled());
|
prefs.Set("Decoration.Blue", (int)colour.Blue);
|
||||||
Client::Ref().SetPref("Simulation.AmbientHeat", sim->aheat_enable);
|
prefs.Set("Decoration.Alpha", (int)colour.Alpha);
|
||||||
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);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < menuList.size(); i++)
|
for (size_t i = 0; i < menuList.size(); i++)
|
||||||
{
|
{
|
||||||
@ -317,8 +310,9 @@ void GameModel::BuildMenus()
|
|||||||
menuList[SC_LIFE]->AddTool(tempTool);
|
menuList[SC_LIFE]->AddTool(tempTool);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
auto &prefs = GlobalPrefs::Ref();
|
||||||
Json::Value validatedCustomLifeTypes(Json::arrayValue);
|
auto customGOLTypes = prefs.Get("CustomGOL.Types", std::vector<ByteString>{});
|
||||||
|
std::vector<ByteString> validatedCustomLifeTypes;
|
||||||
std::vector<Simulation::CustomGOLData> newCustomGol;
|
std::vector<Simulation::CustomGOLData> newCustomGol;
|
||||||
for (auto gol : customGOLTypes)
|
for (auto gol : customGOLTypes)
|
||||||
{
|
{
|
||||||
@ -351,10 +345,10 @@ void GameModel::BuildMenus()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
newCustomGol.push_back(gd);
|
newCustomGol.push_back(gd);
|
||||||
validatedCustomLifeTypes.append(gol);
|
validatedCustomLifeTypes.push_back(gol);
|
||||||
}
|
}
|
||||||
// All custom rules that fail validation will be removed
|
// All custom rules that fail validation will be removed
|
||||||
Client::Ref().SetPref("CustomGOL.Types", validatedCustomLifeTypes);
|
prefs.Set("CustomGOL.Types", validatedCustomLifeTypes);
|
||||||
for (auto &gd : newCustomGol)
|
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);
|
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_)
|
void GameModel::SetUndoHistoryLimit(unsigned int undoHistoryLimit_)
|
||||||
{
|
{
|
||||||
undoHistoryLimit = undoHistoryLimit_;
|
undoHistoryLimit = undoHistoryLimit_;
|
||||||
Client::Ref().SetPref("Simulation.UndoHistoryLimit", undoHistoryLimit);
|
GlobalPrefs::Ref().Set("Simulation.UndoHistoryLimit", undoHistoryLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameModel::SetVote(int direction)
|
void GameModel::SetVote(int direction)
|
||||||
@ -1653,17 +1647,18 @@ void GameModel::SetPerfectCircle(bool perfectCircle)
|
|||||||
bool GameModel::RemoveCustomGOLType(const ByteString &identifier)
|
bool GameModel::RemoveCustomGOLType(const ByteString &identifier)
|
||||||
{
|
{
|
||||||
bool removedAny = false;
|
bool removedAny = false;
|
||||||
auto customGOLTypes = Client::Ref().GetPrefByteStringArray("CustomGOL.Types");
|
auto &prefs = GlobalPrefs::Ref();
|
||||||
Json::Value newCustomGOLTypes(Json::arrayValue);
|
auto customGOLTypes = prefs.Get("CustomGOL.Types", std::vector<ByteString>{});
|
||||||
|
std::vector<ByteString> newCustomGOLTypes;
|
||||||
for (auto gol : customGOLTypes)
|
for (auto gol : customGOLTypes)
|
||||||
{
|
{
|
||||||
auto parts = gol.PartitionBy(' ');
|
auto parts = gol.PartitionBy(' ');
|
||||||
if (parts.size() && "DEFAULT_PT_LIFECUST_" + parts[0] == identifier)
|
if (parts.size() && "DEFAULT_PT_LIFECUST_" + parts[0] == identifier)
|
||||||
removedAny = true;
|
removedAny = true;
|
||||||
else
|
else
|
||||||
newCustomGOLTypes.append(gol);
|
newCustomGOLTypes.push_back(gol);
|
||||||
}
|
}
|
||||||
Client::Ref().SetPref("CustomGOL.Types", newCustomGOLTypes);
|
prefs.Set("CustomGOL.Types", newCustomGOLTypes);
|
||||||
BuildMenus();
|
BuildMenus();
|
||||||
return removedAny;
|
return removedAny;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "Tool.h"
|
#include "Tool.h"
|
||||||
|
|
||||||
#include "client/Client.h"
|
#include "prefs/GlobalPrefs.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "Format.h"
|
#include "Format.h"
|
||||||
|
|
||||||
@ -75,12 +75,14 @@ sim(sim_)
|
|||||||
{
|
{
|
||||||
property->AddOption(std::pair<String, int>(properties[i].Name.FromAscii(), i));
|
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 = new ui::Textbox(ui::Point(8, 46), ui::Point(Size.X-16, 16), "", "[value]");
|
||||||
textField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
textField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||||
textField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
textField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
||||||
textField->SetText(Client::Ref().GetPrefString("Prop.Value", ""));
|
textField->SetText(prefs.Get("Prop.Value", String("")));
|
||||||
AddComponent(textField);
|
AddComponent(textField);
|
||||||
FocusComponent(textField);
|
FocusComponent(textField);
|
||||||
SetProperty(false);
|
SetProperty(false);
|
||||||
@ -216,8 +218,12 @@ void PropertyWindow::SetProperty(bool warn)
|
|||||||
new ErrorMessage("Could not set property", "Invalid value provided");
|
new ErrorMessage("Could not set property", "Invalid value provided");
|
||||||
return;
|
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/Air.h"
|
||||||
#include "simulation/Gravity.h"
|
#include "simulation/Gravity.h"
|
||||||
|
|
||||||
#include "client/Client.h"
|
#include "prefs/GlobalPrefs.h"
|
||||||
|
|
||||||
#include "gui/interface/Engine.h"
|
#include "gui/interface/Engine.h"
|
||||||
#include "gui/game/GameModel.h"
|
#include "gui/game/GameModel.h"
|
||||||
@ -85,7 +85,7 @@ int OptionsModel::GetEdgeMode()
|
|||||||
}
|
}
|
||||||
void OptionsModel::SetEdgeMode(int edgeMode)
|
void OptionsModel::SetEdgeMode(int edgeMode)
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("Simulation.EdgeMode", edgeMode);
|
GlobalPrefs::Ref().Set("Simulation.EdgeMode", edgeMode);
|
||||||
gModel->SetEdgeMode(edgeMode);
|
gModel->SetEdgeMode(edgeMode);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ int OptionsModel::GetTemperatureScale()
|
|||||||
}
|
}
|
||||||
void OptionsModel::SetTemperatureScale(int temperatureScale)
|
void OptionsModel::SetTemperatureScale(int temperatureScale)
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("Renderer.TemperatureScale", temperatureScale);
|
GlobalPrefs::Ref().Set("Renderer.TemperatureScale", temperatureScale);
|
||||||
gModel->SetTemperatureScale(temperatureScale);
|
gModel->SetTemperatureScale(temperatureScale);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ float OptionsModel::GetAmbientAirTemperature()
|
|||||||
}
|
}
|
||||||
void OptionsModel::SetAmbientAirTemperature(float ambientAirTemp)
|
void OptionsModel::SetAmbientAirTemperature(float ambientAirTemp)
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("Simulation.AmbientAirTemp", ambientAirTemp);
|
GlobalPrefs::Ref().Set("Simulation.AmbientAirTemp", ambientAirTemp);
|
||||||
gModel->SetAmbientAirTemperature(ambientAirTemp);
|
gModel->SetAmbientAirTemperature(ambientAirTemp);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ int OptionsModel::GetScale()
|
|||||||
void OptionsModel::SetScale(int scale)
|
void OptionsModel::SetScale(int scale)
|
||||||
{
|
{
|
||||||
ui::Engine::Ref().SetScale(scale);
|
ui::Engine::Ref().SetScale(scale);
|
||||||
Client::Ref().SetPref("Scale", int(scale));
|
GlobalPrefs::Ref().Set("Scale", int(scale));
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ bool OptionsModel::GetResizable()
|
|||||||
void OptionsModel::SetResizable(bool resizable)
|
void OptionsModel::SetResizable(bool resizable)
|
||||||
{
|
{
|
||||||
ui::Engine::Ref().SetResizable(resizable);
|
ui::Engine::Ref().SetResizable(resizable);
|
||||||
Client::Ref().SetPref("Resizable", resizable);
|
GlobalPrefs::Ref().Set("Resizable", resizable);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ bool OptionsModel::GetFullscreen()
|
|||||||
void OptionsModel::SetFullscreen(bool fullscreen)
|
void OptionsModel::SetFullscreen(bool fullscreen)
|
||||||
{
|
{
|
||||||
ui::Engine::Ref().SetFullscreen(fullscreen);
|
ui::Engine::Ref().SetFullscreen(fullscreen);
|
||||||
Client::Ref().SetPref("Fullscreen", fullscreen);
|
GlobalPrefs::Ref().Set("Fullscreen", fullscreen);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ bool OptionsModel::GetAltFullscreen()
|
|||||||
void OptionsModel::SetAltFullscreen(bool altFullscreen)
|
void OptionsModel::SetAltFullscreen(bool altFullscreen)
|
||||||
{
|
{
|
||||||
ui::Engine::Ref().SetAltFullscreen(altFullscreen);
|
ui::Engine::Ref().SetAltFullscreen(altFullscreen);
|
||||||
Client::Ref().SetPref("AltFullscreen", altFullscreen);
|
GlobalPrefs::Ref().Set("AltFullscreen", altFullscreen);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ bool OptionsModel::GetForceIntegerScaling()
|
|||||||
void OptionsModel::SetForceIntegerScaling(bool forceIntegerScaling)
|
void OptionsModel::SetForceIntegerScaling(bool forceIntegerScaling)
|
||||||
{
|
{
|
||||||
ui::Engine::Ref().SetForceIntegerScaling(forceIntegerScaling);
|
ui::Engine::Ref().SetForceIntegerScaling(forceIntegerScaling);
|
||||||
Client::Ref().SetPref("ForceIntegerScaling", forceIntegerScaling);
|
GlobalPrefs::Ref().Set("ForceIntegerScaling", forceIntegerScaling);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ bool OptionsModel::GetFastQuit()
|
|||||||
void OptionsModel::SetFastQuit(bool fastquit)
|
void OptionsModel::SetFastQuit(bool fastquit)
|
||||||
{
|
{
|
||||||
ui::Engine::Ref().SetFastQuit(fastquit);
|
ui::Engine::Ref().SetFastQuit(fastquit);
|
||||||
Client::Ref().SetPref("FastQuit", bool(fastquit));
|
GlobalPrefs::Ref().Set("FastQuit", bool(fastquit));
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +220,7 @@ int OptionsModel::GetDecoSpace()
|
|||||||
}
|
}
|
||||||
void OptionsModel::SetDecoSpace(int decoSpace)
|
void OptionsModel::SetDecoSpace(int decoSpace)
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("Simulation.DecoSpace", decoSpace);
|
GlobalPrefs::Ref().Set("Simulation.DecoSpace", decoSpace);
|
||||||
gModel->SetDecoSpace(decoSpace);
|
gModel->SetDecoSpace(decoSpace);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ bool OptionsModel::GetShowAvatars()
|
|||||||
void OptionsModel::SetShowAvatars(bool state)
|
void OptionsModel::SetShowAvatars(bool state)
|
||||||
{
|
{
|
||||||
ui::Engine::Ref().ShowAvatars = state;
|
ui::Engine::Ref().ShowAvatars = state;
|
||||||
Client::Ref().SetPref("ShowAvatars", state);
|
GlobalPrefs::Ref().Set("ShowAvatars", state);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ bool OptionsModel::GetMouseClickRequired()
|
|||||||
|
|
||||||
void OptionsModel::SetMouseClickRequired(bool mouseClickRequired)
|
void OptionsModel::SetMouseClickRequired(bool mouseClickRequired)
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("MouseClickRequired", mouseClickRequired);
|
GlobalPrefs::Ref().Set("MouseClickRequired", mouseClickRequired);
|
||||||
gModel->SetMouseClickRequired(mouseClickRequired);
|
gModel->SetMouseClickRequired(mouseClickRequired);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
@ -256,7 +256,7 @@ bool OptionsModel::GetIncludePressure()
|
|||||||
|
|
||||||
void OptionsModel::SetIncludePressure(bool includePressure)
|
void OptionsModel::SetIncludePressure(bool includePressure)
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("Simulation.IncludePressure", includePressure);
|
GlobalPrefs::Ref().Set("Simulation.IncludePressure", includePressure);
|
||||||
gModel->SetIncludePressure(includePressure);
|
gModel->SetIncludePressure(includePressure);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
@ -268,7 +268,7 @@ bool OptionsModel::GetPerfectCircle()
|
|||||||
|
|
||||||
void OptionsModel::SetPerfectCircle(bool perfectCircle)
|
void OptionsModel::SetPerfectCircle(bool perfectCircle)
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("PerfectCircleBrush", perfectCircle);
|
GlobalPrefs::Ref().Set("PerfectCircleBrush", perfectCircle);
|
||||||
gModel->SetPerfectCircle(perfectCircle);
|
gModel->SetPerfectCircle(perfectCircle);
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
@ -280,7 +280,7 @@ bool OptionsModel::GetMomentumScroll()
|
|||||||
|
|
||||||
void OptionsModel::SetMomentumScroll(bool state)
|
void OptionsModel::SetMomentumScroll(bool state)
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("MomentumScroll", state);
|
GlobalPrefs::Ref().Set("MomentumScroll", state);
|
||||||
ui::Engine::Ref().MomentumScroll = state;
|
ui::Engine::Ref().MomentumScroll = state;
|
||||||
notifySettingsChanged();
|
notifySettingsChanged();
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "graphics/Renderer.h"
|
#include "graphics/Renderer.h"
|
||||||
#include "gui/Style.h"
|
#include "gui/Style.h"
|
||||||
#include "simulation/ElementDefs.h"
|
#include "simulation/ElementDefs.h"
|
||||||
|
#include "client/Client.h"
|
||||||
|
|
||||||
#include "gui/dialogues/ConfirmPrompt.h"
|
#include "gui/dialogues/ConfirmPrompt.h"
|
||||||
#include "gui/dialogues/InformationMessage.h"
|
#include "gui/dialogues/InformationMessage.h"
|
||||||
@ -420,7 +421,7 @@ OptionsView::OptionsView():
|
|||||||
ByteString to = Platform::sharedCwd;
|
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" +
|
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.", { [=] () {
|
"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);
|
new InformationMessage("Migration Complete", ret, false);
|
||||||
} });
|
} });
|
||||||
} });
|
} });
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Update.h"
|
#include "Update.h"
|
||||||
|
|
||||||
|
#include "prefs/GlobalPrefs.h"
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
@ -32,7 +33,13 @@ private:
|
|||||||
}
|
}
|
||||||
bool doWork() override
|
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);
|
auto request = std::make_unique<http::Request>(updateName);
|
||||||
request->Start();
|
request->Start();
|
||||||
notifyStatus("Downloading update");
|
notifyStatus("Downloading update");
|
||||||
@ -48,15 +55,11 @@ private:
|
|||||||
auto [ status, data ] = request->Finish();
|
auto [ status, data ] = request->Finish();
|
||||||
if (status!=200)
|
if (status!=200)
|
||||||
{
|
{
|
||||||
error = String::Build("Server responded with Status ", status);
|
return niceNotifyError("Could not download update: " + String::Build("Server responded with Status ", status));
|
||||||
notifyError("Could not download update: " + error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (!data.size())
|
if (!data.size())
|
||||||
{
|
{
|
||||||
error = "Server responded with nothing";
|
return niceNotifyError("Server did not return any data");
|
||||||
notifyError("Server did not return any data");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyStatus("Unpacking update");
|
notifyStatus("Unpacking update");
|
||||||
@ -66,13 +69,11 @@ private:
|
|||||||
|
|
||||||
if(data.size()<16)
|
if(data.size()<16)
|
||||||
{
|
{
|
||||||
error = String::Build("Unsufficient data, got ", data.size(), " bytes");
|
return niceNotifyError(String::Build("Unsufficient data, got ", data.size(), " bytes"));
|
||||||
goto corrupt;
|
|
||||||
}
|
}
|
||||||
if (data[0]!=0x42 || data[1]!=0x75 || data[2]!=0x54 || data[3]!=0x54)
|
if (data[0]!=0x42 || data[1]!=0x75 || data[2]!=0x54 || data[3]!=0x54)
|
||||||
{
|
{
|
||||||
error = "Invalid update format";
|
return niceNotifyError("Invalid update format");
|
||||||
goto corrupt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uncompressedLength = (unsigned char)data[4];
|
uncompressedLength = (unsigned char)data[4];
|
||||||
@ -80,40 +81,28 @@ private:
|
|||||||
uncompressedLength |= ((unsigned char)data[6])<<16;
|
uncompressedLength |= ((unsigned char)data[6])<<16;
|
||||||
uncompressedLength |= ((unsigned char)data[7])<<24;
|
uncompressedLength |= ((unsigned char)data[7])<<24;
|
||||||
|
|
||||||
char * res;
|
std::vector<char> res(uncompressedLength);
|
||||||
res = (char *)malloc(uncompressedLength);
|
|
||||||
if (!res)
|
|
||||||
{
|
|
||||||
error = String::Build("Unable to allocate ", uncompressedLength, " bytes of memory for decompression");
|
|
||||||
goto corrupt;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dstate;
|
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)
|
if (dstate)
|
||||||
{
|
{
|
||||||
error = String::Build("Unable to decompress update: ", dstate);
|
return niceNotifyError(String::Build("Unable to decompress update: ", dstate));
|
||||||
free(res);
|
|
||||||
goto corrupt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyStatus("Applying update");
|
notifyStatus("Applying update");
|
||||||
notifyProgress(-1);
|
notifyProgress(-1);
|
||||||
|
|
||||||
Client::Ref().SetPref("version.update", true);
|
prefs.Set("version.update", true);
|
||||||
if (update_start(res, uncompressedLength))
|
if (update_start(&res[0], uncompressedLength))
|
||||||
{
|
{
|
||||||
Client::Ref().SetPref("version.update", false);
|
prefs.Set("version.update", false);
|
||||||
update_cleanup();
|
update_cleanup();
|
||||||
notifyError("Update failed - try downloading a new version.");
|
notifyError("Update failed - try downloading a new version.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
corrupt:
|
|
||||||
notifyError("Downloaded update is corrupted\n" + error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "LuaSmartRef.h"
|
#include "LuaSmartRef.h"
|
||||||
#include "PowderToy.h"
|
#include "PowderToy.h"
|
||||||
|
|
||||||
#include "client/Client.h"
|
#include "prefs/GlobalPrefs.h"
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
#include "graphics/Graphics.h"
|
#include "graphics/Graphics.h"
|
||||||
#include "graphics/Renderer.h"
|
#include "graphics/Renderer.h"
|
||||||
@ -1321,9 +1321,20 @@ int luatpt_setwindowsize(lua_State* l)
|
|||||||
int kiosk = luaL_optint(l,2,0);
|
int kiosk = luaL_optint(l,2,0);
|
||||||
// TODO: handle this the same way as it's handled in PowderToySDL.cpp
|
// TODO: handle this the same way as it's handled in PowderToySDL.cpp
|
||||||
// > maybe bind the maximum allowed scale to screen size somehow
|
// > maybe bind the maximum allowed scale to screen size somehow
|
||||||
if (scale < 1 || scale > 10) scale = 1;
|
if (scale < 1 || scale > 10)
|
||||||
if (kiosk!=1) kiosk = 0;
|
{
|
||||||
Client::Ref().SetPref("Scale", scale);
|
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().SetScale(scale);
|
||||||
ui::Engine::Ref().SetFullscreen(kiosk);
|
ui::Engine::Ref().SetFullscreen(kiosk);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -44,6 +44,7 @@ else
|
|||||||
'lua/PlainCommandInterface.cpp',
|
'lua/PlainCommandInterface.cpp',
|
||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
|
subdir('prefs')
|
||||||
subdir('resampler')
|
subdir('resampler')
|
||||||
subdir('simulation')
|
subdir('simulation')
|
||||||
subdir('tasks')
|
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 "Simulation.h"
|
||||||
#include "client/Client.h"
|
|
||||||
#include "ElementClasses.h"
|
#include "ElementClasses.h"
|
||||||
#include "graphics/Renderer.h"
|
#include "graphics/Renderer.h"
|
||||||
#include "gui/game/Brush.h"
|
#include "gui/game/Brush.h"
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "GOLString.h"
|
#include "GOLString.h"
|
||||||
#include "client/Client.h"
|
|
||||||
|
|
||||||
int ParseGOLString(const String &value)
|
int ParseGOLString(const String &value)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user