mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-22 17:49:43 +01:00
Move all settings to settings.vvv
The game previously did this dumb thing where it lumped in all its settings with its file that tracked your records and unlocks, `unlock.vvv`. It wasn't really an issue, until 2.3 came along and added a few settings, suddenly making a problem where 2.3 settings would be reset by chance if you decided to touch 2.2. The solution to this is to move all settings to a new file, `settings.vvv`. However, for compatibility with 2.2, settings will still be written to `unlock.vvv`. The game will prioritize reading from `settings.vvv` instead of `unlock.vvv`, so if there's a setting that's missing from `unlock.vvv`, no worries there. But if `settings.vvv` is missing, then it'll read settings from `unlock.vvv`. As well, if `unlock.vvv` is missing, then `settings.vvv` will be read from instead (I explicitly tested for this, and found that I had to write special code to handle this case, otherwise the game would overwrite the existing `settings.vvv` before reading from it; kids, make sure to always test your code!). Closes #373 fully.
This commit is contained in:
parent
9e1ba97f63
commit
5aa8b99113
6 changed files with 144 additions and 27 deletions
|
@ -4436,6 +4436,14 @@ void Game::deletestats()
|
|||
}
|
||||
}
|
||||
|
||||
void Game::deletesettings()
|
||||
{
|
||||
if (!FILESYSTEM_delete("saves/settings.vvv"))
|
||||
{
|
||||
puts("Error deleting saves/settings.vvv");
|
||||
}
|
||||
}
|
||||
|
||||
void Game::unlocknum( int t )
|
||||
{
|
||||
#if !defined(MAKEANDPLAY)
|
||||
|
@ -4471,7 +4479,10 @@ void Game::loadstats(int *width, int *height, bool *vsync)
|
|||
tinyxml2::XMLDocument doc;
|
||||
if (!FILESYSTEM_loadTiXml2Document("saves/unlock.vvv", doc))
|
||||
{
|
||||
savestats();
|
||||
// Save unlock.vvv only. Maybe we have a settings.vvv laying around too,
|
||||
// and we don't want to overwrite that!
|
||||
savestats(true);
|
||||
|
||||
printf("No Stats found. Assuming a new player\n");
|
||||
}
|
||||
|
||||
|
@ -4493,7 +4504,9 @@ void Game::loadstats(int *width, int *height, bool *vsync)
|
|||
hRoot=tinyxml2::XMLHandle(pElem);
|
||||
}
|
||||
|
||||
for( pElem = hRoot.FirstChildElement( "Data" ).FirstChild().ToElement(); pElem; pElem=pElem->NextSiblingElement())
|
||||
tinyxml2::XMLElement* dataNode = hRoot.FirstChildElement("Data").FirstChild().ToElement();
|
||||
|
||||
for( pElem = dataNode; pElem; pElem=pElem->NextSiblingElement())
|
||||
{
|
||||
std::string pKey(pElem->Value());
|
||||
const char* pText = pElem->GetText() ;
|
||||
|
@ -4526,6 +4539,35 @@ void Game::loadstats(int *width, int *height, bool *vsync)
|
|||
stat_trinkets = help.Int(pText);
|
||||
}
|
||||
|
||||
if (pKey == "swnbestrank")
|
||||
{
|
||||
swnbestrank = help.Int(pText);
|
||||
}
|
||||
|
||||
if (pKey == "swnrecord")
|
||||
{
|
||||
swnrecord = help.Int(pText);
|
||||
}
|
||||
}
|
||||
|
||||
deserializesettings(dataNode, width, height, vsync);
|
||||
}
|
||||
|
||||
void Game::deserializesettings(tinyxml2::XMLElement* dataNode, int* width, int* height, bool* vsync)
|
||||
{
|
||||
// Don't duplicate controller buttons!
|
||||
controllerButton_flip.clear();
|
||||
controllerButton_map.clear();
|
||||
controllerButton_esc.clear();
|
||||
controllerButton_restart.clear();
|
||||
|
||||
for (tinyxml2::XMLElement* pElem = dataNode;
|
||||
pElem != NULL;
|
||||
pElem = pElem->NextSiblingElement())
|
||||
{
|
||||
std::string pKey(pElem->Value());
|
||||
const char* pText = pElem->GetText();
|
||||
|
||||
if (pKey == "fullscreen")
|
||||
{
|
||||
fullscreen = help.Int(pText);
|
||||
|
@ -4595,16 +4637,6 @@ void Game::loadstats(int *width, int *height, bool *vsync)
|
|||
|
||||
}
|
||||
|
||||
if (pKey == "swnbestrank")
|
||||
{
|
||||
swnbestrank = help.Int(pText);
|
||||
}
|
||||
|
||||
if (pKey == "swnrecord")
|
||||
{
|
||||
swnrecord = help.Int(pText);
|
||||
}
|
||||
|
||||
if (pKey == "advanced_smoothing")
|
||||
{
|
||||
fullScreenEffect_badSignal = help.Int(pText);
|
||||
|
@ -4734,7 +4766,7 @@ void Game::loadstats(int *width, int *height, bool *vsync)
|
|||
}
|
||||
}
|
||||
|
||||
void Game::savestats()
|
||||
void Game::savestats(const bool stats_only /*= true*/)
|
||||
{
|
||||
tinyxml2::XMLDocument doc;
|
||||
bool already_exists = FILESYSTEM_loadTiXml2Document("saves/unlock.vvv", doc);
|
||||
|
@ -4804,6 +4836,24 @@ void Game::savestats()
|
|||
|
||||
xml::update_tag(dataNode, "stat_trinkets", stat_trinkets);
|
||||
|
||||
xml::update_tag(dataNode, "swnbestrank", swnbestrank);
|
||||
|
||||
xml::update_tag(dataNode, "swnrecord", swnrecord);
|
||||
|
||||
serializesettings(dataNode);
|
||||
|
||||
FILESYSTEM_saveTiXml2Document("saves/unlock.vvv", doc);
|
||||
|
||||
if (!stats_only)
|
||||
{
|
||||
savesettings();
|
||||
}
|
||||
}
|
||||
|
||||
void Game::serializesettings(tinyxml2::XMLElement* dataNode)
|
||||
{
|
||||
tinyxml2::XMLDocument& doc = xml::get_document(dataNode);
|
||||
|
||||
xml::update_tag(dataNode, "fullscreen", fullscreen);
|
||||
|
||||
xml::update_tag(dataNode, "stretch", stretchMode);
|
||||
|
@ -4834,10 +4884,6 @@ void Game::savestats()
|
|||
|
||||
xml::update_tag(dataNode, "slowdown", slowdown);
|
||||
|
||||
xml::update_tag(dataNode, "swnbestrank", swnbestrank);
|
||||
|
||||
xml::update_tag(dataNode, "swnrecord", swnrecord);
|
||||
|
||||
|
||||
xml::update_tag(dataNode, "advanced_smoothing", fullScreenEffect_badSignal);
|
||||
|
||||
|
@ -4927,8 +4973,58 @@ void Game::savestats()
|
|||
}
|
||||
|
||||
xml::update_tag(dataNode, "controllerSensitivity", controllerSensitivity);
|
||||
}
|
||||
|
||||
FILESYSTEM_saveTiXml2Document("saves/unlock.vvv", doc);
|
||||
void Game::loadsettings(int* width, int* height, bool* vsync)
|
||||
{
|
||||
tinyxml2::XMLDocument doc;
|
||||
if (!FILESYSTEM_loadTiXml2Document("saves/settings.vvv", doc))
|
||||
{
|
||||
savesettings();
|
||||
puts("No settings.vvv found");
|
||||
}
|
||||
|
||||
tinyxml2::XMLHandle hDoc(&doc);
|
||||
tinyxml2::XMLElement* pElem;
|
||||
tinyxml2::XMLHandle hRoot(NULL);
|
||||
|
||||
{
|
||||
pElem = hDoc.FirstChildElement().ToElement();
|
||||
// should always have a valid root but handle gracefully if it doesn't
|
||||
if (!pElem)
|
||||
{
|
||||
}
|
||||
;
|
||||
|
||||
// save this for later
|
||||
hRoot = tinyxml2::XMLHandle(pElem);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement* dataNode = hRoot.FirstChildElement("Data").FirstChild().ToElement();
|
||||
|
||||
deserializesettings(dataNode, width, height, vsync);
|
||||
}
|
||||
|
||||
void Game::savesettings()
|
||||
{
|
||||
tinyxml2::XMLDocument doc;
|
||||
bool already_exists = FILESYSTEM_loadTiXml2Document("saves/settings.vvv", doc);
|
||||
if (!already_exists)
|
||||
{
|
||||
puts("No settings.vvv found. Creating new file");
|
||||
}
|
||||
|
||||
xml::update_declaration(doc);
|
||||
|
||||
tinyxml2::XMLElement* root = xml::update_element(doc, "Settings");
|
||||
|
||||
xml::update_comment(root, " Settings (duplicated from unlock.vvv) ");
|
||||
|
||||
tinyxml2::XMLElement* dataNode = xml::update_element(root, "Data");
|
||||
|
||||
serializesettings(dataNode);
|
||||
|
||||
FILESYSTEM_saveTiXml2Document("saves/settings.vvv", doc);
|
||||
}
|
||||
|
||||
void Game::customstart()
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
#include <vector>
|
||||
|
||||
// Forward decl without including all of <tinyxml2.h>
|
||||
namespace tinyxml2 { class XMLDocument; }
|
||||
namespace tinyxml2
|
||||
{
|
||||
class XMLDocument;
|
||||
class XMLElement;
|
||||
}
|
||||
|
||||
struct MenuOption
|
||||
{
|
||||
|
@ -126,10 +130,20 @@ public:
|
|||
|
||||
void loadstats(int *width, int *height, bool *vsync);
|
||||
|
||||
void savestats();
|
||||
void savestats(const bool stats_only = false);
|
||||
|
||||
void deletestats();
|
||||
|
||||
void deserializesettings(tinyxml2::XMLElement* dataNode, int* width, int* height, bool* vsync);
|
||||
|
||||
void serializesettings(tinyxml2::XMLElement* dataNode);
|
||||
|
||||
void loadsettings(int* width, int* height, bool* vsync);
|
||||
|
||||
void savesettings();
|
||||
|
||||
void deletesettings();
|
||||
|
||||
void deletequick();
|
||||
|
||||
bool savetele();
|
||||
|
|
|
@ -1280,6 +1280,7 @@ void menuactionpress()
|
|||
game.deletequick();
|
||||
game.deletetele();
|
||||
game.deletestats();
|
||||
game.deletesettings();
|
||||
game.flashlight = 5;
|
||||
game.screenshake = 15;
|
||||
game.createmenu(Menu::mainmenu);
|
||||
|
|
|
@ -4,17 +4,16 @@
|
|||
namespace xml
|
||||
{
|
||||
|
||||
// Helper functions for these utils (not exported)
|
||||
|
||||
static inline tinyxml2::XMLDocument& get_document(tinyxml2::XMLNode* parent)
|
||||
// Just get the document, because TinyXML-2 is annoying.
|
||||
// Useful outside of this file.
|
||||
// TODO: But XML handling should really be put in a separate file (maybe this
|
||||
// one renamed?) instead of lumped in with Game.cpp, and when that happens
|
||||
// maybe this will be unexported again?
|
||||
tinyxml2::XMLDocument& get_document(tinyxml2::XMLNode* parent)
|
||||
{
|
||||
return *(parent->GetDocument());
|
||||
}
|
||||
|
||||
|
||||
// EXPORTED FUNCTIONS
|
||||
|
||||
|
||||
// Create a new element if it doesn't exist. Returns the element.
|
||||
tinyxml2::XMLElement* update_element(tinyxml2::XMLNode* parent, const char* name)
|
||||
{
|
||||
|
|
|
@ -11,6 +11,8 @@ namespace tinyxml2
|
|||
namespace xml
|
||||
{
|
||||
|
||||
tinyxml2::XMLDocument& get_document(tinyxml2::XMLNode* parent);
|
||||
|
||||
tinyxml2::XMLElement* update_element(tinyxml2::XMLNode* parent, const char* name);
|
||||
// Same thing as above, but takes &parent instead of *parent
|
||||
tinyxml2::XMLElement* update_element(tinyxml2::XMLNode& parent, const char* name);
|
||||
|
|
|
@ -217,7 +217,12 @@ int main(int argc, char *argv[])
|
|||
int width = 320;
|
||||
int height = 240;
|
||||
bool vsync = false;
|
||||
|
||||
// Prioritize unlock.vvv first (2.2 and below),
|
||||
// but settings have been migrated to settings.vvv (2.3 and up)
|
||||
game.loadstats(&width, &height, &vsync);
|
||||
game.loadsettings(&width, &height, &vsync);
|
||||
|
||||
gameScreen.init(
|
||||
width,
|
||||
height,
|
||||
|
|
Loading…
Reference in a new issue