add new minimumVersion setting in saves, can restrict the smallest version of TPT that is able to open the save. Uses major/minor version for this

Also add RESTRICTVERSION macro to help when adding restrictions later
Also show errors when opening broken stamps now too
This commit is contained in:
jacob1 2015-10-02 21:25:15 -04:00
parent 1bd861719f
commit 63843c2bd7
5 changed files with 73 additions and 9 deletions

View File

@ -1094,6 +1094,7 @@ SaveFile * Client::GetStamp(std::string stampID)
catch (ParseException & e) catch (ParseException & e)
{ {
std::cerr << "Client: Invalid stamp file, " << stampID << " " << std::string(e.what()) << std::endl; std::cerr << "Client: Invalid stamp file, " << stampID << " " << std::string(e.what()) << std::endl;
file->SetLoadingError(e.what());
} }
} }
return file; return file;

View File

@ -466,7 +466,7 @@ void GameSave::readOPS(char * data, int dataLength)
if (savedVersion > SAVE_VERSION) if (savedVersion > SAVE_VERSION)
{ {
fromNewerVersion = true; fromNewerVersion = true;
throw ParseException(ParseException::WrongVersion, "Save from newer version"); //throw ParseException(ParseException::WrongVersion, "Save from newer version");
} }
//Incompatible cell size //Incompatible cell size
@ -721,6 +721,37 @@ void GameSave::readOPS(char * data, int dataLength)
} }
} }
} }
else if (!strcmp(bson_iterator_key(&iter), "minimumVersion"))
{
if (bson_iterator_type(&iter) == BSON_OBJECT)
{
int major = INT_MAX, minor = INT_MAX;
bson_iterator subiter;
bson_iterator_subiterator(&iter, &subiter);
while (bson_iterator_next(&subiter))
{
if (bson_iterator_type(&subiter) == BSON_INT)
{
if (!strcmp(bson_iterator_key(&subiter), "major"))
major = bson_iterator_int(&subiter);
else if (!strcmp(bson_iterator_key(&subiter), "minor"))
minor = bson_iterator_int(&subiter);
else
fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter));
}
}
if (major > SAVE_VERSION || (major == SAVE_VERSION && minor > MINOR_VERSION))
{
std::stringstream errorMessage;
errorMessage << "Save from a newer version: Requires version " << major << "." << minor;
throw ParseException(ParseException::WrongVersion, errorMessage.str());
}
}
else
{
fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter));
}
}
} }
//Read wall and fan data //Read wall and fan data
@ -1783,6 +1814,12 @@ void GameSave::readPSv(char * data, int dataLength)
} }
} }
// restrict the minimum version this save can be opened with
#define RESTRICTVERSION(major, minor) if ((major) > minimumMajorVersion || (((major) == minimumMajorVersion && (minor) > minimumMinorVersion))) {\
minimumMajorVersion = major;\
minimumMinorVersion = minor;\
}
char * GameSave::serialiseOPS(unsigned int & dataLength) char * GameSave::serialiseOPS(unsigned int & dataLength)
{ {
//Particle *particles = sim->parts; //Particle *particles = sim->parts;
@ -1794,6 +1831,10 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
int blockX, blockY, blockW, blockH, fullX, fullY, fullW, fullH; int blockX, blockY, blockW, blockH, fullX, fullY, fullW, fullH;
int x, y, i, wallDataFound = 0; int x, y, i, wallDataFound = 0;
int posCount, signsCount; int posCount, signsCount;
// minimum version this save is compatible with
// when building, this number may be increased depending on what elements are used
// or what properties are detected
int minimumMajorVersion = 90, minimumMinorVersion = 2;
bson b; bson b;
std::fill(elementCount, elementCount+PT_NUM, 0); std::fill(elementCount, elementCount+PT_NUM, 0);
@ -2117,6 +2158,10 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
bson_append_string(&b, "platform", IDENT_PLATFORM); bson_append_string(&b, "platform", IDENT_PLATFORM);
bson_append_string(&b, "builtType", IDENT_BUILD); bson_append_string(&b, "builtType", IDENT_BUILD);
bson_append_finish_object(&b); bson_append_finish_object(&b);
bson_append_start_object(&b, "minimumVersion");
bson_append_int(&b, "major", minimumMajorVersion);
bson_append_int(&b, "minor", minimumMinorVersion);
bson_append_finish_object(&b);
bson_append_bool(&b, "waterEEnabled", waterEEnabled); bson_append_bool(&b, "waterEEnabled", waterEEnabled);

View File

@ -7,7 +7,8 @@ SaveFile::SaveFile(SaveFile & save):
thumbnail(NULL), thumbnail(NULL),
gameSave(NULL), gameSave(NULL),
filename(save.filename), filename(save.filename),
displayName(save.displayName) displayName(save.displayName),
loadingError(save.loadingError)
{ {
if (save.gameSave) if (save.gameSave)
gameSave = new GameSave(*save.gameSave); gameSave = new GameSave(*save.gameSave);
@ -29,7 +30,8 @@ SaveFile::SaveFile(std::string filename):
thumbnail(NULL), thumbnail(NULL),
gameSave(NULL), gameSave(NULL),
filename(filename), filename(filename),
displayName(filename) displayName(filename),
loadingError("")
{ {
} }
@ -64,6 +66,16 @@ void SaveFile::SetDisplayName(std::string displayName)
this->displayName = displayName; this->displayName = displayName;
} }
std::string SaveFile::GetError()
{
return loadingError;
}
void SaveFile::SetLoadingError(std::string error)
{
loadingError = error;
}
SaveFile::~SaveFile() { SaveFile::~SaveFile() {
delete gameSave; delete gameSave;
delete thumbnail; delete thumbnail;

View File

@ -19,6 +19,8 @@ public:
void SetDisplayName(std::string displayName); void SetDisplayName(std::string displayName);
std::string GetName(); std::string GetName();
void SetFileName(std::string fileName); void SetFileName(std::string fileName);
std::string GetError();
void SetLoadingError(std::string error);
virtual ~SaveFile(); virtual ~SaveFile();
private: private:
@ -26,6 +28,7 @@ private:
GameSave * gameSave; GameSave * gameSave;
std::string filename; std::string filename;
std::string displayName; std::string displayName;
std::string loadingError;
}; };
#endif /* SAVEFILE_H_ */ #endif /* SAVEFILE_H_ */

View File

@ -110,11 +110,14 @@ public:
StampsCallback(GameController * cc_) { cc = cc_; } StampsCallback(GameController * cc_) { cc = cc_; }
virtual void ControllerExit() virtual void ControllerExit()
{ {
if(cc->localBrowser->GetSave()) SaveFile *file = cc->localBrowser->GetSave();
if (file)
{ {
if (cc->localBrowser->GetMoveToFront()) if (file->GetError().length())
Client::Ref().MoveStampToFront(cc->localBrowser->GetSave()->GetName()); new ErrorMessage("Error loading stamp", file->GetError());
cc->LoadStamp(cc->localBrowser->GetSave()->GetGameSave()); else if (cc->localBrowser->GetMoveToFront())
Client::Ref().MoveStampToFront(file->GetName());
cc->LoadStamp(file->GetGameSave());
} }
} }
}; };