diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 6805bc5a9..aac9d494f 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -1094,6 +1094,7 @@ SaveFile * Client::GetStamp(std::string stampID) catch (ParseException & e) { std::cerr << "Client: Invalid stamp file, " << stampID << " " << std::string(e.what()) << std::endl; + file->SetLoadingError(e.what()); } } return file; diff --git a/src/client/GameSave.cpp b/src/client/GameSave.cpp index 0144e1a9b..6391fe99e 100644 --- a/src/client/GameSave.cpp +++ b/src/client/GameSave.cpp @@ -466,7 +466,7 @@ void GameSave::readOPS(char * data, int dataLength) if (savedVersion > SAVE_VERSION) { fromNewerVersion = true; - throw ParseException(ParseException::WrongVersion, "Save from newer version"); + //throw ParseException(ParseException::WrongVersion, "Save from newer version"); } //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 @@ -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) { //Particle *particles = sim->parts; @@ -1794,6 +1831,10 @@ char * GameSave::serialiseOPS(unsigned int & dataLength) int blockX, blockY, blockW, blockH, fullX, fullY, fullW, fullH; int x, y, i, wallDataFound = 0; 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; 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, "builtType", IDENT_BUILD); 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); diff --git a/src/client/SaveFile.cpp b/src/client/SaveFile.cpp index 450811ed4..215d9bf88 100644 --- a/src/client/SaveFile.cpp +++ b/src/client/SaveFile.cpp @@ -7,11 +7,12 @@ SaveFile::SaveFile(SaveFile & save): thumbnail(NULL), gameSave(NULL), filename(save.filename), - displayName(save.displayName) + displayName(save.displayName), + loadingError(save.loadingError) { - if(save.gameSave) + if (save.gameSave) gameSave = new GameSave(*save.gameSave); - if(save.thumbnail) + if (save.thumbnail) thumbnail = new Thumbnail(*save.thumbnail); } @@ -29,7 +30,8 @@ SaveFile::SaveFile(std::string filename): thumbnail(NULL), gameSave(NULL), filename(filename), - displayName(filename) + displayName(filename), + loadingError("") { } @@ -64,6 +66,16 @@ void SaveFile::SetDisplayName(std::string displayName) this->displayName = displayName; } +std::string SaveFile::GetError() +{ + return loadingError; +} + +void SaveFile::SetLoadingError(std::string error) +{ + loadingError = error; +} + SaveFile::~SaveFile() { delete gameSave; delete thumbnail; diff --git a/src/client/SaveFile.h b/src/client/SaveFile.h index 33211ddf6..23d986e11 100644 --- a/src/client/SaveFile.h +++ b/src/client/SaveFile.h @@ -19,6 +19,8 @@ public: void SetDisplayName(std::string displayName); std::string GetName(); void SetFileName(std::string fileName); + std::string GetError(); + void SetLoadingError(std::string error); virtual ~SaveFile(); private: @@ -26,6 +28,7 @@ private: GameSave * gameSave; std::string filename; std::string displayName; + std::string loadingError; }; #endif /* SAVEFILE_H_ */ diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index daa64b321..5db98471f 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -110,11 +110,14 @@ public: StampsCallback(GameController * cc_) { cc = cc_; } virtual void ControllerExit() { - if(cc->localBrowser->GetSave()) + SaveFile *file = cc->localBrowser->GetSave(); + if (file) { - if (cc->localBrowser->GetMoveToFront()) - Client::Ref().MoveStampToFront(cc->localBrowser->GetSave()->GetName()); - cc->LoadStamp(cc->localBrowser->GetSave()->GetGameSave()); + if (file->GetError().length()) + new ErrorMessage("Error loading stamp", file->GetError()); + else if (cc->localBrowser->GetMoveToFront()) + Client::Ref().MoveStampToFront(file->GetName()); + cc->LoadStamp(file->GetGameSave()); } } };