File diff r25665:904100ec67ac → r25666:da59d4ce1d64
src/console_cmds.cpp
Show inline comments
 
@@ -188,13 +188,13 @@ DEF_CONSOLE_HOOK(ConHookNewGRFDeveloperT
 
/**
 
 * Show help for the console.
 
 * @param str String to print in the console.
 
 */
 
static void IConsoleHelp(const char *str)
 
{
 
	IConsolePrintF(CC_HELP, "- {}", str);
 
	IConsolePrint(CC_HELP, "- {}", str);
 
}
 

	
 
/**
 
 * Reset status of all engines.
 
 * @return Will always succeed.
 
 */
 
@@ -322,15 +322,15 @@ DEF_CONSOLE_CMD(ConSave)
 

	
 
	if (argc == 2) {
 
		char *filename = str_fmt("%s.sav", argv[1]);
 
		IConsolePrint(CC_DEFAULT, "Saving map...");
 

	
 
		if (SaveOrLoad(filename, SLO_SAVE, DFT_GAME_FILE, SAVE_DIR) != SL_OK) {
 
			IConsolePrint(CC_ERROR, "Saving map failed");
 
			IConsolePrint(CC_ERROR, "Saving map failed.");
 
		} else {
 
			IConsolePrintF(CC_DEFAULT, "Map successfully saved to %s", filename);
 
			IConsolePrint(CC_INFO, "Map successfully saved to '{}'.", filename);
 
		}
 
		free(filename);
 
		return true;
 
	}
 

	
 
	return false;
 
@@ -414,13 +414,13 @@ DEF_CONSOLE_CMD(ConListFiles)
 
		IConsoleHelp("List all loadable savegames and directories in the current dir via console. Usage: 'ls | dir'");
 
		return true;
 
	}
 

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

	
 
	return true;
 
}
 

	
 
/* Change the dir via console */
 
@@ -520,13 +520,13 @@ static bool ConKickOrBan(const char *arg
 
		n = NetworkServerKickOrBanIP(argv, ban, reason);
 
	}
 

	
 
	if (n == 0) {
 
		IConsolePrint(CC_DEFAULT, ban ? "Client not online, address added to banlist." : "Client not found.");
 
	} else {
 
		IConsolePrintF(CC_DEFAULT, "%sed %u client(s).", ban ? "Bann" : "Kick", n);
 
		IConsolePrint(CC_DEFAULT, "{}ed {} client(s).", ban ? "Bann" : "Kick", n);
 
	}
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConKick)
 
@@ -595,15 +595,13 @@ DEF_CONSOLE_CMD(ConUnBan)
 
	/* Try by index. */
 
	if (index >= _network_ban_list.size()) {
 
		index = atoi(argv[1]) - 1U; // let it wrap
 
	}
 

	
 
	if (index < _network_ban_list.size()) {
 
		char msg[64];
 
		seprintf(msg, lastof(msg), "Unbanned %s", _network_ban_list[index].c_str());
 
		IConsolePrint(CC_DEFAULT, msg);
 
		IConsolePrint(CC_DEFAULT, "Unbanned {}.", _network_ban_list[index]);
 
		_network_ban_list.erase(_network_ban_list.begin() + index);
 
	} else {
 
		IConsolePrint(CC_DEFAULT, "Invalid list index or IP not in ban-list.");
 
		IConsolePrint(CC_DEFAULT, "For a list of banned IP's, see the command 'banlist'");
 
	}
 

	
 
@@ -618,13 +616,13 @@ DEF_CONSOLE_CMD(ConBanList)
 
	}
 

	
 
	IConsolePrint(CC_DEFAULT, "Banlist: ");
 

	
 
	uint i = 1;
 
	for (const auto &entry : _network_ban_list) {
 
		IConsolePrintF(CC_DEFAULT, "  %d) %s", i, entry.c_str());
 
		IConsolePrint(CC_DEFAULT, "  {}) {}", i, entry);
 
		i++;
 
	}
 

	
 
	return true;
 
}
 

	
 
