1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-12-23 10:09:43 +01:00

Merge pull request #326 from InfoTeddy/general-refactors

Refactor how custom level stats are stored, read, and written
This commit is contained in:
Ethan Lee 2020-06-29 22:31:03 -04:00 committed by GitHub
commit e85d5a8714
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 137 additions and 85 deletions

View file

@ -541,13 +541,8 @@ void Game::lifesequence()
void Game::clearcustomlevelstats() void Game::clearcustomlevelstats()
{ {
//just clearing the arrays //just clearing the array
for(int i=0; i<200; i++) customlevelstats.clear();
{
customlevelstats[i]="";
customlevelscore[i]=0;
}
numcustomlevelstats=0;
customlevelstatsloaded=false; //To ensure we don't load it where it isn't needed customlevelstatsloaded=false; //To ensure we don't load it where it isn't needed
} }
@ -560,28 +555,24 @@ void Game::updatecustomlevelstats(std::string clevel, int cscore)
clevel = clevel.substr(7); clevel = clevel.substr(7);
} }
int tvar=-1; int tvar=-1;
for(int j=0; j<numcustomlevelstats; j++) for(size_t j=0; j<customlevelstats.size(); j++)
{ {
if(clevel==customlevelstats[j]) if(clevel==customlevelstats[j].name)
{ {
tvar=j; tvar=j;
j=numcustomlevelstats+1; break;
} }
} }
if(tvar>=0 && cscore > customlevelscore[tvar]) if(tvar>=0 && cscore > customlevelstats[tvar].score)
{ {
//update existing entry //update existing entry
customlevelscore[tvar]=cscore; customlevelstats[tvar].score=cscore;
} }
else else
{ {
//add a new entry //add a new entry
if(numcustomlevelstats<200) CustomLevelStat levelstat = {clevel, cscore};
{ customlevelstats.push_back(levelstat);
customlevelstats[numcustomlevelstats]=clevel;
customlevelscore[numcustomlevelstats]=cscore;
numcustomlevelstats++;
}
} }
savecustomlevelstats(); savecustomlevelstats();
} }
@ -589,76 +580,117 @@ void Game::updatecustomlevelstats(std::string clevel, int cscore)
void Game::loadcustomlevelstats() void Game::loadcustomlevelstats()
{ {
//testing //testing
if(!customlevelstatsloaded) if(customlevelstatsloaded)
{ {
tinyxml2::XMLDocument doc; return;
if (!FILESYSTEM_loadTiXml2Document("saves/levelstats.vvv", doc)) }
{
//No levelstats file exists; start new
numcustomlevelstats=0;
savecustomlevelstats();
}
else
{
tinyxml2::XMLHandle hDoc(&doc);
tinyxml2::XMLElement* pElem;
tinyxml2::XMLHandle hRoot(NULL);
tinyxml2::XMLDocument doc;
if (!FILESYSTEM_loadTiXml2Document("saves/levelstats.vvv", doc))
{
//No levelstats file exists; start new
customlevelstats.clear();
savecustomlevelstats();
return;
}
// Old system
std::vector<std::string> customlevelnames;
std::vector<int> customlevelscores;
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 does
if (!pElem)
{
printf("Error: Levelstats file corrupted\n");
}
// save this for later
hRoot=tinyxml2::XMLHandle(pElem);
}
// First pass, look for the new system of storing stats
// If they don't exist, then fall back to the old system
for (pElem = hRoot.FirstChildElement("Data").FirstChild().ToElement(); pElem; pElem = pElem->NextSiblingElement())
{
std::string pKey(pElem->Value());
const char* pText = pElem->GetText();
if (pText == NULL)
{
pText = "";
}
if (pKey == "stats")
{
for (tinyxml2::XMLElement* stat_el = pElem->FirstChildElement(); stat_el; stat_el = stat_el->NextSiblingElement())
{ {
pElem=hDoc.FirstChildElement().ToElement(); CustomLevelStat stat = {};
// should always have a valid root but handle gracefully if it does
if (!pElem) if (stat_el->GetText() != NULL)
{ {
printf("Error: Levelstats file corrupted\n"); stat.score = atoi(stat_el->GetText());
} }
// save this for later if (stat_el->Attribute("name"))
hRoot=tinyxml2::XMLHandle(pElem); {
stat.name = stat_el->Attribute("name");
}
customlevelstats.push_back(stat);
} }
return;
}
}
for( pElem = hRoot.FirstChildElement( "Data" ).FirstChild().ToElement(); pElem; pElem=pElem->NextSiblingElement())
// Since we're still here, we must be on the old system
for( pElem = hRoot.FirstChildElement( "Data" ).FirstChild().ToElement(); pElem; pElem=pElem->NextSiblingElement())
{
std::string pKey(pElem->Value());
const char* pText = pElem->GetText() ;
if(pText == NULL)
{
pText = "";
}
if (pKey == "customlevelscore")
{
std::string TextString = (pText);
if(TextString.length())
{ {
std::string pKey(pElem->Value()); std::vector<std::string> values = split(TextString,',');
const char* pText = pElem->GetText() ; for(size_t i = 0; i < values.size(); i++)
if(pText == NULL)
{ {
pText = ""; customlevelscores.push_back(atoi(values[i].c_str()));
}
if (pKey == "numcustomlevelstats")
{
numcustomlevelstats = atoi(pText);
if(numcustomlevelstats>=200) numcustomlevelstats=199;
}
if (pKey == "customlevelscore")
{
std::string TextString = (pText);
if(TextString.length())
{
std::vector<std::string> values = split(TextString,',');
for(size_t i = 0; i < values.size(); i++)
{
if(i<200) customlevelscore[i]=(atoi(values[i].c_str()));
}
}
}
if (pKey == "customlevelstats")
{
std::string TextString = (pText);
if(TextString.length())
{
std::vector<std::string> values = split(TextString,'|');
for(size_t i = 0; i < values.size(); i++)
{
if(i<200) customlevelstats[i]=values[i];
}
}
} }
} }
} }
if (pKey == "customlevelstats")
{
std::string TextString = (pText);
if(TextString.length())
{
std::vector<std::string> values = split(TextString,'|');
for(size_t i = 0; i < values.size(); i++)
{
customlevelnames.push_back(values[i]);
}
}
}
}
// If the two arrays happen to differ in length, just go with the smallest one
for (size_t i = 0; i < std::min(customlevelnames.size(), customlevelscores.size()); i++)
{
CustomLevelStat stat = {customlevelnames[i], customlevelscores[i]};
customlevelstats.push_back(stat);
} }
} }
@ -678,6 +710,7 @@ void Game::savecustomlevelstats()
tinyxml2::XMLElement * msgs = doc.NewElement( "Data" ); tinyxml2::XMLElement * msgs = doc.NewElement( "Data" );
root->LinkEndChild( msgs ); root->LinkEndChild( msgs );
int numcustomlevelstats = customlevelstats.size();
if(numcustomlevelstats>=200)numcustomlevelstats=199; if(numcustomlevelstats>=200)numcustomlevelstats=199;
msg = doc.NewElement( "numcustomlevelstats" ); msg = doc.NewElement( "numcustomlevelstats" );
msg->LinkEndChild( doc.NewText( help.String(numcustomlevelstats).c_str() )); msg->LinkEndChild( doc.NewText( help.String(numcustomlevelstats).c_str() ));
@ -686,7 +719,7 @@ void Game::savecustomlevelstats()
std::string customlevelscorestr; std::string customlevelscorestr;
for(int i = 0; i < numcustomlevelstats; i++ ) for(int i = 0; i < numcustomlevelstats; i++ )
{ {
customlevelscorestr += help.String(customlevelscore[i]) + ","; customlevelscorestr += help.String(customlevelstats[i].score) + ",";
} }
msg = doc.NewElement( "customlevelscore" ); msg = doc.NewElement( "customlevelscore" );
msg->LinkEndChild( doc.NewText( customlevelscorestr.c_str() )); msg->LinkEndChild( doc.NewText( customlevelscorestr.c_str() ));
@ -695,12 +728,27 @@ void Game::savecustomlevelstats()
std::string customlevelstatsstr; std::string customlevelstatsstr;
for(int i = 0; i < numcustomlevelstats; i++ ) for(int i = 0; i < numcustomlevelstats; i++ )
{ {
customlevelstatsstr += customlevelstats[i] + "|"; customlevelstatsstr += customlevelstats[i].name + "|";
} }
msg = doc.NewElement( "customlevelstats" ); msg = doc.NewElement( "customlevelstats" );
msg->LinkEndChild( doc.NewText( customlevelstatsstr.c_str() )); msg->LinkEndChild( doc.NewText( customlevelstatsstr.c_str() ));
msgs->LinkEndChild( msg ); msgs->LinkEndChild( msg );
// New system
msg = doc.NewElement("stats");
tinyxml2::XMLElement* stat_el;
for (size_t i = 0; i < customlevelstats.size(); i++)
{
stat_el = doc.NewElement("stat");
CustomLevelStat& stat = customlevelstats[i];
stat_el->SetAttribute("name", stat.name.c_str());
stat_el->LinkEndChild(doc.NewText(help.String(stat.score).c_str()));
msg->LinkEndChild(stat_el);
}
msgs->LinkEndChild(msg);
if(FILESYSTEM_saveTiXml2Document("saves/levelstats.vvv", doc)) if(FILESYSTEM_saveTiXml2Document("saves/levelstats.vvv", doc))
{ {
printf("Level stats saved\n"); printf("Level stats saved\n");
@ -7028,26 +7076,26 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
{ {
//This is, er, suboptimal. Whatever, life optimisation and all that //This is, er, suboptimal. Whatever, life optimisation and all that
int tvar=-1; int tvar=-1;
for(int j=0; j<numcustomlevelstats; j++) for(size_t j=0; j<customlevelstats.size(); j++)
{ {
if(ed.ListOfMetaData[i].filename.substr(7) == customlevelstats[j]) if(ed.ListOfMetaData[i].filename.substr(7) == customlevelstats[j].name)
{ {
tvar=j; tvar=j;
j=numcustomlevelstats+1; break;
} }
} }
std::string text; std::string text;
if(tvar>=0) if(tvar>=0)
{ {
if(customlevelscore[tvar]==0) if(customlevelstats[tvar].score==0)
{ {
text = " " + ed.ListOfMetaData[i].title; text = " " + ed.ListOfMetaData[i].title;
} }
else if(customlevelscore[tvar]==1) else if(customlevelstats[tvar].score==1)
{ {
text = " * " + ed.ListOfMetaData[i].title; text = " * " + ed.ListOfMetaData[i].title;
} }
else if(customlevelscore[tvar]==3) else if(customlevelstats[tvar].score==3)
{ {
text = "** " + ed.ListOfMetaData[i].title; text = "** " + ed.ListOfMetaData[i].title;
} }

View file

@ -76,6 +76,12 @@ struct MenuStackFrame
enum Menu::MenuName name; enum Menu::MenuName name;
}; };
struct CustomLevelStat
{
std::string name;
int score; //0 - not played, 1 - finished, 2 - all trinkets, 3 - finished, all trinkets
};
class Game class Game
{ {
@ -364,9 +370,7 @@ public:
void savecustomlevelstats(); void savecustomlevelstats();
void updatecustomlevelstats(std::string clevel, int cscore); void updatecustomlevelstats(std::string clevel, int cscore);
std::string customlevelstats[200]; //string array containing level filenames std::vector<CustomLevelStat> customlevelstats;
int customlevelscore[200];//0 - not played, 1 - finished, 2 - all trinkets, 3 - finished, all trinkets
int numcustomlevelstats;
bool customlevelstatsloaded; bool customlevelstatsloaded;