diff --git a/CMakeLists.txt b/CMakeLists.txt index d19e2e9..21b771d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ set(sources "src/main.cpp" "src/World.cpp" "src/FileHelpers.cpp" "src/BookmarkManager.cpp" + "src/VersionConstants.cpp" "src/ResourceDisplay/ResourceDisplay.cpp" "src/ResourceDisplay/SvgResourceDisplay.cpp" "src/ResourceDisplay/ImageResourceDisplay.cpp" diff --git a/include/Helpers/Networking/NetLibrary.hpp b/include/Helpers/Networking/NetLibrary.hpp index 54ef784..d8b3ff6 100644 --- a/include/Helpers/Networking/NetLibrary.hpp +++ b/include/Helpers/Networking/NetLibrary.hpp @@ -14,7 +14,7 @@ template std::weak_ptr make_weak_ptr(std::shared_ptr ptr) { retu #define RELIABLE_COMMAND_CHANNEL "reliableCommand" #define UNRELIABLE_COMMAND_CHANNEL "unreliableCommand" #define RESOURCE_COMMAND_CHANNEL "resourceCommand" -#define MAIN_NETLIBRARY_CHANNEL "main00003" // NOTE: Change this value whenever netcode is incompatible with the previous version +#define MAIN_NETLIBRARY_CHANNEL "main00004" // NOTE: Change this value whenever netcode is incompatible with the previous version typedef uint8_t MessageCommandType; diff --git a/include/Helpers/VersionNumber.cpp b/include/Helpers/VersionNumber.cpp index 7fb0011..5d88f04 100644 --- a/include/Helpers/VersionNumber.cpp +++ b/include/Helpers/VersionNumber.cpp @@ -5,6 +5,18 @@ std::string version_numbers_to_version_str(const VersionNumber& versionNum) { return std::to_string(versionNum.major) + "." + std::to_string(versionNum.minor) + "." + std::to_string(versionNum.patch); } +bool operator<=(const VersionNumber& a, const VersionNumber& b) { + return !(a > b); +} + +bool operator<(const VersionNumber& a, const VersionNumber& b) { + return !(a >= b); +} + +bool operator>=(const VersionNumber& a, const VersionNumber& b) { + return (a > b) || (a == b); +} + bool operator>(const VersionNumber& a, const VersionNumber& b) { return (a.major > b.major) || (a.major == b.major && (a.minor > b.minor || (a.minor == b.minor && a.patch > b.patch))); } @@ -13,6 +25,10 @@ bool operator==(const VersionNumber& a, const VersionNumber& b) { return a.major == b.major && a.minor == b.minor && a.patch == b.patch; } +bool operator!=(const VersionNumber& a, const VersionNumber& b) { + return a.major != b.major || a.minor != b.minor || a.patch != b.patch; +} + std::optional version_str_to_version_numbers(const std::string& versionStr) { try { std::vector splitStrings = split_string_by_token(versionStr, "."); diff --git a/include/Helpers/VersionNumber.hpp b/include/Helpers/VersionNumber.hpp index 0bff051..5067102 100644 --- a/include/Helpers/VersionNumber.hpp +++ b/include/Helpers/VersionNumber.hpp @@ -10,5 +10,9 @@ struct VersionNumber { std::optional version_str_to_version_numbers(const std::string& versionStr); std::string version_numbers_to_version_str(const VersionNumber& versionNum); +bool operator<=(const VersionNumber& a, const VersionNumber& b); +bool operator<(const VersionNumber& a, const VersionNumber& b); bool operator>(const VersionNumber& a, const VersionNumber& b); +bool operator>=(const VersionNumber& a, const VersionNumber& b); bool operator==(const VersionNumber& a, const VersionNumber& b); +bool operator!=(const VersionNumber& a, const VersionNumber& b); diff --git a/src/DrawComponents/DrawBrushStroke.cpp b/src/DrawComponents/DrawBrushStroke.cpp index c44251d..a412c99 100644 --- a/src/DrawComponents/DrawBrushStroke.cpp +++ b/src/DrawComponents/DrawBrushStroke.cpp @@ -23,6 +23,14 @@ void DrawBrushStroke::load(cereal::PortableBinaryInputArchive& a) { a(d->points, d->color, d->hasRoundCaps); } +void DrawBrushStroke::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(d->points, d->color, d->hasRoundCaps); +} + +void DrawBrushStroke::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + a(d->points, d->color, d->hasRoundCaps); +} + DrawComponentType DrawBrushStroke::get_type() const { return DRAWCOMPONENT_BRUSHSTROKE; } diff --git a/src/DrawComponents/DrawBrushStroke.hpp b/src/DrawComponents/DrawBrushStroke.hpp index bed14ee..8a8bf4c 100644 --- a/src/DrawComponents/DrawBrushStroke.hpp +++ b/src/DrawComponents/DrawBrushStroke.hpp @@ -25,6 +25,8 @@ class DrawBrushStroke : public DrawComponent { virtual DrawComponentType get_type() const override; virtual void save(cereal::PortableBinaryOutputArchive& a) const override; virtual void load(cereal::PortableBinaryInputArchive& a) override; + virtual void save_file(cereal::PortableBinaryOutputArchive& a) const override; + virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) override; struct Data { std::vector points; diff --git a/src/DrawComponents/DrawComponent.hpp b/src/DrawComponents/DrawComponent.hpp index 99d97e5..1c8cf87 100644 --- a/src/DrawComponents/DrawComponent.hpp +++ b/src/DrawComponents/DrawComponent.hpp @@ -6,6 +6,7 @@ #include "../CoordSpaceHelper.hpp" #include "../Server/MainServer.hpp" #include "../CollabList.hpp" +#include #ifndef IS_SERVER #include "../DrawData.hpp" @@ -43,6 +44,8 @@ class DrawComponent { static std::shared_ptr allocate_comp_type(DrawComponentType type); virtual void save(cereal::PortableBinaryOutputArchive& a) const = 0; virtual void load(cereal::PortableBinaryInputArchive& a) = 0; + virtual void save_file(cereal::PortableBinaryOutputArchive& a) const = 0; + virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) = 0; virtual DrawComponentType get_type() const = 0; virtual void get_used_resources(std::unordered_set& v) const; virtual void remap_resource_ids(std::unordered_map& newIDs); diff --git a/src/DrawComponents/DrawEllipse.cpp b/src/DrawComponents/DrawEllipse.cpp index 893d574..0a9c833 100644 --- a/src/DrawComponents/DrawEllipse.cpp +++ b/src/DrawComponents/DrawEllipse.cpp @@ -18,6 +18,14 @@ void DrawEllipse::load(cereal::PortableBinaryInputArchive& a) { a(d.strokeColor, d.fillColor, d.strokeWidth, d.p1, d.p2, d.fillStrokeMode); } +void DrawEllipse::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(d.strokeColor, d.fillColor, d.strokeWidth, d.p1, d.p2, d.fillStrokeMode); +} + +void DrawEllipse::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + a(d.strokeColor, d.fillColor, d.strokeWidth, d.p1, d.p2, d.fillStrokeMode); +} + #ifndef IS_SERVER std::shared_ptr DrawEllipse::copy() const { auto a = std::make_shared(); diff --git a/src/DrawComponents/DrawEllipse.hpp b/src/DrawComponents/DrawEllipse.hpp index 0946eb5..aff09c6 100644 --- a/src/DrawComponents/DrawEllipse.hpp +++ b/src/DrawComponents/DrawEllipse.hpp @@ -11,6 +11,8 @@ class DrawEllipse : public DrawComponent { public: virtual void save(cereal::PortableBinaryOutputArchive& a) const override; virtual void load(cereal::PortableBinaryInputArchive& a) override; + virtual void save_file(cereal::PortableBinaryOutputArchive& a) const override; + virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) override; virtual DrawComponentType get_type() const override; // User input data diff --git a/src/DrawComponents/DrawImage.cpp b/src/DrawComponents/DrawImage.cpp index 3547669..a83f529 100644 --- a/src/DrawComponents/DrawImage.cpp +++ b/src/DrawComponents/DrawImage.cpp @@ -24,6 +24,14 @@ void DrawImage::load(cereal::PortableBinaryInputArchive& a) { a(d.p1, d.p2, d.imageID); } +void DrawImage::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(d.p1, d.p2, d.imageID); +} + +void DrawImage::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + a(d.p1, d.p2, d.imageID); +} + void DrawImage::get_used_resources(std::unordered_set& v) const { v.emplace(d.imageID); } diff --git a/src/DrawComponents/DrawImage.hpp b/src/DrawComponents/DrawImage.hpp index 27d3318..0265409 100644 --- a/src/DrawComponents/DrawImage.hpp +++ b/src/DrawComponents/DrawImage.hpp @@ -11,6 +11,8 @@ class DrawImage : public DrawComponent { public: virtual void save(cereal::PortableBinaryOutputArchive& a) const override; virtual void load(cereal::PortableBinaryInputArchive& a) override; + virtual void save_file(cereal::PortableBinaryOutputArchive& a) const override; + virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) override; virtual DrawComponentType get_type() const override; virtual void get_used_resources(std::unordered_set& v) const override; virtual void remap_resource_ids(std::unordered_map& newIDs) override; diff --git a/src/DrawComponents/DrawRectangle.cpp b/src/DrawComponents/DrawRectangle.cpp index 50e58a6..cde63e0 100644 --- a/src/DrawComponents/DrawRectangle.cpp +++ b/src/DrawComponents/DrawRectangle.cpp @@ -21,6 +21,14 @@ void DrawRectangle::load(cereal::PortableBinaryInputArchive& a) { a(d.strokeColor, d.fillColor, d.cornerRadius, d.strokeWidth, d.p1, d.p2, d.fillStrokeMode); } +void DrawRectangle::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(d.strokeColor, d.fillColor, d.cornerRadius, d.strokeWidth, d.p1, d.p2, d.fillStrokeMode); +} + +void DrawRectangle::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + a(d.strokeColor, d.fillColor, d.cornerRadius, d.strokeWidth, d.p1, d.p2, d.fillStrokeMode); +} + #ifndef IS_SERVER std::shared_ptr DrawRectangle::copy() const { auto a = std::make_shared(); diff --git a/src/DrawComponents/DrawRectangle.hpp b/src/DrawComponents/DrawRectangle.hpp index 5f9b920..9f4bbbc 100644 --- a/src/DrawComponents/DrawRectangle.hpp +++ b/src/DrawComponents/DrawRectangle.hpp @@ -11,6 +11,8 @@ class DrawRectangle : public DrawComponent { public: virtual void save(cereal::PortableBinaryOutputArchive& a) const override; virtual void load(cereal::PortableBinaryInputArchive& a) override; + virtual void save_file(cereal::PortableBinaryOutputArchive& a) const override; + virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) override; virtual DrawComponentType get_type() const override; // User input data diff --git a/src/DrawComponents/DrawTextBox.cpp b/src/DrawComponents/DrawTextBox.cpp index 4148b66..5443501 100644 --- a/src/DrawComponents/DrawTextBox.cpp +++ b/src/DrawComponents/DrawTextBox.cpp @@ -37,6 +37,29 @@ void DrawTextBox::load(cereal::PortableBinaryInputArchive& a) { textBox->set_rich_text_data(richText); } +void DrawTextBox::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(d.p1, d.p2, textBox->get_rich_text_data()); +} + +void DrawTextBox::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + if(version < VersionNumber(0, 3, 0)) { + bool editing; // Unused + Vector4f textColor; + float textSize; + RichText::TextBox::Cursor cursor; // Unused, Equivalent to old cursor structure, just paragraph index and text index flipped + std::string currentText; + a(editing, d.p1, d.p2, textColor, textSize, cursor, currentText); + textBox->insert({0, 0}, currentText); + textBox->set_text_style_modifier_between({0, 0}, textBox->move(RichText::TextBox::Movement::END, {0, 0}), std::make_shared(textColor)); + textBox->set_text_style_modifier_between({0, 0}, textBox->move(RichText::TextBox::Movement::END, {0, 0}), std::make_shared(textSize)); + } + else { + TextData richText; + a(d.p1, d.p2, richText); + textBox->set_rich_text_data(richText); + } +} + #ifndef IS_SERVER std::shared_ptr DrawTextBox::copy() const { auto a = std::make_shared(); diff --git a/src/DrawComponents/DrawTextBox.hpp b/src/DrawComponents/DrawTextBox.hpp index 324e69b..17454d0 100644 --- a/src/DrawComponents/DrawTextBox.hpp +++ b/src/DrawComponents/DrawTextBox.hpp @@ -16,6 +16,8 @@ class DrawTextBox : public DrawComponent { virtual DrawComponentType get_type() const override; virtual void save(cereal::PortableBinaryOutputArchive& a) const override; virtual void load(cereal::PortableBinaryInputArchive& a) override; + virtual void save_file(cereal::PortableBinaryOutputArchive& a) const override; + virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) override; // User input data struct Data { diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 4b5aa51..6b5ef22 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -174,7 +174,7 @@ void DrawingProgram::parallel_loop_all_components(std::function DrawingProgram::get_used_resources() { +std::unordered_set DrawingProgram::get_used_resources() const { std::unordered_set toRet; for(auto& c : components.client_list()) c->obj->get_used_resources(toRet); @@ -559,6 +559,23 @@ void DrawingProgram::initialize_draw_data(cereal::PortableBinaryInputArchive& a) compCache.test_rebuild(components.client_list(), true); } +void DrawingProgram::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + uint64_t compCount; + a(compCount); + for(uint64_t i = 0; i < compCount; i++) { + DrawComponentType t; + a(t); + auto newComp = DrawComponent::allocate_comp_type(t); + a(newComp->id, newComp->coords); + newComp->load_file(a, version); + components.init_emplace_back(newComp); + } + parallel_loop_all_components([&](const auto& c){ + c->obj->commit_update(*this, false); + }); + compCache.test_rebuild(components.client_list(), true); +} + void DrawingProgram::client_erase_set(std::unordered_set erasedComponents) { std::unordered_set idsToErase; for(auto& c : erasedComponents) @@ -687,11 +704,12 @@ void DrawingProgram::draw_drag_circle(SkCanvas* canvas, const Vector2f& sPos, co canvas->drawCircle(sPos.x(), sPos.y(), constantRadius, paintOutline); } -void DrawingProgram::write_to_file(cereal::PortableBinaryOutputArchive& a) { +void DrawingProgram::save_file(cereal::PortableBinaryOutputArchive& a) const { auto& cList = components.client_list(); a((uint64_t)cList.size()); for(size_t i = 0; i < cList.size(); i++) { - a(cList[i]->obj->get_type(), cList[i]->obj->id, cList[i]->obj->coords, *cList[i]->obj); + a(cList[i]->obj->get_type(), cList[i]->obj->id, cList[i]->obj->coords); + cList[i]->obj->save_file(a); } } diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index f7d56bd..5ab82a3 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -30,10 +30,13 @@ class DrawingProgram { void update(); void scale_up(const WorldScalar& scaleUpAmount); void draw(SkCanvas* canvas, const DrawData& drawData); + void initialize_draw_data(cereal::PortableBinaryInputArchive& a); - std::unordered_set get_used_resources(); + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version); + + std::unordered_set get_used_resources() const; ClientPortionID get_max_id(ServerPortionID serverID); - void write_to_file(cereal::PortableBinaryOutputArchive& a); + void save_file(cereal::PortableBinaryOutputArchive& a) const; World& world; bool prevent_undo_or_redo(); diff --git a/src/Server/CommandList.hpp b/src/Server/CommandList.hpp index 3f3818a..0e97733 100644 --- a/src/Server/CommandList.hpp +++ b/src/Server/CommandList.hpp @@ -48,14 +48,5 @@ enum ClientCommands : MessageCommandType { CLIENT_CANVAS_SCALE }; -// NOTE: Do not change savefile header length -#define SAVEFILE_HEADER_LEN 12 -// NOTE: Change these values whenever savefile is incompatible with previous version -#define SAVEFILE_HEADER "INFPNT000003" -#define SAVEFILE_HEADER_V2 "INFPNT000002" -#define SAVEFILE_HEADER_V1 "INFPNT000001" -// Version header -#define VERSION_STRING "0.3.0" - // Arbitrary value. Higher scale up values lead to less scale up events (which can cause stuttering), but leads to larger numbers overall, which can cause a tiny bit of lag and increased memory usage #define CANVAS_SCALE_UP_STEP WorldScalar("100000000000000000000000000000000000000000000000000") diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index 6ec7d2a..3b155fd 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -9,6 +9,7 @@ #include "GUIStuff/Elements/Element.hpp" #include "GUIStuff/GUIManager.hpp" #include "InputManager.hpp" +#include "VersionConstants.hpp" #include "World.hpp" #include #include @@ -193,7 +194,7 @@ void Toolbar::load_licenses() { std::sort(thirdPartyLicenses.begin(), thirdPartyLicenses.end(), [](const auto& a1, const auto& a2) { return std::lexicographical_compare(a1.first.begin(), a1.first.end(), a2.first.begin(), a2.first.end()); }); - ownLicenseText = "InfiniPaint v" + std::string(VERSION_STRING); + ownLicenseText = "InfiniPaint v" + VersionConstants::CURRENT_VERSION_STRING; ownLicenseText += R"( @@ -583,7 +584,7 @@ void Toolbar::update_notification_check() { case FileDownloader::DownloadData::Status::SUCCESS: { updateCheckerData.updateCheckDone = true; std::optional newVersion = version_str_to_version_numbers(updateCheckerData.versionFile->str); - std::optional currentVersion = version_str_to_version_numbers(VERSION_STRING); + std::optional currentVersion = VersionConstants::CURRENT_VERSION_NUMBER; if(newVersion.has_value() && currentVersion.has_value()) { VersionNumber& newV = newVersion.value(); VersionNumber& currentV = currentVersion.value(); diff --git a/src/VersionConstants.cpp b/src/VersionConstants.cpp new file mode 100644 index 0000000..1fe16ff --- /dev/null +++ b/src/VersionConstants.cpp @@ -0,0 +1,20 @@ +#include "VersionConstants.hpp" +#include + +namespace VersionConstants { + +VersionNumber header_to_version_number(const std::string& header) { + static std::unordered_map m; + if(m.empty()) { + m["INFPNT000001"] = VersionNumber(0, 0, 1); + m["INFPNT000002"] = VersionNumber(0, 1, 0); + m["INFPNT000003"] = VersionNumber(0, 2, 0); + m["INFPNT000004"] = VersionNumber(0, 3, 0); + } + auto it = m.find(header); + if(it == m.end()) + throw std::runtime_error("[VersionConstants::header_to_version_number] Header " + header + " is invalid"); + return it->second; +} + +} diff --git a/src/VersionConstants.hpp b/src/VersionConstants.hpp new file mode 100644 index 0000000..38862ae --- /dev/null +++ b/src/VersionConstants.hpp @@ -0,0 +1,16 @@ +#pragma once +#include +#include + +namespace VersionConstants { + // Map OLDEST version that is compatible with the filetype with a specific header + // This means that, to check for file version, you can do these two checks: + // Check if older than a certain version: if(fileVersion < NEWEST VERSION YOU SHOULDNT RUN THE IF STATEMENT ON) + // Check if newer/equal to a certain version: if(fileVersion >= OLDEST VERSION YOU SHOULD RUN THE IF STATEMENT ON) + VersionNumber header_to_version_number(const std::string& header); + + constexpr int SAVEFILE_HEADER_LEN = 12; // DO NOT CHANGE THIS HEADER LENGTH + const std::string CURRENT_SAVEFILE_HEADER = "INFPNT000004"; // Change whenever the save file is incompatible with the previous version + const std::string CURRENT_VERSION_STRING = "0.3.0"; + constexpr VersionNumber CURRENT_VERSION_NUMBER(0, 3, 0); +} diff --git a/src/World.cpp b/src/World.cpp index 2d4f93b..449c474 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -7,6 +7,7 @@ #include "MainProgram.hpp" #include "SharedTypes.hpp" #include "Toolbar.hpp" +#include "VersionConstants.hpp" #include "WorldGrid.hpp" #include "cereal/archives/portable_binary.hpp" #include @@ -273,14 +274,13 @@ void World::save_to_file(const std::filesystem::path& fileName) { filePath = force_extension_on_path(fileName, FILE_EXTENSION); std::stringstream f; - f.write(SAVEFILE_HEADER, SAVEFILE_HEADER_LEN); + f.write(VersionConstants::CURRENT_SAVEFILE_HEADER.c_str(), VersionConstants::SAVEFILE_HEADER_LEN); { std::stringstream fWorldDataToCompress; { cereal::PortableBinaryOutputArchive a(fWorldDataToCompress); - SaveLoadFileOp op{.world = this, .versionStr = SAVEFILE_HEADER}; - a(op); + save_file(a); } std::vector compressedData(ZSTD_compressBound(fWorldDataToCompress.view().size())); @@ -321,30 +321,26 @@ void World::load_from_file(const std::filesystem::path& fileName, std::string_vi buffer = byteDataFromFile; } - if(buffer.size() < SAVEFILE_HEADER_LEN) + if(buffer.size() < VersionConstants::SAVEFILE_HEADER_LEN) throw std::runtime_error("[World::load_from_file] File is not an InfiniPaint canvas (File too small)"); - std::string_view fileHeader = buffer.substr(0, SAVEFILE_HEADER_LEN); + std::string_view fileHeader = buffer.substr(0, VersionConstants::SAVEFILE_HEADER_LEN); + VersionNumber fileVersion = VersionConstants::header_to_version_number(std::string(fileHeader)); std::string_view uncompressedDataView; std::vector uncompressedDataVector; - if(fileHeader == SAVEFILE_HEADER || fileHeader == SAVEFILE_HEADER_V2) { - uncompressedDataVector.resize(ZSTD_getFrameContentSize(buffer.data() + SAVEFILE_HEADER_LEN, buffer.size() - SAVEFILE_HEADER_LEN)); - size_t trueUncompressedSize = ZSTD_decompress(uncompressedDataVector.data(), uncompressedDataVector.size(), buffer.data() + SAVEFILE_HEADER_LEN, buffer.size() - SAVEFILE_HEADER_LEN); + if(fileVersion < VersionNumber(0, 1, 0)) + uncompressedDataView = std::string_view(buffer.data() + VersionConstants::SAVEFILE_HEADER_LEN, buffer.size() - VersionConstants::SAVEFILE_HEADER_LEN); + else { + uncompressedDataVector.resize(ZSTD_getFrameContentSize(buffer.data() + VersionConstants::SAVEFILE_HEADER_LEN, buffer.size() - VersionConstants::SAVEFILE_HEADER_LEN)); + size_t trueUncompressedSize = ZSTD_decompress(uncompressedDataVector.data(), uncompressedDataVector.size(), buffer.data() + VersionConstants::SAVEFILE_HEADER_LEN, buffer.size() - VersionConstants::SAVEFILE_HEADER_LEN); uncompressedDataView = std::string_view(uncompressedDataVector.data(), trueUncompressedSize); } - else if(fileHeader == SAVEFILE_HEADER_V1) - uncompressedDataView = std::string_view(buffer.data() + SAVEFILE_HEADER_LEN, buffer.size() - SAVEFILE_HEADER_LEN); - else - throw std::runtime_error("[World::load_from_file] File is not an InfiniPaint canvas (Wrong header)"); - - ByteMemStream f((char*)uncompressedDataView.data(), uncompressedDataView.size()); cereal::PortableBinaryInputArchive a(f); - SaveLoadFileOp op{.world = this, .versionStr = std::string(fileHeader)}; - a(op); + load_file(a, fileVersion); nextClientID = get_max_id(ownID); Logger::get().log("USERINFO", "File loaded"); @@ -355,34 +351,34 @@ ClientPortionID World::get_max_id(ServerPortionID serverID) { return std::max(std::max(rMan.get_max_id(serverID), drawProg.get_max_id(serverID)), gridMan.get_max_id(serverID)); } -void World::SaveLoadFileOp::save(cereal::PortableBinaryOutputArchive& a) const { - a(world->drawData.cam.c, world->main.window.size.cast().eval()); - a(convert_vec3(world->canvasTheme.backColor)); - world->drawProg.write_to_file(a); - a(world->bMan); - a(world->gridMan); - world->rMan.save_strip_unused_resources(a, world->drawProg.get_used_resources()); +void World::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(drawData.cam.c, main.window.size.cast().eval()); + a(convert_vec3(canvasTheme.backColor)); + drawProg.save_file(a); + a(bMan); + a(gridMan); + rMan.save_strip_unused_resources(a, drawProg.get_used_resources()); } -void World::SaveLoadFileOp::load(cereal::PortableBinaryInputArchive& a) { +void World::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { CoordSpaceHelper coordsToJumpTo; Vector2f windowSizeToJumpTo; a(coordsToJumpTo, windowSizeToJumpTo); - if(versionStr == SAVEFILE_HEADER_V1) - world->set_canvas_background_color(DEFAULT_CANVAS_BACKGROUND_COLOR); + if(version < VersionNumber(0, 1, 0)) + set_canvas_background_color(DEFAULT_CANVAS_BACKGROUND_COLOR); else { Vector3f canvasBackColor; a(canvasBackColor); - world->set_canvas_background_color(canvasBackColor); + set_canvas_background_color(canvasBackColor); } - world->drawData.cam.smooth_move_to(*world, coordsToJumpTo, windowSizeToJumpTo, true); - world->drawProg.initialize_draw_data(a); - a(world->bMan); - if(versionStr == SAVEFILE_HEADER) - a(world->gridMan); - a(world->rMan); + drawData.cam.smooth_move_to(*this, coordsToJumpTo, windowSizeToJumpTo, true); + drawProg.load_file(a, version); + a(bMan); + if(version >= VersionNumber(0, 2, 0)) + a(gridMan); + a(rMan); } WorldScalar World::calculate_zoom_from_uniform_zoom(WorldScalar uniformZoom, WorldVec oldWindowSize) { diff --git a/src/World.hpp b/src/World.hpp index fb5aaf5..b8236ab 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -34,12 +34,8 @@ class World { World(MainProgram& initMain, OpenWorldInfo& worldInfo); - struct SaveLoadFileOp { - World* world; - std::string versionStr; - void save(cereal::PortableBinaryOutputArchive& a) const; - void load(cereal::PortableBinaryInputArchive& a); - }; + void save_file(cereal::PortableBinaryOutputArchive& a) const; + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version); MainProgram& main; DrawData drawData;