@@ -710,15 +708,15 @@ DEF_CONSOLE_CMD(ConServerInfo)
 
	if (argc == 0) {
 
		IConsoleHelp("List current and maximum client/company limits. Usage 'server_info'");
 
		IConsoleHelp("You can change these values by modifying settings 'network.max_clients', 'network.max_companies' and 'network.max_spectators'");
 
		return true;
 
	}
 

	
 
	IConsolePrintF(CC_DEFAULT, "Current/maximum clients:    %2d/%2d", _network_game_info.clients_on, _settings_client.network.max_clients);
 
	IConsolePrintF(CC_DEFAULT, "Current/maximum companies:  %2d/%2d", (int)Company::GetNumItems(), _settings_client.network.max_companies);
 
	IConsolePrintF(CC_DEFAULT, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), _settings_client.network.max_spectators);
 
	IConsolePrint(CC_DEFAULT, "Current/maximum clients:    {:3d}/{:3d}", _network_game_info.clients_on, _settings_client.network.max_clients);
 
	IConsolePrint(CC_DEFAULT, "Current/maximum companies:  {:3d}/{:3d}", Company::GetNumItems(), _settings_client.network.max_companies);
 
	IConsolePrint(CC_DEFAULT, "Current/maximum spectators: {:3d}/{:3d}", NetworkSpectatorCount(), _settings_client.network.max_spectators);
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConClientNickChange)
 
{
 
@@ -919,13 +917,13 @@ DEF_CONSOLE_CMD(ConNetworkReconnect)
 
	if (_settings_client.network.last_joined.empty()) {
 
		IConsolePrint(CC_DEFAULT, "No server for reconnecting.");
 
		return true;
 
	}
 

	
 
	/* Don't resolve the address first, just print it directly as it comes from the config file. */
 
	IConsolePrintF(CC_DEFAULT, "Reconnecting to %s ...", _settings_client.network.last_joined.c_str());
 
	IConsolePrint(CC_DEFAULT, "Reconnecting to {} ...", _settings_client.network.last_joined);
 

	
 
	return NetworkClientConnectGame(_settings_client.network.last_joined, playas);
 
}
 

	
 
DEF_CONSOLE_CMD(ConNetworkConnect)
 
{
 
@@ -1022,15 +1020,18 @@ DEF_CONSOLE_CMD(ConScript)
 
		return true;
 
	}
 

	
 
	if (!CloseConsoleLogIfActive()) {
 
		if (argc < 2) return false;
 

	
 
		IConsolePrintF(CC_DEFAULT, "file output started to: %s", argv[1]);
 
		_iconsole_output_file = fopen(argv[1], "ab");
 
		if (_iconsole_output_file == nullptr) IConsolePrint(CC_ERROR, "Could not open file '{}'.", argv[1]);
 
		if (_iconsole_output_file == nullptr) {
 
			IConsolePrint(CC_ERROR, "Could not open console log file '{}'.", argv[1]);
 
		} else {
 
			IConsolePrint(CC_INFO, "Console log output started to: '{}'", argv[1]);
 
		}
 
	}
 

	
 
	return true;
 
}
 

	
 

	
 
@@ -1114,13 +1115,13 @@ static void PrintLineByLine(char *buf)
 
{
 
	char *p = buf;
 
	/* Print output line by line */
 
	for (char *p2 = buf; *p2 != '\0'; p2++) {
 
		if (*p2 == '\n') {
 
			*p2 = '\0';
 
			IConsolePrintF(CC_DEFAULT, "%s", p);
 
			IConsolePrint(CC_DEFAULT, p);
 
			p = p2 + 1;
 
		}
 
	}
 
}
 

	
 
DEF_CONSOLE_CMD(ConListAILibs)
 
