summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoïc Guilloux <glx22@users.noreply.github.com>2021-07-17 12:48:35 +0200
committerGitHub <noreply@github.com>2021-07-17 12:48:35 +0200
commit460991ecf4fbeca2c0f8c39874b39a0885d6f67d (patch)
treebb4df8e1fba39293c8db4772c9b553a88a6fa58c
parent16abdd52546eb3cfa9d51d674c41711c2c170029 (diff)
downloadopenttd-460991ecf4fbeca2c0f8c39874b39a0885d6f67d.tar.xz
Feature: Persistant rotation of numbered auto/netsave after restart (#9397)
It was always starting from 0 on openttd restart. Now the most recent auto/netsave number will be used as a base to generate the next filename.
-rw-r--r--src/fios.cpp57
-rw-r--r--src/fios.h12
-rw-r--r--src/network/network_client.cpp4
-rw-r--r--src/openttd.cpp2
-rw-r--r--src/saveload/saveload.cpp17
-rw-r--r--src/saveload/saveload.h3
6 files changed, 77 insertions, 18 deletions
diff --git a/src/fios.cpp b/src/fios.cpp
index c59bcfb21..0491c1e51 100644
--- a/src/fios.cpp
+++ b/src/fios.cpp
@@ -22,6 +22,7 @@
#include <sys/stat.h>
#include <functional>
#include <optional>
+#include <charconv>
#ifndef _WIN32
# include <unistd.h>
@@ -745,3 +746,59 @@ void ScanScenarios()
{
_scanner.Scan(true);
}
+
+/**
+ * Constructs FiosNumberedSaveName. Initial number is the most recent save, or -1 if not found.
+ * @param prefix The prefix to use to generate a filename.
+*/
+FiosNumberedSaveName::FiosNumberedSaveName(const std::string &prefix) : prefix(prefix), number(-1)
+{
+ static std::optional<std::string> _autosave_path;
+ if (!_autosave_path) _autosave_path = FioFindDirectory(AUTOSAVE_DIR);
+
+ static std::string _prefix; ///< Static as the lambda needs access to it.
+
+ /* Callback for FiosFileScanner. */
+ static fios_getlist_callback_proc *proc = [](SaveLoadOperation fop, const std::string &file, const char *ext, char *title, const char *last) {
+ if (strcasecmp(ext, ".sav") == 0 && StrStartsWith(file, _prefix)) return FIOS_TYPE_FILE;
+ return FIOS_TYPE_INVALID;
+ };
+
+ /* Prefix to check in the callback. */
+ _prefix = *_autosave_path + this->prefix;
+
+ /* Get the save list. */
+ FileList list;
+ FiosFileScanner scanner(SLO_SAVE, proc, list);
+ scanner.Scan(".sav", _autosave_path->c_str(), false);
+
+ /* Find the number for the most recent save, if any. */
+ if (list.begin() != list.end()) {
+ SortingBits order = _savegame_sort_order;
+ _savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING;
+ std::sort(list.begin(), list.end());
+ _savegame_sort_order = order;
+
+ std::string_view name = list.begin()->title;
+ std::from_chars(name.data() + this->prefix.size(), name.data() + name.size(), this->number);
+ }
+}
+
+/**
+ * Generate a savegame name and number according to _settings_client.gui.max_num_autosaves.
+ * @return A filename in format "<prefix><number>.sav".
+*/
+std::string FiosNumberedSaveName::Filename()
+{
+ if (++this->number >= _settings_client.gui.max_num_autosaves) this->number = 0;
+ return fmt::format("{}{}.sav", this->prefix, this->number);
+}
+
+/**
+ * Generate an extension for a savegame name.
+ * @return An extension in format "-<prefix>.sav".
+*/
+std::string FiosNumberedSaveName::Extension()
+{
+ return fmt::format("-{}.sav", this->prefix);
+}
diff --git a/src/fios.h b/src/fios.h
index 34504d5e0..c0e516297 100644
--- a/src/fios.h
+++ b/src/fios.h
@@ -125,4 +125,16 @@ std::string FiosMakeSavegameName(const char *name);
FiosType FiosGetSavegameListCallback(SaveLoadOperation fop, const std::string &file, const char *ext, char *title, const char *last);
+/**
+ * A savegame name automatically numbered.
+ */
+struct FiosNumberedSaveName {
+ FiosNumberedSaveName(const std::string &prefix);
+ std::string Filename();
+ std::string Extension();
+private:
+ std::string prefix;
+ int number;
+};
+
#endif /* FIOS_H */
diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp
index 9f08062f3..d38437cc1 100644
--- a/src/network/network_client.cpp
+++ b/src/network/network_client.cpp
@@ -132,8 +132,8 @@ struct PacketReader : LoadFilter {
*/
void ClientNetworkEmergencySave()
{
- static int _netsave_ctr = 0;
- DoAutoOrNetsave(_netsave_ctr, true);
+ static FiosNumberedSaveName _netsave_ctr("netsave");
+ DoAutoOrNetsave(_netsave_ctr);
}
diff --git a/src/openttd.cpp b/src/openttd.cpp
index 711df58c4..0ea1fa75d 100644
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -1393,7 +1393,7 @@ void StateGameLoop()
*/
static void DoAutosave()
{
- static int _autosave_ctr = 0;
+ static FiosNumberedSaveName _autosave_ctr("autosave");
DoAutoOrNetsave(_autosave_ctr);
}
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp
index d771bf526..c8a1a0d29 100644
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -3328,26 +3328,15 @@ SaveOrLoadResult SaveOrLoad(const std::string &filename, SaveLoadOperation fop,
* @param counter A reference to the counter variable to be used for rotating the file name.
* @param netsave Indicates if this is a regular autosave or a netsave.
*/
-void DoAutoOrNetsave(int &counter, bool netsave)
+void DoAutoOrNetsave(FiosNumberedSaveName &counter)
{
char buf[MAX_PATH];
if (_settings_client.gui.keep_all_autosave) {
GenerateDefaultSaveName(buf, lastof(buf));
- if (!netsave) {
- strecat(buf, ".sav", lastof(buf));
- } else {
- strecat(buf, "-netsave.sav", lastof(buf));
- }
+ strecat(buf, counter.Extension().c_str(), lastof(buf));
} else {
- /* Generate a savegame name and number according to _settings_client.gui.max_num_autosaves. */
- if (!netsave) {
- seprintf(buf, lastof(buf), "autosave%d.sav", counter);
- } else {
- seprintf(buf, lastof(buf), "netsave%d.sav", counter);
- }
-
- if (++counter >= _settings_client.gui.max_num_autosaves) counter = 0;
+ strecpy(buf, counter.Filename().c_str(), lastof(buf));
}
Debug(sl, 2, "Autosaving to '{}'", buf);
diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h
index d79bc1416..3047cbfd8 100644
--- a/src/saveload/saveload.h
+++ b/src/saveload/saveload.h
@@ -11,6 +11,7 @@
#define SAVELOAD_H
#include "../fileio_type.h"
+#include "../fios.h"
#include "../strings_type.h"
#include "../core/span_type.hpp"
#include <optional>
@@ -381,7 +382,7 @@ void WaitTillSaved();
void ProcessAsyncSaveFinish();
void DoExitSave();
-void DoAutoOrNetsave(int &counter, bool netsave = false);
+void DoAutoOrNetsave(FiosNumberedSaveName &counter);
SaveOrLoadResult SaveWithFilter(struct SaveFilter *writer, bool threaded);
SaveOrLoadResult LoadWithFilter(struct LoadFilter *reader);