diff --git a/src/Space.cpp b/src/Space.cpp index 1709973a107..36e140de250 100644 --- a/src/Space.cpp +++ b/src/Space.cpp @@ -262,8 +262,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++) + for (Uint32 i = 0; i < bodyArray.size(); i++) { + if(bodyArray[i].count("is_not_in_space") > 0) + continue; m_bodies.push_back(Body::FromJson(bodyArray[i], this)); + } } catch (Json::type_error &) { throw SavedGameCorruptException(); } @@ -348,8 +351,23 @@ 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 = 0; i < m_bodyIndex.size() - 1; i++) { + // First index of m_bodyIndex is reserved to + // nullptr or bad index + Body* b = m_bodyIndex[i + 1]; 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. + // FIXME: This is done to save it's lua components which is otherwise won't save. + // This needs a better way to handle this case. + // Described in depth: https://github.com/pioneerspacesim/pioneer/pull/5657#issuecomment-1818188703 + 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..d9075d0db39 100644 --- a/src/lua/LuaSerializer.cpp +++ b/src/lua/LuaSerializer.cpp @@ -462,14 +462,17 @@ 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]; + // First index of m_bodyIndex is reserved to + // nullptr or bad index + Body *body = space->GetBodyByIndex(idx + 1); // Serialize lua components Json luaComponentsObj = Json::object(); if (!LuaObjectBase::SerializeComponents(body, luaComponentsObj)) - break; + continue; if (!luaComponentsObj.empty()) { bodies[idx]["lua_components"] = luaComponentsObj; @@ -485,8 +488,7 @@ 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]; @@ -494,7 +496,9 @@ void LuaSerializer::LoadComponents(const Json &jsonObj, Space *space) if (bodyObj.count("lua_components") != 0) { const Json &luaComponents = bodyObj["lua_components"]; if (luaComponents.is_object() && !luaComponents.empty()) { - Body *body = space->GetBodies()[idx]; + // First index of m_bodyIndex is reserved to + // nullptr or bad index + Body *body = space->GetBodyByIndex(idx + 1); // Ensure we've registered the body object in Lua LuaObject::PushToLua(body);