@@ -1254,13 +1255,13 @@ DEF_CONSOLE_CMD(ConReloadAI)
 
		IConsolePrint(CC_ERROR, "Only the server can reload an AI.");
 
		return true;
 
	}
 

	
 
	CompanyID company_id = (CompanyID)(atoi(argv[1]) - 1);
 
	if (!Company::IsValidID(company_id)) {
 
		IConsolePrintF(CC_DEFAULT, "Unknown company. Company range is between 1 and %d.", MAX_COMPANIES);
 
		IConsolePrint(CC_ERROR, "Unknown company. Company range is between 1 and {}.", MAX_COMPANIES);
 
		return true;
 
	}
 

	
 
	/* In singleplayer mode the player can be in an AI company, after cheating or loading network save with an AI in first slot. */
 
	if (Company::IsHumanID(company_id) || company_id == _local_company) {
 
		IConsolePrint(CC_ERROR, "Company is not controlled by an AI.");
 
@@ -1292,13 +1293,13 @@ DEF_CONSOLE_CMD(ConStopAI)
 
		IConsolePrint(CC_ERROR, "Only the server can stop an AI.");
 
		return true;
 
	}
 

	
 
	CompanyID company_id = (CompanyID)(atoi(argv[1]) - 1);
 
	if (!Company::IsValidID(company_id)) {
 
		IConsolePrintF(CC_DEFAULT, "Unknown company. Company range is between 1 and %d.", MAX_COMPANIES);
 
		IConsolePrint(CC_ERROR, "Unknown company. Company range is between 1 and {}.", MAX_COMPANIES);
 
		return true;
 
	}
 

	
 
	/* In singleplayer mode the player can be in an AI company, after cheating or loading network save with an AI in first slot. */
 
	if (Company::IsHumanID(company_id) || company_id == _local_company) {
 
		IConsolePrint(CC_ERROR, "Company is not controlled by an AI.");
 
@@ -1365,39 +1366,39 @@ DEF_CONSOLE_CMD(ConGetSeed)
 
	if (argc == 0) {
 
		IConsoleHelp("Returns the seed used to create this game. Usage: 'getseed'");
 
		IConsoleHelp("The seed can be used to reproduce the exact same map as the game started with.");
 
		return true;
 
	}
 

	
 
	IConsolePrintF(CC_DEFAULT, "Generation Seed: %u", _settings_game.game_creation.generation_seed);
 
	IConsolePrint(CC_DEFAULT, "Generation Seed: {}", _settings_game.game_creation.generation_seed);
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConGetDate)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Returns the current date (year-month-day) of the game. Usage: 'getdate'");
 
		return true;
 
	}
 

	
 
	YearMonthDay ymd;
 
	ConvertDateToYMD(_date, &ymd);
 
	IConsolePrintF(CC_DEFAULT, "Date: %04d-%02d-%02d", ymd.year, ymd.month + 1, ymd.day);
 
	IConsolePrint(CC_DEFAULT, "Date: {:04d}-{:02d}-{:02d}", ymd.year, ymd.month + 1, ymd.day);
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConGetSysDate)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Returns the current date (year-month-day) of your system. Usage: 'getsysdate'");
 
		return true;
 
	}
 

	
 
	char buffer[lengthof("2000-01-02 03:04:05")];
 
	LocalTime::Format(buffer, lastof(buffer), "%Y-%m-%d %H:%M:%S");
 
	IConsolePrintF(CC_DEFAULT, "System Date: %s", buffer);
 
	IConsolePrint(CC_DEFAULT, "System Date: {}", buffer);
 
	return true;
 
}
 

	
 

	
 
DEF_CONSOLE_CMD(ConAlias)
 
{
 
@@ -1529,13 +1530,13 @@ DEF_CONSOLE_CMD(ConDebugLevel)
 
		return true;
 
	}
 

	
 
	if (argc > 2) return false;
 

	
 
	if (argc == 1) {
 
		IConsolePrintF(CC_DEFAULT, "Current debug-level: '%s'", GetDebugString());
 
		IConsolePrint(CC_DEFAULT, "Current debug-level: '{}'", GetDebugString());
 
	} else {
 
		SetDebugString(argv[1]);
 
	}
 

	
 
	return true;
 
}
 
@@ -1582,13 +1583,13 @@ DEF_CONSOLE_CMD(ConHelp)
 
		if (alias != nullptr) {
 
			cmd = IConsole::CmdGet(alias->cmdline);
 
			if (cmd != nullptr) {
 
				cmd->proc(0, nullptr);
 
				return true;
 
			}
 
			IConsolePrintF(CC_ERROR, "ERROR: alias is of special type, please see its execution-line: '%s'", alias->cmdline.c_str());
 
			IConsolePrint(CC_ERROR, "Alias is of special type, please see its execution-line: '{}'.", alias->cmdline);
 
			return true;
 
		}
 

	
 
		IConsolePrint(CC_ERROR, "Command not found");
 
		return true;
 
	}
 
