OpenTTD Source 20260820-master-g39da062c0c
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
135{
136 assert(_fios_path != nullptr);
137
138 /* Remove trailing path separator, if present. */
139 std::string_view base = *_fios_path;
140 if (!base.empty() && base.back() == PATHSEPCHAR) base.remove_suffix(1);
141 /* Join with a single separator, converting via OTTD2FS so non-ASCII names work on Windows. */
142 std::filesystem::path target = OTTD2FS(fmt::format("{}{}{}", base, PATHSEP, name));
143
144 std::error_code error_code;
145 if (std::filesystem::create_directory(target, error_code)) {
147 }
148
149 /* A false return with no error means the target already exists. Confirm it is a directory to tell it apart from a stray file or other entry. */
150 if (!error_code) {
151 return std::filesystem::is_directory(target, error_code) ? DirectoryCreateResult::AlreadyExists : DirectoryCreateResult::OtherError;
152 }
153
154 /* An existing non-directory file shows up here as file_exists. */
155 if (error_code == std::errc::file_exists) return DirectoryCreateResult::AlreadyExists;
156 if (error_code == std::errc::permission_denied || error_code == std::errc::read_only_file_system) return DirectoryCreateResult::PermissionDenied;
158}
159
165bool FiosBrowseTo(const FiosItem *item)
166{
167 switch (item->type.detailed) {
169#if defined(_WIN32)
170 assert(_fios_path != nullptr);
171 *_fios_path = std::string{ item->name, 0, 1 } + ":" PATHSEP;
172#endif
173 break;
174
176 break;
177
179 assert(_fios_path != nullptr);
180 auto s = _fios_path->find_last_of(PATHSEPCHAR);
181 if (s != std::string::npos && s != 0) {
182 _fios_path->erase(s); // Remove last path separator character, so we can go up one level.
183 }
184
185 s = _fios_path->find_last_of(PATHSEPCHAR);
186 if (s != std::string::npos) {
187 _fios_path->erase(s + 1); // go up a directory
188 }
189 break;
190 }
191
193 assert(_fios_path != nullptr);
194 *_fios_path += item->name;
195 *_fios_path += PATHSEP;
196 break;
197
199 assert(_fios_path != nullptr);
200 *_fios_path = item->name;
201 break;
202
203 default:
204 return false;
205 }
206
207 return true;
208}
209
217static std::string FiosMakeFilename(const std::string *path, std::string_view name, std::string_view ext)
218{
219 std::string_view base_path;
220
221 if (path != nullptr) {
222 base_path = *path;
223 /* Remove trailing path separator, if present */
224 if (!base_path.empty() && base_path.back() == PATHSEPCHAR) base_path.remove_suffix(1);
225 }
226
227 /* Don't append the extension if it is already there */
228 auto period = name.find_last_of('.');
229 if (period != std::string_view::npos && StrEqualsIgnoreCase(name.substr(period), ext)) ext = "";
230
231 return fmt::format("{}{}{}{}", base_path, PATHSEP, name, ext);
232}
233
239std::string FiosMakeSavegameName(std::string_view name)
240{
241 std::string_view extension = (_game_mode == GameMode::Editor) ? ".scn" : ".sav";
242
243 return FiosMakeFilename(_fios_path, name, extension);
244}
245
251std::string FiosMakeHeightmapName(std::string_view name)
252{
253 return FiosMakeFilename(_fios_path, name, fmt::format(".{}", GetCurrentScreenshotExtension()));
254}
255
256typedef std::tuple<FiosType, std::string> FiosGetTypeAndNameProc(SaveLoadOperation fop, std::string_view filename, std::string_view ext);
257
263 FiosGetTypeAndNameProc *callback_proc;
265public:
275
276 bool AddFile(const std::string &filename, size_t, const std::string &) override;
277};
278
284bool FiosFileScanner::AddFile(const std::string &filename, size_t, const std::string &)
285{
286 auto sep = filename.rfind('.');
287 if (sep == std::string::npos) return false;
288 std::string ext = filename.substr(sep);
289
290 auto [type, title] = this->callback_proc(this->fop, filename, ext);
291 if (type == FIOS_TYPE_INVALID) return false;
292
293 for (const auto &fios : file_list) {
294 if (filename == fios.name) return false;
295 }
296
297 FiosItem *fios = &file_list.emplace_back();
298
299 std::error_code error_code;
300 auto write_time = std::filesystem::last_write_time(OTTD2FS(filename), error_code);
301 if (error_code) {
302 fios->mtime = 0;
303 } else {
304 fios->mtime = std::chrono::duration_cast<std::chrono::milliseconds>(write_time.time_since_epoch()).count();
305 }
306
307 fios->type = type;
308 fios->name = filename;
309
310 /* If the file doesn't have a title, use its filename */
311 if (title.empty()) {
312 auto ps = filename.rfind(PATHSEPCHAR);
313 fios->title = GetEncodedString(STR_JUST_RAW_STRING, StrMakeValid(filename.substr((ps == std::string::npos ? 0 : ps + 1))));
314 } else {
315 fios->title = GetEncodedString(STR_JUST_RAW_STRING, StrMakeValid(title));
316 };
317
318 return true;
319}
320
321
330static void FiosGetFileList(SaveLoadOperation fop, bool show_dirs, FiosGetTypeAndNameProc *callback_proc, Subdirectory subdir, FileList &file_list)
331{
332 size_t sort_start = 0;
333
334 file_list.clear();
335
336 assert(_fios_path != nullptr);
337
338 if (show_dirs) {
339 /* A parent directory link exists if we are not in the root directory */
340 if (!FiosIsRoot(*_fios_path)) {
341 FiosItem &fios = file_list.emplace_back();
342 fios.type = FIOS_TYPE_PARENT;
343 fios.mtime = 0;
344 fios.name = "..";
345 fios.title = GetEncodedString(STR_SAVELOAD_PARENT_DIRECTORY, ".."sv);
346 sort_start = file_list.size();
347 }
348
349 /* Show subdirectories */
350 std::error_code error_code;
351 for (const auto &dir_entry : std::filesystem::directory_iterator(OTTD2FS(*_fios_path), error_code)) {
352 if (!dir_entry.is_directory()) continue;
353 if (FiosIsHiddenFile(dir_entry) && dir_entry.path().filename() != PERSONAL_DIR) continue;
354
355 FiosItem &fios = file_list.emplace_back();
356 fios.type = FIOS_TYPE_DIR;
357 fios.mtime = 0;
358 fios.name = FS2OTTD(dir_entry.path().filename().native());
359 fios.title = GetEncodedString(STR_SAVELOAD_DIRECTORY, fios.name + PATHSEP);
360 }
361
362 /* Sort the subdirs always ascending by name. */
363 std::sort(file_list.begin() + sort_start, file_list.end(), FiosItemNameSorter);
364 }
365
366 /* This is where to start sorting for the filenames */
367 sort_start = file_list.size();
368
369 /* Show files */
370 FiosFileScanner scanner(fop, callback_proc, file_list);
371 if (subdir == Subdirectory::None) {
372 scanner.Scan({}, *_fios_path, false);
373 } else {
374 scanner.Scan({}, subdir, true, true);
375 }
376
377 std::sort(file_list.begin() + sort_start, file_list.end(), FiosItemSorter);
378
379 /* Show drives */
380 FiosGetDrives(file_list);
381}
382
390static std::string GetFileTitle(std::string_view file, Subdirectory subdir)
391{
392 std::string filename = fmt::format("{}.title", file);
393 auto f = FioFOpenFile(filename, "r", subdir);
394 if (!f.has_value()) return {};
395
396 char title[80];
397 size_t read = fread(title, 1, lengthof(title), *f);
398
399 assert(read <= lengthof(title));
400 return StrMakeValid(std::string_view{title, read});
401}
402
412std::tuple<FiosType, std::string> FiosGetSavegameListCallback(SaveLoadOperation fop, std::string_view file, std::string_view ext)
413{
414 /* Show savegame files
415 * .SAV OpenTTD saved game
416 * .SS1 Transport Tycoon Deluxe preset game
417 * .SV1 Transport Tycoon Deluxe (Patch) saved game
418 * .SV2 Transport Tycoon Deluxe (Patch) saved 2-player game */
419
420 if (StrEqualsIgnoreCase(ext, ".sav")) {
421 return { FIOS_TYPE_FILE, GetFileTitle(file, Subdirectory::Save) };
422 }
423
424 if (fop == SaveLoadOperation::Load) {
425 if (StrEqualsIgnoreCase(ext, ".ss1") || StrEqualsIgnoreCase(ext, ".sv1") ||
426 StrEqualsIgnoreCase(ext, ".sv2")) {
427 return { FIOS_TYPE_OLDFILE, GetOldSaveGameName(file) };
428 }
429 }
430
431 return { FIOS_TYPE_INVALID, {} };
432}
433
441void FiosGetSavegameList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
442{
443 static std::optional<std::string> fios_save_path;
444
445 if (!fios_save_path) fios_save_path = FioFindDirectory(Subdirectory::Save);
446
447 _fios_path = &(*fios_save_path);
448
450}
451
461std::tuple<FiosType, std::string> FiosGetScenarioListCallback(SaveLoadOperation fop, std::string_view file, std::string_view ext)
462{
463 /* Show scenario files
464 * .SCN OpenTTD style scenario file
465 * .SV0 Transport Tycoon Deluxe (Patch) scenario
466 * .SS0 Transport Tycoon Deluxe preset scenario */
467 if (StrEqualsIgnoreCase(ext, ".scn")) {
468 return { FIOS_TYPE_SCENARIO, GetFileTitle(file, Subdirectory::Scenario) };
469
470 }
471
472 if (fop == SaveLoadOperation::Load) {
473 if (StrEqualsIgnoreCase(ext, ".sv0") || StrEqualsIgnoreCase(ext, ".ss0")) {
474 return { FIOS_TYPE_OLD_SCENARIO, GetOldSaveGameName(file) };
475 }
476 }
477
478 return { FIOS_TYPE_INVALID, {} };
479}
480
488void FiosGetScenarioList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
489{
490 static std::optional<std::string> fios_scn_path;
491
492 /* Copy the default path on first run or on 'New Game' */
493 if (!fios_scn_path) fios_scn_path = FioFindDirectory(Subdirectory::Scenario);
494
495 _fios_path = &(*fios_scn_path);
496
497 std::string base_path = FioFindDirectory(Subdirectory::Scenario);
498 Subdirectory subdir = (fop == SaveLoadOperation::Load && base_path == *_fios_path) ? Subdirectory::Scenario : Subdirectory::None;
499 FiosGetFileList(fop, show_dirs, &FiosGetScenarioListCallback, subdir, file_list);
500}
501
502std::tuple<FiosType, std::string> FiosGetHeightmapListCallback(SaveLoadOperation, std::string_view file, std::string_view ext)
503{
504 /* Show heightmap files
505 * .PNG PNG Based heightmap files
506 * .BMP BMP Based heightmap files
507 */
508
509 FiosType type = FIOS_TYPE_INVALID;
510
511#ifdef WITH_PNG
512 if (StrEqualsIgnoreCase(ext, ".png")) type = FIOS_TYPE_PNG;
513#endif /* WITH_PNG */
514
515 if (StrEqualsIgnoreCase(ext, ".bmp")) type = FIOS_TYPE_BMP;
516
517 if (type == FIOS_TYPE_INVALID) return { FIOS_TYPE_INVALID, {} };
518
519 TarFileList::iterator it = _tar_filelist[Subdirectory::Scenario].find(file);
520 if (it != _tar_filelist[Subdirectory::Scenario].end()) {
521 /* If the file is in a tar and that tar is not in a heightmap
522 * directory we are for sure not supposed to see it.
523 * Examples of this are pngs part of documentation within
524 * collections of NewGRFs or 32 bpp graphics replacement PNGs.
525 */
526 bool match = false;
527 for (Searchpath sp : _valid_searchpaths) {
528 std::string buf = FioGetDirectory(sp, Subdirectory::Heightmap);
529
530 if (it->second.tar_filename.starts_with(buf)) {
531 match = true;
532 break;
533 }
534 }
535
536 if (!match) return { FIOS_TYPE_INVALID, {} };
537 }
538
539 return { type, GetFileTitle(file, Subdirectory::Heightmap) };
540}
541
548void FiosGetHeightmapList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
549{
550 static std::optional<std::string> fios_hmap_path;
551
552 if (!fios_hmap_path) fios_hmap_path = FioFindDirectory(Subdirectory::Heightmap);
553
554 _fios_path = &(*fios_hmap_path);
555
556 std::string base_path = FioFindDirectory(Subdirectory::Heightmap);
557 Subdirectory subdir = base_path == *_fios_path ? Subdirectory::Heightmap : Subdirectory::None;
558 FiosGetFileList(fop, show_dirs, &FiosGetHeightmapListCallback, subdir, file_list);
559}
560
568static std::tuple<FiosType, std::string> FiosGetTownDataListCallback(SaveLoadOperation fop, std::string_view file, std::string_view ext)
569{
570 if (fop == SaveLoadOperation::Load) {
571 if (StrEqualsIgnoreCase(ext, ".json")) {
572 return { FIOS_TYPE_JSON, GetFileTitle(file, Subdirectory::Save) };
573 }
574 }
575
576 return { FIOS_TYPE_INVALID, {} };
577}
578
585void FiosGetTownDataList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
586{
587 static std::optional<std::string> fios_town_data_path;
588
589 if (!fios_town_data_path) fios_town_data_path = FioFindDirectory(Subdirectory::Heightmap);
590
591 _fios_path = &(*fios_town_data_path);
592
593 std::string base_path = FioFindDirectory(Subdirectory::Heightmap);
594 Subdirectory subdir = base_path == *_fios_path ? Subdirectory::Heightmap : Subdirectory::None;
595 FiosGetFileList(fop, show_dirs, &FiosGetTownDataListCallback, subdir, file_list);
596}
597
602std::string_view FiosGetScreenshotDir()
603{
604 static std::optional<std::string> fios_screenshot_path;
605
606 if (!fios_screenshot_path) fios_screenshot_path = FioFindDirectory(Subdirectory::Screenshot);
607
608 return *fios_screenshot_path;
609}
610
613 uint32_t scenid;
614 MD5Hash md5sum;
615 std::string filename;
616
617 bool operator == (const ScenarioIdentifier &other) const
618 {
619 return this->scenid == other.scenid && this->md5sum == other.md5sum;
620 }
621};
622
626class ScenarioScanner : protected FileScanner, public std::vector<ScenarioIdentifier> {
627 bool scanned;
628public:
631
636 void Scan(bool rescan)
637 {
638 if (this->scanned && !rescan) return;
639
640 this->FileScanner::Scan(".id", Subdirectory::Scenario, true, true);
641 this->scanned = true;
642 }
643
644 bool AddFile(const std::string &filename, size_t, const std::string &) override
645 {
646 auto f = FioFOpenFile(filename, "r", Subdirectory::Scenario);
647 if (!f.has_value()) return false;
648
650 int fret = fscanf(*f, "%u", &id.scenid);
651 if (fret != 1) return false;
652 id.filename = filename;
653
654 Md5 checksum;
655 uint8_t buffer[1024];
656 size_t len, size;
657
658 /* open the scenario file, but first get the name.
659 * This is safe as we check on extension which
660 * must always exist. */
661 f = FioFOpenFile(filename.substr(0, filename.rfind('.')), "rb", Subdirectory::Scenario, &size);
662 if (!f.has_value()) return false;
663
664 /* calculate md5sum */
665 while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, *f)) != 0 && size != 0) {
666 size -= len;
667 checksum.Append(buffer, len);
668 }
669 checksum.Finish(id.md5sum);
670
671 include(*this, id);
672 return true;
673 }
674};
675
678
685std::optional<std::string_view> FindScenario(const ContentInfo &ci, bool md5sum)
686{
687 _scanner.Scan(false);
688
689 for (ScenarioIdentifier &id : _scanner) {
690 if (md5sum ? (id.md5sum == ci.md5sum)
691 : (id.scenid == ci.unique_id)) {
692 return id.filename;
693 }
694 }
695
696 return std::nullopt;
697}
698
705bool HasScenario(const ContentInfo &ci, bool md5sum)
706{
707 return FindScenario(ci, md5sum).has_value();
708}
709
714{
715 _scanner.Scan(true);
716}
717
722FiosNumberedSaveName::FiosNumberedSaveName(const std::string &prefix) : prefix(prefix), number(-1)
723{
724 static std::optional<std::string> _autosave_path;
725 if (!_autosave_path) _autosave_path = FioFindDirectory(Subdirectory::Autosave);
726
727 static std::string _prefix;
728
729 /* Callback for FiosFileScanner. */
730 static FiosGetTypeAndNameProc *const proc = [](SaveLoadOperation, std::string_view file, std::string_view ext) {
731 if (StrEqualsIgnoreCase(ext, ".sav") && file.starts_with(_prefix)) return std::tuple(FIOS_TYPE_FILE, std::string{});
732 return std::tuple(FIOS_TYPE_INVALID, std::string{});
733 };
734
735 /* Prefix to check in the callback. */
736 _prefix = *_autosave_path + this->prefix;
737
738 /* Get the save list. */
739 FileList list;
740 FiosFileScanner scanner(SaveLoadOperation::Save, proc, list);
741 scanner.Scan(".sav", *_autosave_path, false);
742
743 /* Find the number for the most recent save, if any. */
744 if (!list.empty()) {
745 auto elem = std::ranges::max_element(list, FiosItemModificationDateSorter);
746 std::string name = elem->title.GetDecodedString();
747 std::from_chars(name.data() + this->prefix.size(), name.data() + name.size(), this->number);
748 }
749}
750
756{
757 if (++this->number >= _settings_client.gui.max_num_autosaves) this->number = 0;
758 return fmt::format("{}{}.sav", this->prefix, this->number);
759}
760
766{
767 return fmt::format("-{}.sav", this->prefix);
768}
std::string GetDecodedString() const
Decode the encoded string.
Definition strings.cpp:207
List of file information.
Definition fios.h:94
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:1170
Scanner to scan for a particular type of FIOS file.
Definition fios.cpp:261
FiosFileScanner(SaveLoadOperation fop, FiosGetTypeAndNameProc *callback_proc, FileList &file_list)
Create the scanner.
Definition fios.cpp:272
SaveLoadOperation fop
The kind of file we are looking for.
Definition fios.cpp:262
FileList & file_list
Destination of the found files.
Definition fios.cpp:264
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:284
FiosGetTypeAndNameProc * callback_proc
Callback to check whether the file may be added.
Definition fios.cpp:263
Scanner to find the unique IDs of scenarios.
Definition fios.cpp:626
bool scanned
Whether we've already scanned.
Definition fios.cpp:627
void Scan(bool rescan)
Scan, but only if it's needed.
Definition fios.cpp:636
bool AddFile(const std::string &filename, size_t, const std::string &) override
Add a file with the given filename.
Definition fios.cpp:644
ScenarioScanner()
Initialise.
Definition fios.cpp:630
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.
EnumIndexArray< TarFileList, Subdirectory, Subdirectory::End > _tar_filelist
List of files within tar files found in each subdirectory.
Definition fileio.cpp:70
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:249
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:461
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:568
std::optional< std::string_view > FindScenario(const ContentInfo &ci, bool md5sum)
Find a given scenario based on its unique ID.
Definition fios.cpp:685
std::string FiosMakeSavegameName(std::string_view name)
Make a save game or scenario filename from a name.
Definition fios.cpp:239
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:412
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:390
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:217
void FiosGetSavegameList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of savegames.
Definition fios.cpp:441
void FiosGetHeightmapList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of heightmaps.
Definition fios.cpp:548
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:330
void ScanScenarios()
Force a (re)scan of the scenarios.
Definition fios.cpp:713
std::string FiosMakeHeightmapName(std::string_view name)
Construct a filename for a height map.
Definition fios.cpp:251
bool HasScenario(const ContentInfo &ci, bool md5sum)
Check whether we've got a given scenario based on its unique ID.
Definition fios.cpp:705
void FiosGetScenarioList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of scenarios.
Definition fios.cpp:488
std::string_view FiosGetScreenshotDir()
Get the directory for screenshots.
Definition fios.cpp:602
DirectoryCreateResult FiosCreateDirectory(std::string_view name)
Create a new subdirectory inside the current FIOS path.
Definition fios.cpp:134
bool FiosBrowseTo(const FiosItem *item)
Browse to a new path based on the passed item, starting at _fios_path.
Definition fios.cpp:165
static ScenarioScanner _scanner
Scanner for scenarios.
Definition fios.cpp:677
void FiosGetTownDataList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of town data files.
Definition fios.cpp:585
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:57
DirectoryCreateResult
Outcome of a directory creation attempt.
Definition fios.h:29
@ PermissionDenied
The OS rejected the operation for permission reasons.
Definition fios.h:32
@ Success
Directory was created.
Definition fios.h:30
@ OtherError
Any other filesystem error.
Definition fios.h:33
@ AlreadyExists
A file or directory with that name already exists.
Definition fios.h:31
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:441
void FiosGetHeightmapList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of heightmaps.
Definition fios.cpp:548
void FiosGetScenarioList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of scenarios.
Definition fios.cpp:488
void FiosGetTownDataList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
Get a list of town data files.
Definition fios.cpp:585
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.
@ Editor
In the scenario editor.
Definition openttd.h:21
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:261
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:86
std::string Filename()
Generate a savegame name and number according to _settings_client.gui.max_num_autosaves.
Definition fios.cpp:755
FiosNumberedSaveName(const std::string &prefix)
Constructs FiosNumberedSaveName.
Definition fios.cpp:722
std::string Extension()
Generate an extension for a savegame name.
Definition fios.cpp:765
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:612
uint32_t scenid
ID for the scenario (generated by content).
Definition fios.cpp:613
MD5Hash md5sum
MD5 checksum of file.
Definition fios.cpp:614
std::string filename
filename of the file.
Definition fios.cpp:615
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:388
std::string FS2OTTD(std::wstring_view name)
Convert to OpenTTD's encoding from a wide string.
Definition win32.cpp:372