bool savegame::save_game(CVideo* video, const std::string& filename) { try { Uint32 start, end; start = SDL_GetTicks(); if (filename_ == "") filename_ = filename; before_save(); write_game_to_disk(filename_); if (resources::persist != NULL) { resources::persist->end_transaction(); resources::persist ->start_transaction(); } end = SDL_GetTicks(); LOG_SAVE << "Milliseconds to save " << filename_ << ": " << end - start << std::endl; if (video != NULL && show_confirmation_) gui2::show_transient_message(*video, _("Saved"), _("The game has been saved.")); return true; } catch(game::save_game_failed& e) { ERR_SAVE << error_message_ << e.message << std::endl; if (video != NULL){ gui2::show_error_message(*video, error_message_ + e.message); //do not bother retrying, since the user can just try to save the game again //maybe show a yes-no dialog for "disable autosaves now"? } return false; }; }
bool savegame::save_game(CVideo* video, const std::string& filename) { static std::string parent, grandparent; try { Uint32 start, end; start = SDL_GetTicks(); if (filename_ == "") filename_ = filename; before_save(); // The magic moment that does save threading; after // each save, the filename of the save file becomes // the parent for the next. *Unless* the parent file // has the same name as the savefile, in which case we // use the grandparent name. When user loads a savegame, // we load its correct parent link along with it. if (filename_ == parent) { gamestate_.classification().parent = grandparent; } else { gamestate_.classification().parent = parent; } LOG_SAVE << "Setting parent of '" << filename_<< "' to " << gamestate_.classification().parent << "\n"; write_game_to_disk(filename_); if (resources::persist != NULL) { resources::persist->end_transaction(); resources::persist ->start_transaction(); } grandparent = parent; parent = filename_; end = SDL_GetTicks(); LOG_SAVE << "Milliseconds to save " << filename_ << ": " << end - start << "\n"; if (video != NULL && show_confirmation_) gui2::show_message(*video, _("Saved"), _("The game has been saved")); return true; } catch(game::save_game_failed& e) { ERR_SAVE << error_message_ << e.message; if (video != NULL){ gui2::show_error_message(*video, error_message_ + e.message); //do not bother retrying, since the user can just try to save the game again //maybe show a yes-no dialog for "disable autosaves now"? } return false; }; }
Status Base::save() { if (_connection == nullptr) { return Status::status_ailment(); } before_save(); set_updated_at(); fmt::MemoryWriter buf; if (_new_record) { before_create(); set_created_at(); buf << "INSERT INTO " << table_name() << " ("; std::vector<std::tuple<std::string, std::string> > values; for (auto &one : _fields) { if (one.first == "id") continue; values.push_back(std::make_tuple(one.first, one.second)); } auto size = values.size(); for (auto &one : values) { size -= 1; buf << std::get<0>(one); if (0 < size) { buf << ", "; } } buf << ") VALUES ("; size = values.size(); for (auto &one : values) { size -= 1; buf << "'" << std::get<1>(one) << "'"; if (0 < size) { buf << ", "; } } buf << ");"; } else { before_update(); buf << "UPDATE " << table_name() << " SET "; auto size = _dirty_keys.size(); for (auto &key : _dirty_keys) { size -= 1; buf << key << " = '" << _fields[key] << "'"; if (0 < size) { buf << ", "; } } buf << " WHERE id = " << _fields["id"]; } _connection->execute_sql(buf.str()); if (_new_record) { auto id = _connection->last_row_id(); _set_field("id", fmt::format("{0}", id)); after_create(); } else { after_update(); } after_save(); return Status::ok(); }