@@ -1612,13 +1613,13 @@ DEF_CONSOLE_CMD(ConListCommands)
 
		return true;
 
	}
 

	
 
	for (auto &it : IConsole::Commands()) {
 
		const IConsoleCmd *cmd = &it.second;
 
		if (argv[1] == nullptr || cmd->name.find(argv[1]) != std::string::npos) {
 
			if (cmd->hook == nullptr || cmd->hook(false) != CHR_HIDE) IConsolePrintF(CC_DEFAULT, "%s", cmd->name.c_str());
 
			if (cmd->hook == nullptr || cmd->hook(false) != CHR_HIDE) IConsolePrint(CC_DEFAULT, cmd->name);
 
		}
 
	}
 

	
 
	return true;
 
}
 

	
 
@@ -1629,13 +1630,13 @@ DEF_CONSOLE_CMD(ConListAliases)
 
		return true;
 
	}
 

	
 
	for (auto &it : IConsole::Aliases()) {
 
		const IConsoleAlias *alias = &it.second;
 
		if (argv[1] == nullptr || alias->name.find(argv[1]) != std::string::npos) {
 
			IConsolePrintF(CC_DEFAULT, "%s => %s", alias->name.c_str(), alias->cmdline.c_str());
 
			IConsolePrint(CC_DEFAULT, "{} => {}", alias->name, alias->cmdline);
 
		}
 
	}
 

	
 
	return true;
 
}
 

	
 
@@ -1658,13 +1659,13 @@ DEF_CONSOLE_CMD(ConCompanies)
 
		} else if (_network_server) {
 
			password_state = _network_company_states[c->index].password.empty() ? "unprotected" : "protected";
 
		}
 

	
 
		char colour[512];
 
		GetString(colour, STR_COLOUR_DARK_BLUE + _company_colours[c->index], lastof(colour));
 
		IConsolePrintF(CC_INFO, "#:%d(%s) Company Name: '%s'  Year Founded: %d  Money: " OTTD_PRINTF64 "  Loan: " OTTD_PRINTF64 "  Value: " OTTD_PRINTF64 "  (T:%d, R:%d, P:%d, S:%d) %s",
 
		IConsolePrint(CC_INFO, "#:{}({}) Company Name: '{}'  Year Founded: {}  Money: {}  Loan: {}  Value: {}  (T:{}, R:{}, P:{}, S:{}) {}",
 
			c->index + 1, colour, company_name,
 
			c->inaugurated_year, (int64)c->money, (int64)c->current_loan, (int64)CalculateCompanyValue(c),
 
			c->group_all[VEH_TRAIN].num_vehicle,
 
			c->group_all[VEH_ROAD].num_vehicle,
 
			c->group_all[VEH_AIRCRAFT].num_vehicle,
 
			c->group_all[VEH_SHIP].num_vehicle,
 
@@ -1702,13 +1703,13 @@ DEF_CONSOLE_CMD(ConSayCompany)
 
	}
 

	
 
	if (argc != 3) return false;
 

	
 
	CompanyID company_id = (CompanyID)(atoi(argv[1]) - 1);
 
	if (!Company::IsValidID(company_id)) {
 
		IConsolePrintF(CC_DEFAULT, "Unknown company. Company range is between 1 and %d.", MAX_COMPANIES);
 
		IConsolePrint(CC_DEFAULT, "Unknown company. Company range is between 1 and {}.", MAX_COMPANIES);
 
		return true;
 
	}
 

	
 
	if (!_network_server) {
 
		NetworkClientSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, company_id, argv[2]);
 
	} else {
 
@@ -1739,24 +1740,21 @@ DEF_CONSOLE_CMD(ConSayClient)
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConCompanyPassword)
 
