From f65ca13b35ddc84aca978c7d047f8e711415780e Mon Sep 17 00:00:00 2001 From: Max5377 <69468517+Max5377@users.noreply.github.com> Date: Wed, 1 Nov 2023 13:53:20 +0300 Subject: [PATCH] Fix lua components corruption on save Fix for the issue when objects which are not in space were corrupted on save, because their lua components wasn't saved. For this, m_bodyIndex vector is used instead of m_bodies to not miss any bodies that are currently exists in the game. --- src/Space.cpp | 18 +++++++++++++++++- src/lua/LuaSerializer.cpp | 16 ++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/Space.cpp b/src/Space.cpp index 1709973a107..f36371d65b3 100644 --- a/src/Space.cpp +++ b/src/Space.cpp @@ -263,7 +263,11 @@ Space::Space(Game *game, RefCountedPtr galaxy, const Json &jsonObj, doub try { Json bodyArray = spaceObj["bodies"].get(); for (Uint32 i = 0; i < bodyArray.size(); i++) + { + if(bodyArray[i]["is_not_in_space"].is_boolean()) + continue; m_bodies.push_back(Body::FromJson(bodyArray[i], this)); + } } catch (Json::type_error &) { throw SavedGameCorruptException(); } @@ -348,8 +352,20 @@ void Space::ToJson(Json &jsonObj) spaceObj["frame"] = frameObj; Json bodyArray = Json::array(); // Create JSON array to contain body data. - for (Body *b : m_bodies) { + for (size_t i = 1; i < m_bodyIndex.size(); i++) + { + Body* b = m_bodyIndex[i]; Json bodyArrayEl({}); // Create JSON object to contain body. + if (!b->IsInSpace()) + { + bodyArrayEl["is_not_in_space"] = true; + // Append empty body object to array. + // The only working example right now is ship in hyperspace + // which is loaded through HyperspaceCloud class, so + // there is no need to load it a second time. + bodyArray.push_back(bodyArrayEl); + continue; + } b->ToJson(bodyArrayEl, this); bodyArray.push_back(bodyArrayEl); // Append body object to array. } diff --git a/src/lua/LuaSerializer.cpp b/src/lua/LuaSerializer.cpp index e5cd7d2bbd8..3ad9b5a750e 100644 --- a/src/lua/LuaSerializer.cpp +++ b/src/lua/LuaSerializer.cpp @@ -462,9 +462,10 @@ void LuaSerializer::SaveComponents(Json &jsonObj, Space *space) // Note: this loop relies on the ordering and contents of Space::m_bodies not changing // between when bodies were serialized and when this function is called. + // Space should not do update, because it invalidates m_bodyIndex vector. - for (size_t idx = 0; idx < bodies.size(); idx++) { - Body *body = space->GetBodies()[idx]; + for (size_t idx = 1; idx < bodies.size(); idx++) { + Body *body = space->GetBodyByIndex(idx); // Serialize lua components Json luaComponentsObj = Json::object(); @@ -472,7 +473,7 @@ void LuaSerializer::SaveComponents(Json &jsonObj, Space *space) break; if (!luaComponentsObj.empty()) { - bodies[idx]["lua_components"] = luaComponentsObj; + bodies[idx - 1]["lua_components"] = luaComponentsObj; } } } @@ -485,16 +486,15 @@ void LuaSerializer::LoadComponents(const Json &jsonObj, Space *space) // Note: this loop relies on the ordering and contents of Space::m_bodies not changing // between when bodies were deserialized and when this function is called. - // Space::GetBodyByIndex cannot be used to lookup bodies as it can be different from the - // index into the JSON bodies array when loading. + // Space should not do update, because it invalidates m_bodyIndex vector. - for (size_t idx = 0; idx < bodies.size(); idx++) { - const Json &bodyObj = bodies[idx]; + for (size_t idx = 1; idx < bodies.size(); idx++) { + const Json &bodyObj = bodies[idx - 1]; if (bodyObj.count("lua_components") != 0) { const Json &luaComponents = bodyObj["lua_components"]; if (luaComponents.is_object() && !luaComponents.empty()) { - Body *body = space->GetBodies()[idx]; + Body *body = space->GetBodyByIndex(idx); // Ensure we've registered the body object in Lua LuaObject::PushToLua(body);