OpenTTD Source 20260421-master-gc2fbc6fdeb
fios.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "stdafx.h"
11#include "3rdparty/md5/md5.h"
13#include "fileio_func.h"
14#include "fios.h"
16#include "screenshot.h"
17#include "string_func.h"
18#include "strings_func.h"
19#include "tar_type.h"
20#include <sys/stat.h>
21#include <charconv>
22#include <filesystem>
23
24#include "table/strings.h"
25
26#include "safeguards.h"
27
28static std::string *_fios_path = nullptr;
29
30/* OS-specific functions are taken from their respective files (win32/unix .c) */
31extern bool FiosIsRoot(const std::string &path);
32extern bool FiosIsHiddenFile(const std::filesystem::path &path);
33extern void FiosGetDrives(FileList &file_list);
34
35/* get the name of an oldstyle savegame */
36extern std::string GetOldSaveGameName(std::string_view file);
37
39bool FiosItemNameSorter(const FiosItem &a, const FiosItem &b)
40{
41 return StrNaturalCompare(a.title.GetDecodedString(), b.title.GetDecodedString()) < 0;
42}
43
46{
47 if (a.mtime == b.mtime) return FiosItemNameSorter(a, b);
48 return a.mtime < b.mtime;
49}
50
57void FileList::BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop, bool show_dirs)
58{
59 this->clear();
60
61 assert(fop == SaveLoadOperation::Load || fop == SaveLoadOperation::Save);
62 switch (abstract_filetype) {
64 break;
65
67 FiosGetSavegameList(fop, show_dirs, *this);
68 break;
69
71 FiosGetScenarioList(fop, show_dirs, *this);
72 break;
73
75 FiosGetHeightmapList(fop, show_dirs, *this);
76 break;
77
79 FiosGetTownDataList(fop, show_dirs, *this);
80 break;
81
82 default:
83 NOT_REACHED();
84 }
85}
86
93const FiosItem *FileList::FindItem(std::string_view file)
94{
95 for (const auto &it : *this) {
96 const FiosItem *item = &it;
97 if (file == item->name) return item;
98 if (file == item->title.GetDecodedString()) return item;
99 }
100
101 /* If no name matches, try to parse it as number */
102 StringConsumer consumer{file};
103 auto number = consumer.TryReadIntegerBase<int>(10);
104 if (number.has_value() && !consumer.AnyBytesLeft() && IsInsideMM(*number, 0, this->size())) return &this->at(*number);
105
106 /* As a last effort assume it is an OpenTTD savegame and
107 * that the ".sav" part was not given. */
108 std::string long_file(file);
109 long_file += ".sav";
110 for (const auto &it : *this) {
111 const FiosItem *item = &it;
112 if (long_file == item->name) return item;
113 if (long_file == item->title.GetDecodedString()) return item;
114 }
115
116 return nullptr;
117}
118
124{
125 return *_fios_path;
126}
127
133bool FiosBrowseTo(const FiosItem *item)
134{
135 switch (item->type.detailed) {
137#if defined(_WIN32)
138 assert(_fios_path != nullptr);
139 *_fios_path = std::string{ item->name, 0, 1 } + ":" PATHSEP;
140#endif
141 break;
142
144 break;
145
147 assert(_fios_path != nullptr);
148 auto s = _fios_path->find_last_of(PATHSEPCHAR);
149 if (s != std::string::npos && s != 0) {
150 _fios_path->erase(s); // Remove last path separator character, so we can go up one level.
151 }
152
153 s = _fios_path->find_last_of(PATHSEPCHAR);
154 if (s != std::string::npos) {
155 _fios_path->erase(s + 1); // go up a directory
156 }
157 break;
158 }
159
161 assert(_fios_path != nullptr);
162 *_fios_path += item->name;
163 *_fios_path += PATHSEP;
164 break;
165
167 assert(_fios_path != nullptr);
168 *_fios_path = item->name;
169 break;
170
171 default:
172 return false;
173 }
174
175 return true;
176}
177
185static std::string FiosMakeFilename(const std::string *path, std::string_view name, std::string_view ext)
186{
187 std::string_view base_path;
188
189 if (path != nullptr) {
190 base_path = *path;
191 /* Remove trailing path separator, if present */
192 if (!base_path.empty() && base_path.back() == PATHSEPCHAR) base_path.remove_suffix(1);
193 }
194
195 /* Don't append the extension if it is already there */
196 auto period = name.find_last_of('.');
197 if (period != std::string_view::npos && StrEqualsIgnoreCase(name.substr(period), ext)) ext = "";
198
199 return fmt::format("{}{}{}{}", base_path, PATHSEP, name, ext);
200}
201
207std::string FiosMakeSavegameName(std::string_view name)
208{
209 std::string_view extension = (_game_mode == GM_EDITOR) ? ".scn" : ".sav";
210
211 return FiosMakeFilename(_fios_path, name, extension);
212}
213
219std::string FiosMakeHeightmapName(std::string_view name)
220{
221 return FiosMakeFilename(_fios_path, name, fmt::format(".{}", GetCurrentScreenshotExtension()));
222}
223
224typedef std::tuple<FiosType, std::string> FiosGetTypeAndNameProc(SaveLoadOperation fop, std::string_view filename, std::string_view ext);
225
231 FiosGetTypeAndNameProc *callback_proc;
233public:
243
244 bool AddFile(const std::string &filename, size_t, const std::string &) override;
245};
246
252bool FiosFileScanner::AddFile(const std::string &filename, size_t, const std::string &)
253{
254 auto sep = filename.rfind('.');
255 if (sep == std::string::npos) return false;
256 std::string ext = filename.substr(sep);
257
258 auto [type, title] = this->callback_proc(this->fop, filename, ext);
259 if (type == FIOS_TYPE_INVALID) return false;
260
261 for (const auto &fios : file_list) {
262 if (filename == fios.name) return false;
263 }
264
265 FiosItem *fios = &file_list.emplace_back();
266
267 std::error_code error_code;
268 auto write_time = std::filesystem::last_write_time(OTTD2FS(filename), error_code);
269 if (error_code) {
270 fios->mtime = 0;
271 } else {
272 fios->mtime = std::chrono::duration_cast<std::chrono::milliseconds>(write_time.time_since_epoch()).count();
273 }
274
275 fios->type = type;
276 fios->name = filename;
277
278 /* If the file doesn't have a title, use its filename */
279 if (title.empty()) {
280 auto ps = filename.rfind(PATHSEPCHAR);
281 fios->title = GetEncodedString(STR_JUST_RAW_STRING, StrMakeValid(filename.substr((ps == std::string::npos ? 0 : ps + 1))));
282 } else {
283 fios->title = GetEncodedString(STR_JUST_RAW_STRING, StrMakeValid(title));
284 };
285
286 return true;
287}
288
289
298static void FiosGetFileList(SaveLoadOperation fop, bool show_dirs, FiosGetTypeAndNameProc *callback_proc, Subdirectory subdir, FileList &file_list)
299{
300 size_t sort_start = 0;
301
302 file_list.clear();
303
304 assert(_fios_path != nullptr);
305
306 if (show_dirs) {
307 /* A parent directory link exists if we are not in the root directory */
308 if (!FiosIsRoot(*_fios_path)) {
309 FiosItem &fios = file_list.emplace_back();
310 fios.type = FIOS_TYPE_PARENT;
311 fios.mtime = 0;
312 fios.name = "..";
313 fios.title = GetEncodedString(STR_SAVELOAD_PARENT_DIRECTORY, ".."sv);
314 sort_start = file_list.size();
315 }
316
317 /* Show subdirectories */
318 std::error_code error_code;
319 for (const auto &dir_entry : std::filesystem::directory_iterator(OTTD2FS(*_fios_path), error_code)) {
320 if (!dir_entry.is_directory()) continue;
321 if (FiosIsHiddenFile(dir_entry) && dir_entry.path().filename() != PERSONAL_DIR) continue;
322
323 FiosItem &fios = file_list.emplace_back();
324 fios.type = FIOS_TYPE_DIR;
325 fios.mtime = 0;
326 fios.name = FS2OTTD(dir_entry.path().filename().native());
327 fios.title = GetEncodedString(STR_SAVELOAD_DIRECTORY, fios.name + PATHSEP);
328 }
329
330 /* Sort the subdirs always ascending by name. */
331 std::sort(file_list.begin() + sort_start, file_list.end(), FiosItemNameSorter);
332 }
333
334 /* This is where to start sorting for the filenames */
335 sort_start = file_list.size();
336
337 /* Show files */
338 FiosFileScanner scanner(fop, callback_proc, file_list);
339 if (subdir == Subdirectory::None) {
340 scanner.Scan({}, *_fios_path, false);
341 } else {
342 scanner.Scan({}, subdir, true, true);
343 }
344
345 std::sort(file_list.begin() + sort_start, file_list.end(), FiosItemSorter);
346
347 /* Show drives */
348 FiosGetDrives(file_list);
349}
350
358static std::string GetFileTitle(std::string_view file, Subdirectory subdir)
359{
360 std::string filename = fmt::format("{}.title", file);
361 auto f = FioFOpenFile(filename, "r", subdir);
362 if (!f.has_value()) return {};
363
364 char title[80];
365 size_t read = fread(title, 1, lengthof(title), *f);
366
367 assert(read <= lengthof(title));
368 return StrMakeValid(std::string_view{title, read});
369}
370
380std::tuple<FiosType, std::string> FiosGetSavegameListCallback(SaveLoadOperation fop, std::string_view file, std::string_view ext)
381{
382 /* Show savegame files
383 * .SAV OpenTTD saved game
384 * .SS1 Transport Tycoon Deluxe preset game
385 * .SV1 Transport Tycoon Deluxe (Patch) saved game
386 * .SV2 Transport Tycoon Deluxe (Patch) saved 2-player game */
387
388 if (StrEqualsIgnoreCase(ext, ".sav")) {
389 return { FIOS_TYPE_FILE, GetFileTitle(file, Subdirectory::Save) };
390 }
391
392 if (fop == SaveLoadOperation::Load) {
393 if (StrEqualsIgnoreCase(ext, ".ss1") || StrEqualsIgnoreCase(ext, ".sv1") ||
394 StrEqualsIgnoreCase(ext, ".sv2")) {
395 return { FIOS_TYPE_OLDFILE, GetOldSaveGameName(file) };
396 }
397 }
398
399 return { FIOS_TYPE_INVALID, {} };
400}
401
409void FiosGetSavegameList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
410{
411 static std::optional<std::string> fios_save_path;
412
413 if (!fios_save_path) fios_save_path = FioFindDirectory(Subdirectory::Save);
414
415 _fios_path = &(*fios_save_path);
416
418}
419
429std::tuple<FiosType, std::string> FiosGetScenarioListCallback(SaveLoadOperation fop, std::string_view file, std::string_view ext)
430{
431 /* Show scenario files
432 * .SCN OpenTTD style scenario file
433 * .SV0 Transport Tycoon Deluxe (Patch) scenario
434 * .SS0 Transport Tycoon Deluxe preset scenario */
435 if (StrEqualsIgnoreCase(ext, ".scn")) {
436 return { FIOS_TYPE_SCENARIO, GetFileTitle(file, Subdirectory::Scenario) };
437
438 }
439
440 if (fop == SaveLoadOperation::Load) {
441 if (StrEqualsIgnoreCase(ext, ".sv0") || StrEqualsIgnoreCase(ext, ".ss0")) {
442 return { FIOS_TYPE_OLD_SCENARIO, GetOldSaveGameName(file) };
443 }
444 }
445
446 return { FIOS_TYPE_INVALID, {} };
447}
448
456void FiosGetScenarioList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
457{
458 static std::optional<std::string> fios_scn_path;
459
460 /* Copy the default path on first run or on 'New Game' */
461 if (!fios_scn_path) fios_scn_path = FioFindDirectory(Subdirectory::Scenario);
462
463 _fios_path = &(*fios_scn_path);
464
465 std::string base_path = FioFindDirectory(Subdirectory::Scenario);
466 Subdirectory subdir = (fop == SaveLoadOperation::Load && base_path == *_fios_path) ? Subdirectory::Scenario : Subdirectory::None;
467 FiosGetFileList(fop, show_dirs, &FiosGetScenarioListCallback, subdir, file_list);
468}
469
470std::tuple<FiosType, std::string> FiosGetHeightmapListCallback(SaveLoadOperation, std::string_view file, std::string_view ext)
471{
472 /* Show heightmap files
473 * .PNG PNG Based heightmap files
474 * .BMP BMP Based heightmap files
475 */
476
477 FiosType type = FIOS_TYPE_INVALID;
478
479#ifdef WITH_PNG
480 if (StrEqualsIgnoreCase(ext, ".png")) type = FIOS_TYPE_PNG;
481#endif /* WITH_PNG */
482
483 if (StrEqualsIgnoreCase(ext, ".bmp")) type = FIOS_TYPE_BMP;
484
485 if (type == FIOS_TYPE_INVALID) return { FIOS_TYPE_INVALID, {} };
486
487 TarFileList::iterator it = _tar_filelist[Subdirectory::Scenario].find(file);
488 if (it != _tar_filelist[Subdirectory::Scenario].end()) {
489 /* If the file is in a tar and that tar is not in a heightmap
490 * directory we are for sure not supposed to see it.
491 * Examples of this are pngs part of documentation within
492 * collections of NewGRFs or 32 bpp graphics replacement PNGs.
493 */
494 bool match = false;
495 for (Searchpath sp : _valid_searchpaths) {
496 std::string buf = FioGetDirectory(sp, Subdirectory::Heightmap);
497
498 if (it->second.tar_filename.starts_with(buf)) {
499 match = true;
500 break;
501 }
502 }
503
504 if (!match) return { FIOS_TYPE_INVALID, {} };
505 }
506
507 return { type, GetFileTitle(file, Subdirectory::Heightmap) };
508}
509
516void FiosGetHeightmapList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
517{
518 static std::optional<std::string> fios_hmap_path;
519
520 if (!fios_hmap_path) fios_hmap_path = FioFindDirectory(Subdirectory::Heightmap);
521
522 _fios_path = &(*fios_hmap_path);
523
524 std::string base_path = FioFindDirectory(Subdirectory::Heightmap);
525 Subdirectory subdir = base_path == *_fios_path ? Subdirectory::Heightmap : Subdirectory::None;
526 FiosGetFileList(fop, show_dirs, &FiosGetHeightmapListCallback, subdir, file_list);
527}
528
536static std::tuple<FiosType, std::string> FiosGetTownDataListCallback(SaveLoadOperation fop, std::string_view file, std::string_view ext)
537{
538 if (fop == SaveLoadOperation::Load) {
539 if (StrEqualsIgnoreCase(ext, ".json")) {
540 return { FIOS_TYPE_JSON, GetFileTitle(file, Subdirectory::Save) };
541 }
542 }
543
544 return { FIOS_TYPE_INVALID, {} };
545}
546
553void FiosGetTownDataList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
554{
555 static std::optional<std::string> fios_town_data_path;
556
557 if (!fios_town_data_path) fios_town_data_path = FioFindDirectory(Subdirectory::Heightmap);
558
559 _fios_path = &(*fios_town_data_path);
560
561 std::string base_path = FioFindDirectory(Subdirectory::Heightmap);
562 Subdirectory subdir = base_path == *_fios_path ? Subdirectory::Heightmap : Subdirectory::None;
563 FiosGetFileList(fop, show_dirs, &FiosGetTownDataListCallback, subdir, file_list);
564}
565
570std::string_view FiosGetScreenshotDir()
571{
572 static std::optional<std::string> fios_screenshot_path;
573
574 if (!fios_screenshot_path) fios_screenshot_path = FioFindDirectory(Subdirectory::Screenshot);
575
576 return *fios_screenshot_path;
577}
578
581 uint32_t scenid;
582 MD5Hash md5sum;
583 std::string filename;
584
585 bool operator == (const ScenarioIdentifier &other) const
586 {
587 return this->scenid == other.scenid && this->md5sum == other.md5sum;
588 }
589};
590
594class ScenarioScanner : protected FileScanner, public std::vector<ScenarioIdentifier> {
595 bool scanned;
596public:
599
604 void Scan(bool rescan)
605 {
606 if (this->scanned && !rescan) return;
607
608 this->FileScanner::Scan(".id", Subdirectory::Scenario, true, true);
609 this->scanned = true;
610 }
611
612 bool AddFile(const std::string &filename, size_t, const std::string &) override
613 {
614 auto f = FioFOpenFile(filename, "r", Subdirectory::Scenario);
615 if (!f.has_value()) return false;
616
618 int fret = fscanf(*f, "%u", &id.scenid);
619 if (fret != 1) return false;
620 id.filename = filename;
621
622 Md5 checksum;
623 uint8_t buffer[1024];
624 size_t len, size;
625
626 /* open the scenario file, but first get the name.
627 * This is safe as we check on extension which
628 * must always exist. */
629 f = FioFOpenFile(filename.substr(0, filename.rfind('.')), "rb", Subdirectory::Scenario, &size);
630 if (!f.has_value()) return false;
631
632 /* calculate md5sum */
633 while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, *f)) != 0 && size != 0) {
634 size -= len;
635 checksum.Append(buffer, len);
636 }
637 checksum.Finish(id.md5sum);
638
639 include(*this, id);
640 return true;
641 }
642};
643
646
653std::optional<std::string_view> FindScenario(const ContentInfo &ci, bool md5sum)
654{
655 _scanner.Scan(false);
656
657 for (ScenarioIdentifier &id : _scanner) {
658 if (md5sum ? (id.md5sum == ci.md5sum)
659 : (id.scenid == ci.unique_id)) {
660 return id.filename;
661 }
662 }
663
664 return std::nullopt;
665}
666
673bool HasScenario(const ContentInfo &ci, bool md5sum)
674{
675 return FindScenario(ci, md5sum).has_value();
676}
677
682{
683 _scanner.Scan(true);
684}
685
690FiosNumberedSaveName::FiosNumberedSaveName(const std::string &prefix) : prefix(prefix), number(-1)
691{
692 static std::optional<std::string> _autosave_path;
693 if (!_autosave_path) _autosave_path = FioFindDirectory(Subdirectory::Autosave);
694
695 static std::string _prefix;
696
697 /* Callback for FiosFileScanner. */
698 static FiosGetTypeAndNameProc *const proc = [](SaveLoadOperation, std::string_view file, std::string_view ext) {
699 if (StrEqualsIgnoreCase(ext, ".sav") && file.starts_with(_prefix)) return std::tuple(FIOS_TYPE_FILE, std::string{});
700 return std::tuple(FIOS_TYPE_INVALID, std::string{});
701 };
702
703 /* Prefix to check in the callback. */
704 _prefix = *_autosave_path + this->prefix;
705
706 /* Get the save list. */
707 FileList list;
708 FiosFileScanner scanner(SaveLoadOperation::Save, proc, list);
709 scanner.Scan(".sav", *_autosave_path, false);
710
711 /* Find the number for the most recent save, if any. */
712 if (!list.empty()) {
713 auto elem = std::ranges::max_element(list, FiosItemModificationDateSorter);
714 std::string name = elem->title.GetDecodedString();
715 std::from_chars(name.data() + this->prefix.size(), name.data() + name.size(), this->number);
716 }
717}
718
724{
725 if (++this->number >= _settings_client.gui.max_num_autosaves) this->number = 0;
726 return fmt::format("{}{}.sav", this->prefix, this->number);
727}
728
734{
735 return fmt::format("-{}.sav", this->prefix);
736}
std::string GetDecodedString() const
Decode the encoded string.
Definition strings.cpp:207
List of file information.
Definition fios.h:86
void BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop, bool show_dirs)
Construct a file list with the given kind of files, for the stated purpose.
Definition fios.cpp:57
const FiosItem * FindItem(std::string_view file)
Find file information of a file by its name from the file list.
Definition fios.cpp:93
Helper for scanning for files with a given name.
Definition fileio_func.h:37
uint Scan(std::string_view extension, Subdirectory sd, bool tars=true, bool recursive=true)
Scan for files with the given extension in the given search path.
Definition fileio.cpp:1123
Scanner to scan for a particular type of FIOS file.
Definition fios.cpp:229
FiosFileScanner(SaveLoadOperation fop, FiosGetTypeAndNameProc *callback_proc, FileList &file_list)
Create the scanner.
Definition fios.cpp:240
SaveLoadOperation fop
The kind of file we are looking for.
Definition fios.cpp:230
FileList & file_list
Destination of the found files.
Definition fios.cpp:232
bool AddFile(const std::string &filename, size_t, const std::string &) override
Try to add a fios item set with the given filename.
Definition fios.cpp:252
FiosGetTypeAndNameProc * callback_proc
Callback to check whether the file may be added.
Definition fios.cpp:231
Scanner to find the unique IDs of scenarios.
Definition fios.cpp:594
bool scanned
Whether we've already scanned.
Definition fios.cpp:595
void Scan(bool rescan)
Scan, but only if it's needed.
Definition fios.cpp:604
bool AddFile(const std::string &filename, size_t, const std::string &) override
Add a file with the given filename.
Definition fios.cpp:612
ScenarioScanner()
Initialise.
Definition fios.cpp:598
Parse data from a string / buffer.
std::optional< T > TryReadIntegerBase(int base, bool clamp=false)
Try to read and parse an integer in number 'base', and then advance the reader.
bool AnyBytesLeft() const noexcept
Check whether any bytes left to read.
bool include(Container &container, typename Container::const_reference &item)
Helper function to append an item to a container if it is not already contained.
std::optional< FileHandle > FioFOpenFile(std::string_view filename, std::string_view mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
Definition fileio.cpp:246
EnumClassIndexContainer< std::array< TarFileList, to_underlying(Subdirectory::End)>, Subdirectory > _tar_filelist
List of files within tar files found in each subdirectory.
Definition fileio.cpp:70
Functions for standard in/out file operations.
SaveLoadOperation
Operation performed on the file.
Definition fileio_type.h:52
@ Save
File is being saved.
Definition fileio_type.h:55
@ Load
File is being loaded.
Definition fileio_type.h:54
@ FiosDirect
Direct filename.
Definition fileio_type.h:44
@ FiosDrive
A drive (letter) entry.
Definition fileio_type.h:41
@ Invalid
Unknown or invalid file.
Definition fileio_type.h:48
@ FiosDirectory
A directory entry.
Definition fileio_type.h:43
@ FiosParent
A parent directory entry.
Definition fileio_type.h:42
Searchpath
Types of searchpaths OpenTTD might use.
Subdirectory
The different kinds of subdirectories OpenTTD uses.
Definition fileio_type.h:88
@ Autosave
Subdirectory of save for autosaves.
Definition fileio_type.h:91
@ Screenshot
Subdirectory for all screenshots.
@ Scenario
Base directory for all scenarios.
Definition fileio_type.h:92
@ Heightmap
Subdirectory of scenario for heightmaps.
Definition fileio_type.h:93
@ None
A path without any base directory.
@ Save
Base directory for all savegames.
Definition fileio_type.h:90
AbstractFileType
The different abstract types of files that the system knows about.
Definition fileio_type.h:17
@ Savegame
old or new savegame
Definition fileio_type.h:19
@ Scenario
old or new scenario
Definition fileio_type.h:20
@ Heightmap
heightmap file
Definition fileio_type.h:21
@ None
nothing to do
Definition fileio_type.h:18
@ TownData
town data file
Definition fileio_type.h:22
std::tuple< FiosType, std::string > FiosGetScenarioListCallback(SaveLoadOperation fop, std::string_view file, std::string_view ext)
Callback for FiosGetFileList.
Definition fios.cpp:429
bool FiosItemModificationDateSorter(const FiosItem &a, const FiosItem &b)
Sort files by their modification date, and name when they are equal.
Definition fios.cpp:45
static std::tuple< FiosType, std::string > FiosGetTownDataListCallback(SaveLoadOperation fop, std::string_view file, std::string_view ext)
Callback for FiosGetTownDataList.
Definition fios.cpp:536
std::optional< std::string_view > FindScenario(const ContentInfo &ci, bool md5sum)
Find a given scenario based on its unique ID.
Definition fios.cpp:653
std::string FiosMakeSavegameName(std::string_view name)
Make a save game or scenario filename from a name.
Definition fios.cpp:207
bool FiosItemNameSorter(const FiosItem &a, const FiosItem &b)
Sort files by their name.
Definition fios.cpp:39
std::tuple< FiosType, std::string > FiosGetSavegameListCallback(SaveLoadOperation fop, std::string_view file, std::string_view ext)
Callback for FiosGetFileList.
Definition fios.cpp:380
static std::string GetFileTitle(std::string_view file, Subdirectory subdir)
Get the title of a file, which (if exists) is stored in a file named the same as the data file but wi...
Definition fios.cpp:358
std::string FiosGetCurrentPath()
Get the current path/working directory.
Definition fios.cpp:123
static std::string FiosMakeFilename(const std::string *path, std::string_view name, std::string_view ext)
Construct a filename from its components in destination buffer buf.
Definition fios.cpp:185
void FiosGetSavegameList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of savegames.
Definition fios.cpp:409
void FiosGetHeightmapList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of heightmaps.
Definition fios.cpp:516
static void FiosGetFileList(SaveLoadOperation fop, bool show_dirs, FiosGetTypeAndNameProc *callback_proc, Subdirectory subdir, FileList &file_list)
Fill the list of the files in a directory, according to some arbitrary rule.
Definition fios.cpp:298
void ScanScenarios()
Force a (re)scan of the scenarios.
Definition fios.cpp:681
std::string FiosMakeHeightmapName(std::string_view name)
Construct a filename for a height map.
Definition fios.cpp:219
bool HasScenario(const ContentInfo &ci, bool md5sum)
Check whether we've got a given scenario based on its unique ID.
Definition fios.cpp:673
void FiosGetScenarioList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of scenarios.
Definition fios.cpp:456
std::string_view FiosGetScreenshotDir()
Get the directory for screenshots.
Definition fios.cpp:570
bool FiosBrowseTo(const FiosItem *item)
Browse to a new path based on the passed item, starting at _fios_path.
Definition fios.cpp:133
static ScenarioScanner _scanner
Scanner for scenarios.
Definition fios.cpp:645
void FiosGetTownDataList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of town data files.
Definition fios.cpp:553
Declarations for savegames operations.
bool FiosItemSorter(const FiosItem &a, const FiosItem &b)
Sorts the FiosItems based on the savegame sorter and order.
Definition fios_gui.cpp:56
bool FiosItemModificationDateSorter(const FiosItem &a, const FiosItem &b)
Sort files by their modification date, and name when they are equal.
Definition fios.cpp:45
void FiosGetSavegameList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of savegames.
Definition fios.cpp:409
void FiosGetHeightmapList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of heightmaps.
Definition fios.cpp:516
void FiosGetScenarioList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of scenarios.
Definition fios.cpp:456
void FiosGetTownDataList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of town data files.
Definition fios.cpp:553
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Part of the network protocol handling content distribution.
A number of safeguards to prevent using unsafe methods.
std::string_view GetCurrentScreenshotExtension()
Get filename extension of current screenshot file format.
Functions to make screenshots.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
bool StrEqualsIgnoreCase(std::string_view str1, std::string_view str2)
Compares two string( view)s for equality, while ignoring the case of the characters.
Definition string.cpp:325
int StrNaturalCompare(std::string_view s1, std::string_view s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition string.cpp:429
static void StrMakeValid(Builder &builder, StringConsumer &consumer, StringValidationSettings settings)
Copies the valid (UTF-8) characters from consumer to the builder.
Definition string.cpp:119
Parse strings.
Functions related to low-level strings.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
Functions related to OTTD's strings.
Container for all important information about a piece of content.
uint32_t unique_id
Unique ID; either GRF ID or shortname.
MD5Hash md5sum
The MD5 checksum.
Deals with finding savegames.
Definition fios.h:78
std::string Filename()
Generate a savegame name and number according to _settings_client.gui.max_num_autosaves.
Definition fios.cpp:723
FiosNumberedSaveName(const std::string &prefix)
Constructs FiosNumberedSaveName.
Definition fios.cpp:690
std::string Extension()
Generate an extension for a savegame name.
Definition fios.cpp:733
Elements of a file system that are recognized.
Definition fileio_type.h:63
DetailedFileType detailed
Detailed file type.
Definition fileio_type.h:65
Basic data to distinguish a scenario.
Definition fios.cpp:580
uint32_t scenid
ID for the scenario (generated by content).
Definition fios.cpp:581
MD5Hash md5sum
MD5 checksum of file.
Definition fios.cpp:582
std::string filename
filename of the file.
Definition fios.cpp:583
Structs, typedefs and macros used for TAR file handling.
std::wstring OTTD2FS(std::string_view name)
Convert from OpenTTD's encoding to a wide string.
Definition win32.cpp:368
std::string FS2OTTD(std::wstring_view name)
Convert to OpenTTD's encoding from a wide string.
Definition win32.cpp:352