{
 
	if (argc == 0) {
 
		const char *helpmsg;
 

	
 
		if (_network_dedicated) {
 
			helpmsg = "Change the password of a company. Usage: 'company_pw <company-no> \"<password>\"";
 
			IConsolePrint(CC_HELP, "Change the password of a company. Usage: 'company_pw <company-no> \"<password>\".");
 
		} else if (_network_server) {
 
			helpmsg = "Change the password of your or any other company. Usage: 'company_pw [<company-no>] \"<password>\"'";
 
			IConsolePrint(CC_HELP, "Change the password of your or any other company. Usage: 'company_pw [<company-no>] \"<password>\"'.");
 
		} else {
 
			helpmsg = "Change the password of your company. Usage: 'company_pw \"<password>\"'";
 
			IConsolePrint(CC_HELP, "Change the password of your company. Usage: 'company_pw \"<password>\"'.");
 
		}
 

	
 
		IConsoleHelp(helpmsg);
 
		IConsoleHelp("Use \"*\" to disable the password.");
 
		IConsolePrint(CC_HELP, "Use \"*\" to disable the password.");
 
		return true;
 
	}
 

	
 
	CompanyID company_id;
 
	std::string password;
 
	const char *errormsg;
 
@@ -1804,23 +1802,23 @@ static ContentType StringToContentType(c
 
}
 

	
 
/** Asynchronous callback */
 
struct ConsoleContentCallback : public ContentCallback {
 
	void OnConnect(bool success)
 
	{
 
		IConsolePrintF(CC_DEFAULT, "Content server connection %s", success ? "established" : "failed");
 
		IConsolePrint(CC_DEFAULT, "Content server connection {}.", success ? "established" : "failed");
 
	}
 

	
 
	void OnDisconnect()
 
	{
 
		IConsolePrintF(CC_DEFAULT, "Content server connection closed");
 
		IConsolePrint(CC_DEFAULT, "Content server connection closed.");
 
	}
 

	
 
	void OnDownloadComplete(ContentID cid)
 
	{
 
		IConsolePrintF(CC_DEFAULT, "Completed download of %d", cid);
 
		IConsolePrint(CC_DEFAULT, "Completed download of {}.", cid);
 
	}
 
};
 

	
 
/**
 
 * Outputs content state information to console
 
 * @param ci the content info
 
@@ -1831,13 +1829,13 @@ static void OutputContentState(const Con
 
	static_assert(lengthof(types) == CONTENT_TYPE_END - CONTENT_TYPE_BEGIN);
 
	static const char * const states[] = { "Not selected", "Selected", "Dep Selected", "Installed", "Unknown" };
 
	static const TextColour state_to_colour[] = { CC_COMMAND, CC_INFO, CC_INFO, CC_WHITE, CC_ERROR };
 

	
 
	char buf[sizeof(ci->md5sum) * 2 + 1];
 
	md5sumToString(buf, lastof(buf), ci->md5sum);
 
	IConsolePrintF(state_to_colour[ci->state], "%d, %s, %s, %s, %08X, %s", ci->id, types[ci->type - 1], states[ci->state], ci->name.c_str(), ci->unique_id, buf);
 
	IConsolePrint(state_to_colour[ci->state], "{}, {}, {}, {}, {:08X}, {}", ci->id, types[ci->type - 1], states[ci->state], ci->name, ci->unique_id, buf);
 
}
 

	
 
DEF_CONSOLE_CMD(ConContent)
 
{
 
	static ContentCallback *cb = nullptr;
 
	if (cb == nullptr) {
 
@@ -1866,13 +1864,13 @@ DEF_CONSOLE_CMD(ConContent)
 
		return true;
 
	}
 

	
 
	if (strcasecmp(argv[1], "select") == 0) {
 
		if (argc <= 2) {
 
			/* List selected content */
 
			IConsolePrintF(CC_WHITE, "id, type, state, name");
 
			IConsolePrint(CC_WHITE, "id, type, state, name");
 
			for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) {
 
				if ((*iter)->state != ContentInfo::SELECTED && (*iter)->state != ContentInfo::AUTOSELECTED) continue;
 
				OutputContentState(*iter);
 
			}
 
		} else if (strcasecmp(argv[2], "all") == 0) {
 
			/* The intention of this function was that you could download
 
@@ -1899,25 +1897,25 @@ DEF_CONSOLE_CMD(ConContent)
 
			_network_content_client.Unselect((ContentID)atoi(argv[2]));
 
		}
 
		return true;
 
	}
 

	
 
	if (strcasecmp(argv[1], "state") == 0) {
 
		IConsolePrintF(CC_WHITE, "id, type, state, name");
 
		IConsolePrint(CC_WHITE, "id, type, state, name");
 
		for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) {
 
			if (argc > 2 && strcasestr((*iter)->name.c_str(), argv[2]) == nullptr) continue;
 
			OutputContentState(*iter);
 
		}
 
		return true;
 
	}
 

	
 
	if (strcasecmp(argv[1], "download") == 0) {
 
		uint files;
 
		uint bytes;
 
		_network_content_client.DownloadSelectedContent(files, bytes);
 
		IConsolePrintF(CC_DEFAULT, "Downloading %d file(s) (%d bytes)", files, bytes);
 
		IConsolePrint(CC_DEFAULT, "Downloading {} file(s) ({} bytes).", files, bytes);
 
		return true;
 
	}
 

	
 
	return false;
 
}
 
#endif /* defined(WITH_ZLIB) */
 
@@ -2019,13 +2017,13 @@ DEF_CONSOLE_CMD(ConNewGRFProfile)
 
		for (GRFFile *grf : files) {
 
			auto profiler = std::find_if(_newgrf_profilers.begin(), _newgrf_profilers.end(), [&](NewGRFProfiler &pr) { return pr.grffile == grf; });
 
			bool selected = profiler != _newgrf_profilers.end();
 
			bool active = selected && profiler->active;
 
			TextColour tc = active ? TC_LIGHT_BLUE : selected ? TC_GREEN : CC_INFO;
 
			const char *statustext = active ? " (active)" : selected ? " (selected)" : "";
 
			IConsolePrintF(tc, "%d: [%08X] %s%s", i, BSWAP32(grf->grfid), grf->filename, statustext);
 
			IConsolePrint(tc, "{}: [{:08X}] {}{}", i, BSWAP32(grf->grfid), grf->filename, statustext);
 
			i++;
 
		}
 
		return true;
 
	}
 

	
 
	/* "select" sub-command */
 
