mirror of https://github.com/OpenTTD/OpenTTD.git
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.
This commit is contained in:
parent
16abdd5254
commit
460991ecf4
57
src/fios.cpp
57
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);
|
||||
}
|
||||
|
|
12
src/fios.h
12
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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1393,7 +1393,7 @@ void StateGameLoop()
|
|||
*/
|
||||
static void DoAutosave()
|
||||
{
|
||||
static int _autosave_ctr = 0;
|
||||
static FiosNumberedSaveName _autosave_ctr("autosave");
|
||||
DoAutoOrNetsave(_autosave_ctr);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue