Changeset - r28557:41091a9754aa
[Not reviewed]
master
0 4 0
Patric Stout - 10 months ago 2024-01-23 13:01:25
truebrain@openttd.org
Add: list_[scenario|heightmap] and load_[scenario|height] console commands (#11867)
4 files changed with 134 insertions and 37 deletions:
0 comments (0 inline, 0 general)
src/console_cmds.cpp
Show inline comments
 
@@ -56,9 +56,8 @@ static uint _script_current_depth; ///< 
 
/** File list storage for the console, for caching the last 'ls' command. */
 
class ConsoleFileList : public FileList {
 
public:
 
	ConsoleFileList() : FileList()
 
	ConsoleFileList(AbstractFileType abstract_filetype, bool show_dirs) : FileList(), abstract_filetype(abstract_filetype), show_dirs(show_dirs)
 
	{
 
		this->file_list_valid = false;
 
	}
 

	
 
	/** Declare the file storage cache as being invalid, also clears all stored files. */
 
@@ -75,15 +74,19 @@ public:
 
	void ValidateFileList(bool force_reload = false)
 
	{
 
		if (force_reload || !this->file_list_valid) {
 
			this->BuildFileList(FT_SAVEGAME, SLO_LOAD);
 
			this->BuildFileList(this->abstract_filetype, SLO_LOAD, this->show_dirs);
 
			this->file_list_valid = true;
 
		}
 
	}
 

	
 
	bool file_list_valid; ///< If set, the file list is valid.
 
	AbstractFileType abstract_filetype; ///< The abstract file type to list.
 
	bool show_dirs; ///< Whether to show directories in the file list.
 
	bool file_list_valid = false; ///< If set, the file list is valid.
 
};
 

	
 
static ConsoleFileList _console_file_list; ///< File storage cache for the console.
 
static ConsoleFileList _console_file_list_savegame{FT_SAVEGAME, true}; ///< File storage cache for savegames.
 
static ConsoleFileList _console_file_list_scenario{FT_SCENARIO, false}; ///< File storage cache for scenarios.
 
static ConsoleFileList _console_file_list_heightmap{FT_HEIGHTMAP, false}; ///< File storage cache for heightmaps.
 

	
 
/* console command defines */
 
#define DEF_CONSOLE_CMD(function) static bool function([[maybe_unused]] byte argc, [[maybe_unused]] char *argv[])
 
@@ -424,8 +427,8 @@ DEF_CONSOLE_CMD(ConLoad)
 
	if (argc != 2) return false;
 

	
 
	const char *file = argv[1];
 
	_console_file_list.ValidateFileList();
 
	const FiosItem *item = _console_file_list.FindItem(file);
 
	_console_file_list_savegame.ValidateFileList();
 
	const FiosItem *item = _console_file_list_savegame.FindItem(file);
 
	if (item != nullptr) {
 
		if (GetAbstractFileType(item->type) == FT_SAVEGAME) {
 
			_switch_mode = SM_LOAD_GAME;
 
@@ -440,6 +443,57 @@ DEF_CONSOLE_CMD(ConLoad)
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConLoadScenario)
 
{
 
	if (argc == 0) {
 
		IConsolePrint(CC_HELP, "Load a scenario by name or index. Usage: 'load_scenario <file | number>'.");
 
		return true;
 
	}
 

	
 
	if (argc != 2) return false;
 

	
 
	const char *file = argv[1];
 
	_console_file_list_scenario.ValidateFileList();
 
	const FiosItem *item = _console_file_list_scenario.FindItem(file);
 
	if (item != nullptr) {
 
		if (GetAbstractFileType(item->type) == FT_SCENARIO) {
 
			_switch_mode = SM_LOAD_GAME;
 
			_file_to_saveload.Set(*item);
 
		} else {
 
			IConsolePrint(CC_ERROR, "'{}' is not a scenario.", file);
 
		}
 
	} else {
 
		IConsolePrint(CC_ERROR, "'{}' cannot be found.", file);
 
	}
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConLoadHeightmap)
 
{
 
	if (argc == 0) {
 
		IConsolePrint(CC_HELP, "Load a heightmap by name or index. Usage: 'load_heightmap <file | number>'.");
 
		return true;
 
	}
 

	
 
	if (argc != 2) return false;
 

	
 
	const char *file = argv[1];
 
	_console_file_list_heightmap.ValidateFileList();
 
	const FiosItem *item = _console_file_list_heightmap.FindItem(file);
 
	if (item != nullptr) {
 
		if (GetAbstractFileType(item->type) == FT_HEIGHTMAP) {
 
			_switch_mode = SM_START_HEIGHTMAP;
 
			_file_to_saveload.Set(*item);
 
		} else {
 
			IConsolePrint(CC_ERROR, "'{}' is not a heightmap.", file);
 
		}
 
	} else {
 
		IConsolePrint(CC_ERROR, "'{}' cannot be found.", file);
 
	}
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConRemove)
 
{
 
@@ -451,8 +505,8 @@ DEF_CONSOLE_CMD(ConRemove)
 
	if (argc != 2) return false;
 

	
 
	const char *file = argv[1];
 
	_console_file_list.ValidateFileList();
 
	const FiosItem *item = _console_file_list.FindItem(file);
 
	_console_file_list_savegame.ValidateFileList();
 
	const FiosItem *item = _console_file_list_savegame.FindItem(file);
 
	if (item != nullptr) {
 
		if (unlink(item->name.c_str()) != 0) {
 
			IConsolePrint(CC_ERROR, "Failed to delete '{}'.", item->name);
 
@@ -461,7 +515,7 @@ DEF_CONSOLE_CMD(ConRemove)
 
		IConsolePrint(CC_ERROR, "'{}' could not be found.", file);
 
	}
 

	
 
	_console_file_list.InvalidateFileList();
 
	_console_file_list_savegame.InvalidateFileList();
 
	return true;
 
}
 

	
 
@@ -474,9 +528,41 @@ DEF_CONSOLE_CMD(ConListFiles)
 
		return true;
 
	}
 

	
 
	_console_file_list.ValidateFileList(true);
 
	for (uint i = 0; i < _console_file_list.size(); i++) {
 
		IConsolePrint(CC_DEFAULT, "{}) {}", i, _console_file_list[i].title);
 
	_console_file_list_savegame.ValidateFileList(true);
 
	for (uint i = 0; i < _console_file_list_savegame.size(); i++) {
 
		IConsolePrint(CC_DEFAULT, "{}) {}", i, _console_file_list_savegame[i].title);
 
	}
 

	
 
	return true;
 
}
 

	
 
/* List all the scenarios */
 
DEF_CONSOLE_CMD(ConListScenarios)
 
{
 
	if (argc == 0) {
 
		IConsolePrint(CC_HELP, "List all loadable scenarios. Usage: 'list_scenarios'.");
 
		return true;
 
	}
 

	
 
	_console_file_list_scenario.ValidateFileList(true);
 
	for (uint i = 0; i < _console_file_list_scenario.size(); i++) {
 
		IConsolePrint(CC_DEFAULT, "{}) {}", i, _console_file_list_scenario[i].title);
 
	}
 

	
 
	return true;
 
}
 

	
 
/* List all the heightmaps */
 
DEF_CONSOLE_CMD(ConListHeightmaps)
 
{
 
	if (argc == 0) {
 
		IConsolePrint(CC_HELP, "List all loadable heightmaps. Usage: 'list_heightmaps'.");
 
		return true;
 
	}
 

	
 
	_console_file_list_heightmap.ValidateFileList(true);
 
	for (uint i = 0; i < _console_file_list_heightmap.size(); i++) {
 
		IConsolePrint(CC_DEFAULT, "{}) {}", i, _console_file_list_heightmap[i].title);
 
	}
 

	
 
	return true;
 
@@ -493,8 +579,8 @@ DEF_CONSOLE_CMD(ConChangeDirectory)
 
	if (argc != 2) return false;
 

	
 
	const char *file = argv[1];
 
	_console_file_list.ValidateFileList(true);
 
	const FiosItem *item = _console_file_list.FindItem(file);
 
	_console_file_list_savegame.ValidateFileList(true);
 
	const FiosItem *item = _console_file_list_savegame.FindItem(file);
 
	if (item != nullptr) {
 
		switch (item->type) {
 
			case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT:
 
@@ -506,7 +592,7 @@ DEF_CONSOLE_CMD(ConChangeDirectory)
 
		IConsolePrint(CC_ERROR, "{}: No such file or directory.", file);
 
	}
 

	
 
	_console_file_list.InvalidateFileList();
 
	_console_file_list_savegame.InvalidateFileList();
 
	return true;
 
}
 

	
 
@@ -518,8 +604,8 @@ DEF_CONSOLE_CMD(ConPrintWorkingDirectory
 
	}
 

	
 
	/* XXX - Workaround for broken file handling */
 
	_console_file_list.ValidateFileList(true);
 
	_console_file_list.InvalidateFileList();
 
	_console_file_list_savegame.ValidateFileList(true);
 
	_console_file_list_savegame.InvalidateFileList();
 

	
 
	IConsolePrint(CC_DEFAULT, FiosGetCurrentPath());
 
	return true;
 
@@ -2531,10 +2617,16 @@ void IConsoleStdLibRegister()
 
	IConsole::CmdRegister("scrollto",                ConScrollToTile);
 
	IConsole::CmdRegister("alias",                   ConAlias);
 
	IConsole::CmdRegister("load",                    ConLoad);
 
	IConsole::CmdRegister("load_save",               ConLoad);
 
	IConsole::CmdRegister("load_scenario",           ConLoadScenario);
 
	IConsole::CmdRegister("load_heightmap",          ConLoadHeightmap);
 
	IConsole::CmdRegister("rm",                      ConRemove);
 
	IConsole::CmdRegister("save",                    ConSave);
 
	IConsole::CmdRegister("saveconfig",              ConSaveConfig);
 
	IConsole::CmdRegister("ls",                      ConListFiles);
 
	IConsole::CmdRegister("list_saves",              ConListFiles);
 
	IConsole::CmdRegister("list_scenarios",          ConListScenarios);
 
	IConsole::CmdRegister("list_heightmaps",         ConListHeightmaps);
 
	IConsole::CmdRegister("cd",                      ConChangeDirectory);
 
	IConsole::CmdRegister("pwd",                     ConPrintWorkingDirectory);
 
	IConsole::CmdRegister("clear",                   ConClearBuffer);
src/fios.cpp
Show inline comments
 
@@ -65,8 +65,9 @@ bool FiosItem::operator< (const FiosItem
 
 * Construct a file list with the given kind of files, for the stated purpose.
 
 * @param abstract_filetype Kind of files to collect.
 
 * @param fop Purpose of the collection, either #SLO_LOAD or #SLO_SAVE.
 
 * @param show_dirs Whether to show directories.
 
 */
 
void FileList::BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop)
 
void FileList::BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop, bool show_dirs)
 
{
 
	this->clear();
 

	
 
@@ -76,15 +77,15 @@ void FileList::BuildFileList(AbstractFil
 
			break;
 

	
 
		case FT_SAVEGAME:
 
			FiosGetSavegameList(fop, *this);
 
			FiosGetSavegameList(fop, show_dirs, *this);
 
			break;
 

	
 
		case FT_SCENARIO:
 
			FiosGetScenarioList(fop, *this);
 
			FiosGetScenarioList(fop, show_dirs, *this);
 
			break;
 

	
 
		case FT_HEIGHTMAP:
 
			FiosGetHeightmapList(fop, *this);
 
			FiosGetHeightmapList(fop, show_dirs, *this);
 
			break;
 

	
 
		default:
 
@@ -337,11 +338,12 @@ bool FiosFileScanner::AddFile(const std:
 
/**
 
 * Fill the list of the files in a directory, according to some arbitrary rule.
 
 * @param fop Purpose of collecting the list.
 
 * @param show_dirs Whether to list directories.
 
 * @param callback_proc The function that is called where you need to do the filtering.
 
 * @param subdir The directory from where to start (global) searching.
 
 * @param file_list Destination of the found files.
 
 */
 
static void FiosGetFileList(SaveLoadOperation fop, FiosGetTypeAndNameProc *callback_proc, Subdirectory subdir, FileList &file_list)
 
static void FiosGetFileList(SaveLoadOperation fop, bool show_dirs, FiosGetTypeAndNameProc *callback_proc, Subdirectory subdir, FileList &file_list)
 
{
 
	struct stat sb;
 
	struct dirent *dirent;
 
@@ -354,7 +356,7 @@ static void FiosGetFileList(SaveLoadOper
 
	assert(_fios_path != nullptr);
 

	
 
	/* A parent directory link exists if we are not in the root directory */
 
	if (!FiosIsRoot(*_fios_path)) {
 
	if (show_dirs && !FiosIsRoot(*_fios_path)) {
 
		fios = &file_list.emplace_back();
 
		fios->type = FIOS_TYPE_PARENT;
 
		fios->mtime = 0;
 
@@ -364,7 +366,7 @@ static void FiosGetFileList(SaveLoadOper
 
	}
 

	
 
	/* Show subdirectories */
 
	if ((dir = ttd_opendir(_fios_path->c_str())) != nullptr) {
 
	if (show_dirs && (dir = ttd_opendir(_fios_path->c_str())) != nullptr) {
 
		while ((dirent = readdir(dir)) != nullptr) {
 
			std::string d_name = FS2OTTD(dirent->d_name);
 

	
 
@@ -384,7 +386,7 @@ static void FiosGetFileList(SaveLoadOper
 
	}
 

	
 
	/* Sort the subdirs always by name, ascending, remember user-sorting order */
 
	{
 
	if (show_dirs) {
 
		SortingBits order = _savegame_sort_order;
 
		_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
 
		std::sort(file_list.begin(), file_list.end());
 
@@ -464,10 +466,11 @@ std::tuple<FiosType, std::string> FiosGe
 
/**
 
 * Get a list of savegames.
 
 * @param fop Purpose of collecting the list.
 
 * @param show_dirs Whether to show directories.
 
 * @param file_list Destination of the found files.
 
 * @see FiosGetFileList
 
 */
 
void FiosGetSavegameList(SaveLoadOperation fop, FileList &file_list)
 
void FiosGetSavegameList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
 
{
 
	static std::optional<std::string> fios_save_path;
 

	
 
@@ -475,7 +478,7 @@ void FiosGetSavegameList(SaveLoadOperati
 

	
 
	_fios_path = &(*fios_save_path);
 

	
 
	FiosGetFileList(fop, &FiosGetSavegameListCallback, NO_DIRECTORY, file_list);
 
	FiosGetFileList(fop, show_dirs, &FiosGetSavegameListCallback, NO_DIRECTORY, file_list);
 
}
 

	
 
/**
 
@@ -510,10 +513,11 @@ std::tuple<FiosType, std::string> FiosGe
 
/**
 
 * Get a list of scenarios.
 
 * @param fop Purpose of collecting the list.
 
 * @param show_dirs Whether to show directories.
 
 * @param file_list Destination of the found files.
 
 * @see FiosGetFileList
 
 */
 
void FiosGetScenarioList(SaveLoadOperation fop, FileList &file_list)
 
void FiosGetScenarioList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
 
{
 
	static std::optional<std::string> fios_scn_path;
 

	
 
@@ -524,7 +528,7 @@ void FiosGetScenarioList(SaveLoadOperati
 

	
 
	std::string base_path = FioFindDirectory(SCENARIO_DIR);
 
	Subdirectory subdir = (fop == SLO_LOAD && base_path == *_fios_path) ? SCENARIO_DIR : NO_DIRECTORY;
 
	FiosGetFileList(fop, &FiosGetScenarioListCallback, subdir, file_list);
 
	FiosGetFileList(fop, show_dirs, &FiosGetScenarioListCallback, subdir, file_list);
 
}
 

	
 
std::tuple<FiosType, std::string> FiosGetHeightmapListCallback(SaveLoadOperation, const std::string &file, const std::string_view ext)
 
@@ -570,9 +574,10 @@ std::tuple<FiosType, std::string> FiosGe
 
/**
 
 * Get a list of heightmaps.
 
 * @param fop Purpose of collecting the list.
 
 * @param show_dirs Whether to show directories.
 
 * @param file_list Destination of the found files.
 
 */
 
void FiosGetHeightmapList(SaveLoadOperation fop, FileList &file_list)
 
void FiosGetHeightmapList(SaveLoadOperation fop, bool show_dirs, FileList &file_list)
 
{
 
	static std::optional<std::string> fios_hmap_path;
 

	
 
@@ -582,7 +587,7 @@ void FiosGetHeightmapList(SaveLoadOperat
 

	
 
	std::string base_path = FioFindDirectory(HEIGHTMAP_DIR);
 
	Subdirectory subdir = base_path == *_fios_path ? HEIGHTMAP_DIR : NO_DIRECTORY;
 
	FiosGetFileList(fop, &FiosGetHeightmapListCallback, subdir, file_list);
 
	FiosGetFileList(fop, show_dirs, &FiosGetHeightmapListCallback, subdir, file_list);
 
}
 

	
 
/**
src/fios.h
Show inline comments
 
@@ -87,7 +87,7 @@ struct FiosItem {
 
/** List of file information. */
 
class FileList : public std::vector<FiosItem> {
 
public:
 
	void BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop);
 
	void BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop, bool show_dirs);
 
	const FiosItem *FindItem(const std::string_view file);
 
};
 

	
 
@@ -104,9 +104,9 @@ extern SortingBits _savegame_sort_order;
 

	
 
void ShowSaveLoadDialog(AbstractFileType abstract_filetype, SaveLoadOperation fop);
 

	
 
void FiosGetSavegameList(SaveLoadOperation fop, FileList &file_list);
 
void FiosGetScenarioList(SaveLoadOperation fop, FileList &file_list);
 
void FiosGetHeightmapList(SaveLoadOperation fop, FileList &file_list);
 
void FiosGetSavegameList(SaveLoadOperation fop, bool show_dirs, FileList &file_list);
 
void FiosGetScenarioList(SaveLoadOperation fop, bool show_dirs, FileList &file_list);
 
void FiosGetHeightmapList(SaveLoadOperation fop, bool show_dirs, FileList &file_list);
 

	
 
bool FiosBrowseTo(const FiosItem *item);
 

	
src/fios_gui.cpp
Show inline comments
 
@@ -829,7 +829,7 @@ public:
 
				if (!gui_scope) break;
 

	
 
				_fios_path_changed = true;
 
				this->fios_items.BuildFileList(this->abstract_filetype, this->fop);
 
				this->fios_items.BuildFileList(this->abstract_filetype, this->fop, true);
 
				this->selected = nullptr;
 
				_load_check_data.Clear();
 

	
0 comments (0 inline, 0 general)