@@ -2078,21 +2076,21 @@ DEF_CONSOLE_CMD(ConNewGRFProfile)
 
				char grfidstr[12]{ 0 };
 
				seprintf(grfidstr, lastof(grfidstr), "[%08X]", BSWAP32(pr.grffile->grfid));
 
				grfids += grfidstr;
 
			}
 
		}
 
		if (started > 0) {
 
			IConsolePrintF(CC_DEBUG, "Started profiling for GRFID%s %s", (started > 1) ? "s" : "", grfids.c_str());
 
			IConsolePrint(CC_DEBUG, "Started profiling for GRFID{} {}", (started > 1) ? "s" : "", grfids);
 
			if (argc >= 3) {
 
				int days = std::max(atoi(argv[2]), 1);
 
				_newgrf_profile_end_date = _date + days;
 

	
 
				char datestrbuf[32]{ 0 };
 
				SetDParam(0, _newgrf_profile_end_date);
 
				GetString(datestrbuf, STR_JUST_DATE_ISO, lastof(datestrbuf));
 
				IConsolePrintF(CC_DEBUG, "Profiling will automatically stop on game date %s", datestrbuf);
 
				IConsolePrint(CC_DEBUG, "Profiling will automatically stop on game date {}.", datestrbuf);
 
			} else {
 
				_newgrf_profile_end_date = MAX_DAY;
 
			}
 
		} else if (_newgrf_profilers.empty()) {
 
			IConsolePrint(CC_ERROR, "No GRFs selected for profiling, did not start.");
 
		} else {
 
@@ -2162,30 +2160,30 @@ DEF_CONSOLE_CMD(ConFramerateWindow)
 
	ShowFramerateWindow();
 
	return true;
 
}
 

	
 
static void ConDumpRoadTypes()
 
{
 
	IConsolePrintF(CC_DEFAULT, "  Flags:");
 
	IConsolePrintF(CC_DEFAULT, "    c = catenary");
 
	IConsolePrintF(CC_DEFAULT, "    l = no level crossings");
 
	IConsolePrintF(CC_DEFAULT, "    X = no houses");
 
	IConsolePrintF(CC_DEFAULT, "    h = hidden");
 
	IConsolePrintF(CC_DEFAULT, "    T = buildable by towns");
 
	IConsolePrint(CC_DEFAULT, "  Flags:");
 
	IConsolePrint(CC_DEFAULT, "    c = catenary");
 
	IConsolePrint(CC_DEFAULT, "    l = no level crossings");
 
	IConsolePrint(CC_DEFAULT, "    X = no houses");
 
	IConsolePrint(CC_DEFAULT, "    h = hidden");
 
	IConsolePrint(CC_DEFAULT, "    T = buildable by towns");
 

	
 
	std::map<uint32, const GRFFile *> grfs;
 
	for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
 
		const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
 
		if (rti->label == 0) continue;
 
		uint32 grfid = 0;
 
		const GRFFile *grf = rti->grffile[ROTSG_GROUND];
 
		if (grf != nullptr) {
 
			grfid = grf->grfid;
 
			grfs.emplace(grfid, grf);
 
		}
 
		IConsolePrintF(CC_DEFAULT, "  %02u %s %c%c%c%c, Flags: %c%c%c%c%c, GRF: %08X, %s",
 
		IConsolePrint(CC_DEFAULT, "  {:02d} {} {:c}{:c}{:c}{:c}, Flags: {}{}{}{}{}, GRF: {:08X}, {}",
 
				(uint)rt,
 
				RoadTypeIsTram(rt) ? "Tram" : "Road",
 
				rti->label >> 24, rti->label >> 16, rti->label >> 8, rti->label,
 
				HasBit(rti->flags, ROTF_CATENARY)          ? 'c' : '-',
 
				HasBit(rti->flags, ROTF_NO_LEVEL_CROSSING) ? 'l' : '-',
 
				HasBit(rti->flags, ROTF_NO_HOUSES)         ? 'X' : '-',
 
@@ -2193,37 +2191,37 @@ static void ConDumpRoadTypes()
 
				HasBit(rti->flags, ROTF_TOWN_BUILD)        ? 'T' : '-',
 
				BSWAP32(grfid),
 
				GetStringPtr(rti->strings.name)
 
		);
 
	}
 
	for (const auto &grf : grfs) {
 
		IConsolePrintF(CC_DEFAULT, "  GRF: %08X = %s", BSWAP32(grf.first), grf.second->filename);
 
		IConsolePrint(CC_DEFAULT, "  GRF: {:08X} = {}", BSWAP32(grf.first), grf.second->filename);
 
	}
 
}
 

	
 
static void ConDumpRailTypes()
 
{
 
	IConsolePrintF(CC_DEFAULT, "  Flags:");
 
	IConsolePrintF(CC_DEFAULT, "    c = catenary");
 
	IConsolePrintF(CC_DEFAULT, "    l = no level crossings");
 
	IConsolePrintF(CC_DEFAULT, "    h = hidden");
 
	IConsolePrintF(CC_DEFAULT, "    s = no sprite combine");
 
	IConsolePrintF(CC_DEFAULT, "    a = always allow 90 degree turns");
 
	IConsolePrintF(CC_DEFAULT, "    d = always disallow 90 degree turns");
 
	IConsolePrint(CC_DEFAULT, "  Flags:");
 
	IConsolePrint(CC_DEFAULT, "    c = catenary");
 
	IConsolePrint(CC_DEFAULT, "    l = no level crossings");
 
	IConsolePrint(CC_DEFAULT, "    h = hidden");
 
	IConsolePrint(CC_DEFAULT, "    s = no sprite combine");
 
	IConsolePrint(CC_DEFAULT, "    a = always allow 90 degree turns");
 
	IConsolePrint(CC_DEFAULT, "    d = always disallow 90 degree turns");
 

	
 
	std::map<uint32, const GRFFile *> grfs;
 
	for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
 
		const RailtypeInfo *rti = GetRailTypeInfo(rt);
 
		if (rti->label == 0) continue;
 
		uint32 grfid = 0;
 
		const GRFFile *grf = rti->grffile[RTSG_GROUND];
 
		if (grf != nullptr) {
 
			grfid = grf->grfid;
 
			grfs.emplace(grfid, grf);
 
		}
 
		IConsolePrintF(CC_DEFAULT, "  %02u %c%c%c%c, Flags: %c%c%c%c%c%c, GRF: %08X, %s",
 
		IConsolePrint(CC_DEFAULT, "  {:02d} {:c}{:c}{:c}{:c}, Flags: {}{}{}{}{}{}, GRF: {:08X}, {}",
 
				(uint)rt,
 
				rti->label >> 24, rti->label >> 16, rti->label >> 8, rti->label,
 
				HasBit(rti->flags, RTF_CATENARY)          ? 'c' : '-',
 
				HasBit(rti->flags, RTF_NO_LEVEL_CROSSING) ? 'l' : '-',
 
				HasBit(rti->flags, RTF_HIDDEN)            ? 'h' : '-',
 
				HasBit(rti->flags, RTF_NO_SPRITE_COMBINE) ? 's' : '-',
 
@@ -2231,42 +2229,42 @@ static void ConDumpRailTypes()
 
				HasBit(rti->flags, RTF_DISALLOW_90DEG)    ? 'd' : '-',
 
				BSWAP32(grfid),
 
				GetStringPtr(rti->strings.name)
 
		);
 
	}
 
	for (const auto &grf : grfs) {
 
		IConsolePrintF(CC_DEFAULT, "  GRF: %08X = %s", BSWAP32(grf.first), grf.second->filename);
 
		IConsolePrint(CC_DEFAULT, "  GRF: {:08X} = {}", BSWAP32(grf.first), grf.second->filename);
 
	}
 
}
 

	
 
static void ConDumpCargoTypes()
 
{
 
	IConsolePrintF(CC_DEFAULT, "  Cargo classes:");
 
	IConsolePrintF(CC_DEFAULT, "    p = passenger");
 
	IConsolePrintF(CC_DEFAULT, "    m = mail");
 
	IConsolePrintF(CC_DEFAULT, "    x = express");
 
	IConsolePrintF(CC_DEFAULT, "    a = armoured");
 
	IConsolePrintF(CC_DEFAULT, "    b = bulk");
 
	IConsolePrintF(CC_DEFAULT, "    g = piece goods");
 
	IConsolePrintF(CC_DEFAULT, "    l = liquid");
 
	IConsolePrintF(CC_DEFAULT, "    r = refrigerated");
 
	IConsolePrintF(CC_DEFAULT, "    h = hazardous");
 
	IConsolePrintF(CC_DEFAULT, "    c = covered/sheltered");
 
	IConsolePrintF(CC_DEFAULT, "    S = special");
 
	IConsolePrint(CC_DEFAULT, "  Cargo classes:");
 
	IConsolePrint(CC_DEFAULT, "    p = passenger");
 
	IConsolePrint(CC_DEFAULT, "    m = mail");
 
	IConsolePrint(CC_DEFAULT, "    x = express");
 
	IConsolePrint(CC_DEFAULT, "    a = armoured");
 
	IConsolePrint(CC_DEFAULT, "    b = bulk");
 
	IConsolePrint(CC_DEFAULT, "    g = piece goods");
 
	IConsolePrint(CC_DEFAULT, "    l = liquid");
 
	IConsolePrint(CC_DEFAULT, "    r = refrigerated");
 
	IConsolePrint(CC_DEFAULT, "    h = hazardous");
 
	IConsolePrint(CC_DEFAULT, "    c = covered/sheltered");
 
	IConsolePrint(CC_DEFAULT, "    S = special");
 

	
 
	std::map<uint32, const GRFFile *> grfs;
 
	for (CargoID i = 0; i < NUM_CARGO; i++) {
 
		const CargoSpec *spec = CargoSpec::Get(i);
 
		if (!spec->IsValid()) continue;
 
		uint32 grfid = 0;
 
		const GRFFile *grf = spec->grffile;
 
		if (grf != nullptr) {
 
			grfid = grf->grfid;
 
			grfs.emplace(grfid, grf);
 
		}
 
		IConsolePrintF(CC_DEFAULT, "  %02u Bit: %2u, Label: %c%c%c%c, Callback mask: 0x%02X, Cargo class: %c%c%c%c%c%c%c%c%c%c%c, GRF: %08X, %s",
 
		IConsolePrint(CC_DEFAULT, "  {:02d} Bit: {:2d}, Label: {:c}{:c}{:c}{:c}, Callback mask: 0x{:02X}, Cargo class: {}{}{}{}{}{}{}{}{}{}{}, GRF: {:08X}, {}",
 
				(uint)i,
 
				spec->bitnum,
 
				spec->label >> 24, spec->label >> 16, spec->label >> 8, spec->label,
 
				spec->callback_mask,
 
				(spec->classes & CC_PASSENGERS)   != 0 ? 'p' : '-',
 
				(spec->classes & CC_MAIL)         != 0 ? 'm' : '-',
 
@@ -2281,13 +2279,13 @@ static void ConDumpCargoTypes()
 
				(spec->classes & CC_SPECIAL)      != 0 ? 'S' : '-',
 
				BSWAP32(grfid),
 
				GetStringPtr(spec->name)
 
		);
 
	}
 
	for (const auto &grf : grfs) {
 
		IConsolePrintF(CC_DEFAULT, "  GRF: %08X = %s", BSWAP32(grf.first), grf.second->filename);
 
		IConsolePrint(CC_DEFAULT, "  GRF: {:08X} = {}", BSWAP32(grf.first), grf.second->filename);
 
	}
 
}
 

	
 

	
 
DEF_CONSOLE_CMD(ConDumpInfo)
 
{