Changeset - r25666:da59d4ce1d64
[Not reviewed]
master
0 9 0
rubidium42 - 3 years ago 2021-06-12 19:33:01
rubidium@openttd.org
Codechange: replace IConsolePrintF with IConsolePrint and fmt formatting

Also make some strings more consistent with the rest of the console strings.
9 files changed with 97 insertions and 120 deletions:
0 comments (0 inline, 0 general)
src/console.cpp
Show inline comments
 
@@ -50,33 +50,33 @@ void IConsoleInit()
 
}
 

	
 
static void IConsoleWriteToLogFile(const char *string)
 
{
 
	if (_iconsole_output_file != nullptr) {
 
		/* if there is an console output file ... also print it there */
 
		const char *header = GetLogPrefix();
 
		if ((strlen(header) != 0 && fwrite(header, strlen(header), 1, _iconsole_output_file) != 1) ||
 
				fwrite(string, strlen(string), 1, _iconsole_output_file) != 1 ||
 
				fwrite("\n", 1, 1, _iconsole_output_file) != 1) {
 
			fclose(_iconsole_output_file);
 
			_iconsole_output_file = nullptr;
 
			IConsolePrintF(CC_DEFAULT, "cannot write to log file");
 
			IConsolePrint(CC_ERROR, "Cannot write to console log file; closing the log file.");
 
		}
 
	}
 
}
 

	
 
bool CloseConsoleLogIfActive()
 
{
 
	if (_iconsole_output_file != nullptr) {
 
		IConsolePrintF(CC_DEFAULT, "file output complete");
 
		IConsolePrint(CC_INFO, "Console log file closed.");
 
		fclose(_iconsole_output_file);
 
		_iconsole_output_file = nullptr;
 
		return true;
 
	}
 

	
 
	return false;
 
}
 

	
 
void IConsoleFree()
 
{
 
	IConsoleGUIFree();
 
	CloseConsoleLogIfActive();
 
@@ -117,43 +117,24 @@ void IConsolePrint(TextColour colour_cod
 
		fprintf(stdout, "%s%s\n", GetLogPrefix(), str);
 
		fflush(stdout);
 
		IConsoleWriteToLogFile(str);
 
		free(str); // free duplicated string since it's not used anymore
 
		return;
 
	}
 

	
 
	IConsoleWriteToLogFile(str);
 
	IConsoleGUIPrint(colour_code, str);
 
}
 

	
 
/**
 
 * Handle the printing of text entered into the console or redirected there
 
 * by any other means. Uses printf() style format, for more information look
 
 * at IConsolePrint()
 
 */
 
void CDECL IConsolePrintF(TextColour colour_code, const char *format, ...)
 
{
 
	assert(IsValidConsoleColour(colour_code));
 

	
 
	va_list va;
 
	char buf[ICON_MAX_STREAMSIZE];
 

	
 
	va_start(va, format);
 
	vseprintf(buf, lastof(buf), format, va);
 
	va_end(va);
 

	
 
	IConsolePrint(colour_code, buf);
 
}
 

	
 
/**
 
 * Change a string into its number representation. Supports
 
 * decimal and hexadecimal numbers as well as 'on'/'off' 'true'/'false'
 
 * @param *value the variable a successful conversion will be put in
 
 * @param *arg the string to be converted
 
 * @return Return true on success or false on failure
 
 */
 
bool GetArgumentInteger(uint32 *value, const char *arg)
 
{
 
	char *endptr;
 

	
 
	if (strcmp(arg, "on") == 0 || strcmp(arg, "true") == 0) {
 
		*value = 1;
src/console_cmds.cpp
Show inline comments
 
@@ -182,25 +182,25 @@ DEF_CONSOLE_HOOK(ConHookNewGRFDeveloperT
 
		}
 
		return ConHookNoNetwork(echo);
 
	}
 
	return CHR_HIDE;
 
}
 

	
 
/**
 
 * 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.
 
 */
 
DEF_CONSOLE_CMD(ConResetEngines)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Reset status data of all engines. This might solve some issues with 'lost' engines. Usage: 'resetengines'");
 
		return true;
 
	}
 
@@ -316,27 +316,27 @@ DEF_CONSOLE_CMD(ConScrollToTile)
 
DEF_CONSOLE_CMD(ConSave)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Save the current game. Usage: 'save <filename>'");
 
		return true;
 
	}
 

	
 
	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;
 
}
 

	
 
/**
 
 * Explicitly save the configuration.
 
 * @return True.
 
 */
 
@@ -408,25 +408,25 @@ DEF_CONSOLE_CMD(ConRemove)
 

	
 

	
 
/* List all the files in the current dir via console */
 
DEF_CONSOLE_CMD(ConListFiles)
 
{
 
	if (argc == 0) {
 
		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 */
 
DEF_CONSOLE_CMD(ConChangeDirectory)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Change the dir via console. Usage: 'cd <directory | number>'");
 
		return true;
 
	}
 
@@ -514,25 +514,25 @@ static bool ConKickOrBan(const char *arg
 
			return true;
 
		}
 

	
 
		/* When banning, kick+ban all clients with that IP */
 
		n = NetworkServerKickOrBanIP(client_id, ban, reason);
 
	} else {
 
		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)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Kick a client from a network game. Usage: 'kick <ip | client-id> [<kick-reason>]'");
 
		IConsoleHelp("For client-id's, see the command 'clients'");
 
		return true;
 
	}
 
@@ -589,48 +589,46 @@ DEF_CONSOLE_CMD(ConUnBan)
 
	/* Try by IP. */
 
	uint index;
 
	for (index = 0; index < _network_ban_list.size(); index++) {
 
		if (_network_ban_list[index] == argv[1]) break;
 
	}
 

	
 
	/* 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'");
 
	}
 

	
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConBanList)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("List the IP's of banned clients: Usage 'banlist'");
 
		return true;
 
	}
 

	
 
	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;
 
}
 

	
 
DEF_CONSOLE_CMD(ConPauseGame)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Pause a network game. Usage: 'pause'");
 
		return true;
 
	}
 
@@ -704,27 +702,27 @@ DEF_CONSOLE_CMD(ConStatus)
 
	NetworkServerShowStatusToConsole();
 
	return true;
 
}
 

	
 
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)
 
{
 
	if (argc != 3) {
 
		IConsoleHelp("Change the nickname of a connected client. Usage: 'client_name <client-id> <new-name>'");
 
		IConsoleHelp("For client-id's, see the command 'clients'");
 
		return true;
 
	}
 

	
 
@@ -913,25 +911,25 @@ DEF_CONSOLE_CMD(ConNetworkReconnect)
 
			/* From a user pov 0 is a new company, internally it's different and all
 
			 * companies are offset by one to ease up on users (eg companies 1-8 not 0-7) */
 
			if (playas < COMPANY_FIRST + 1 || playas > MAX_COMPANIES + 1) return false;
 
			break;
 
	}
 

	
 
	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)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Connect to a remote OTTD server and join the game. Usage: 'connect <ip>'");
 
		IConsoleHelp("IP can contain port and company: 'IP[:Port][#Company]', eg: 'server.ottd.org:443#2'");
 
		IConsoleHelp("Company #255 is spectator all others are a certain company with Company 1 being #1");
 
		return true;
 
	}
 
@@ -1016,27 +1014,30 @@ DEF_CONSOLE_CMD(ConScript)
 
{
 
	extern FILE *_iconsole_output_file;
 

	
 
	if (argc == 0) {
 
		IConsoleHelp("Start or stop logging console output to a file. Usage: 'script <filename>'");
 
		IConsoleHelp("If filename is omitted, a running log is stopped if it is active");
 
		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;
 
}
 

	
 

	
 
DEF_CONSOLE_CMD(ConEcho)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Print back the first argument to the console. Usage: 'echo <arg>'");
 
		return true;
 
	}
 
@@ -1108,25 +1109,25 @@ DEF_CONSOLE_CMD(ConReload)
 
/**
 
 * Print a text buffer line by line to the console. Lines are separated by '\n'.
 
 * @param buf The buffer to print.
 
 * @note All newlines are replace by '\0' characters.
 
 */
 
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)
 
{
 
	char buf[4096];
 
	AI::GetConsoleLibraryList(buf, lastof(buf));
 

	
 
	PrintLineByLine(buf);
 

	
 
@@ -1248,25 +1249,25 @@ DEF_CONSOLE_CMD(ConReloadAI)
 
	if (_game_mode != GM_NORMAL) {
 
		IConsolePrint(CC_ERROR, "AIs can only be managed in a game.");
 
		return true;
 
	}
 

	
 
	if (_networking && !_network_server) {
 
		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.");
 
		return true;
 
	}
 

	
 
	/* First kill the company of the AI, then start a new one. This should start the current AI again */
 
	DoCommandP(0, CCA_DELETE | company_id << 16 | CRR_MANUAL << 24, 0, CMD_COMPANY_CTRL);
 
	DoCommandP(0, CCA_NEW_AI | company_id << 16, 0, CMD_COMPANY_CTRL);
 
@@ -1286,25 +1287,25 @@ DEF_CONSOLE_CMD(ConStopAI)
 
	if (_game_mode != GM_NORMAL) {
 
		IConsolePrint(CC_ERROR, "AIs can only be managed in a game.");
 
		return true;
 
	}
 

	
 
	if (_networking && !_network_server) {
 
		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.");
 
		return true;
 
	}
 

	
 
	/* Now kill the company of the AI. */
 
	DoCommandP(0, CCA_DELETE | company_id << 16 | CRR_MANUAL << 24, 0, CMD_COMPANY_CTRL);
 
	IConsolePrint(CC_DEFAULT, "AI stopped, company deleted.");
 
@@ -1359,51 +1360,51 @@ DEF_CONSOLE_CMD(ConRescanNewGRF)
 

	
 
	return true;
 
}
 

	
 
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)
 
{
 
	IConsoleAlias *alias;
 

	
 
	if (argc == 0) {
 
		IConsoleHelp("Add a new alias, or redefine the behaviour of an existing alias . Usage: 'alias <name> <command>'");
 
		return true;
 
	}
 
@@ -1523,25 +1524,25 @@ DEF_CONSOLE_CMD(ConInfoCmd)
 

	
 
DEF_CONSOLE_CMD(ConDebugLevel)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Get/set the default debugging level for the game. Usage: 'debug_level [<level>]'");
 
		IConsoleHelp("Level can be any combination of names, levels. Eg 'net=5 ms=4'. Remember to enclose it in \"'s");
 
		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;
 
}
 

	
 
DEF_CONSOLE_CMD(ConExit)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Exit the game. Usage: 'exit'");
 
		return true;
 
@@ -1576,25 +1577,25 @@ DEF_CONSOLE_CMD(ConHelp)
 
		if (cmd != nullptr) {
 
			cmd->proc(0, nullptr);
 
			return true;
 
		}
 

	
 
		alias = IConsole::AliasGet(argv[1]);
 
		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;
 
	}
 

	
 
	IConsolePrint(TC_LIGHT_BLUE, " ---- OpenTTD Console Help ---- ");
 
	IConsolePrint(CC_DEFAULT, " - commands: [command to list all commands: list_cmds]");
 
	IConsolePrint(CC_DEFAULT, " call commands with '<command> <arg2> <arg3>...'");
 
	IConsolePrint(CC_DEFAULT, " - to assign strings, or use them as arguments, enclose it within quotes");
 
	IConsolePrint(CC_DEFAULT, " like this: '<command> \"string argument with spaces\"'");
 
@@ -1606,42 +1607,42 @@ DEF_CONSOLE_CMD(ConHelp)
 
}
 

	
 
DEF_CONSOLE_CMD(ConListCommands)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("List all registered commands. Usage: 'list_cmds [<pre-filter>]'");
 
		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;
 
}
 

	
 
DEF_CONSOLE_CMD(ConListAliases)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("List all registered aliases. Usage: 'list_aliases [<pre-filter>]'");
 
		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;
 
}
 

	
 
DEF_CONSOLE_CMD(ConCompanies)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("List the details of all companies in the game. Usage 'companies'");
 
		return true;
 
	}
 
@@ -1652,25 +1653,25 @@ DEF_CONSOLE_CMD(ConCompanies)
 
		SetDParam(0, c->index);
 
		GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
 

	
 
		const char *password_state = "";
 
		if (c->is_ai) {
 
			password_state = "AI";
 
		} 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,
 
			password_state);
 
	}
 

	
 
	return true;
 
}
 

	
 
@@ -1696,25 +1697,25 @@ DEF_CONSOLE_CMD(ConSay)
 
DEF_CONSOLE_CMD(ConSayCompany)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Chat to a certain company in a multiplayer game. Usage: 'say_company <company-no> \"<msg>\"'");
 
		IConsoleHelp("CompanyNo is the company that plays as company <companyno>, 1 through max_companies");
 
		return true;
 
	}
 

	
 
	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 {
 
		bool from_admin = (_redirect_console_to_admin < INVALID_ADMIN_ID);
 
		NetworkServerSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, company_id, argv[2], CLIENT_ID_SERVER, from_admin);
 
	}
 

	
 
	return true;
 
}
 
@@ -1733,36 +1734,33 @@ DEF_CONSOLE_CMD(ConSayClient)
 
		NetworkClientSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
 
	} else {
 
		bool from_admin = (_redirect_console_to_admin < INVALID_ADMIN_ID);
 
		NetworkServerSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], CLIENT_ID_SERVER, from_admin);
 
	}
 

	
 
	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;
 

	
 
	if (argc == 2) {
 
		company_id = _local_company;
 
		password = argv[1];
 
		errormsg = "You have to own a company to make use of this command.";
 
	} else if (argc == 3 && _network_server) {
 
@@ -1798,52 +1796,52 @@ static ContentType StringToContentType(c
 
{
 
	static const char * const inv_lookup[] = { "", "base", "newgrf", "ai", "ailib", "scenario", "heightmap" };
 
	for (uint i = 1 /* there is no type 0 */; i < lengthof(inv_lookup); i++) {
 
		if (strcasecmp(str, inv_lookup[i]) == 0) return (ContentType)i;
 
	}
 
	return CONTENT_TYPE_END;
 
}
 

	
 
/** 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
 
 */
 
static void OutputContentState(const ContentInfo *const ci)
 
{
 
	static const char * const types[] = { "Base graphics", "NewGRF", "AI", "AI library", "Scenario", "Heightmap", "Base sound", "Base music", "Game script", "GS library" };
 
	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) {
 
		cb = new ConsoleContentCallback();
 
		_network_content_client.AddCallback(cb);
 
	}
 

	
 
	if (argc <= 1) {
 
		IConsoleHelp("Query, select and download content. Usage: 'content update|upgrade|select [id]|unselect [all|id]|state [filter]|download'");
 
@@ -1860,25 +1858,25 @@ DEF_CONSOLE_CMD(ConContent)
 
		_network_content_client.RequestContentList((argc > 2) ? StringToContentType(argv[2]) : CONTENT_TYPE_END);
 
		return true;
 
	}
 

	
 
	if (strcasecmp(argv[1], "upgrade") == 0) {
 
		_network_content_client.SelectUpgrade();
 
		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
 
			 * everything after a filter was applied; but this never really
 
			 * took off. Instead, a select few people used this functionality
 
			 * to download every available package on BaNaNaS. This is not in
 
			 * the spirit of this service. Additionally, these few people were
 
			 * good for 70% of the consumed bandwidth of BaNaNaS. */
 
			IConsolePrint(CC_ERROR, "'select all' is no longer supported since 1.11.");
 
@@ -1893,37 +1891,37 @@ DEF_CONSOLE_CMD(ConContent)
 
			IConsolePrint(CC_ERROR, "You must enter the id.");
 
			return false;
 
		}
 
		if (strcasecmp(argv[2], "all") == 0) {
 
			_network_content_client.UnselectAll();
 
		} else {
 
			_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) */
 

	
 
DEF_CONSOLE_CMD(ConSetting)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Change setting for all clients. Usage: 'setting <name> [<value>]'");
 
		IConsoleHelp("Omitting <value> will print out the current value of the setting.");
 
@@ -2013,25 +2011,25 @@ DEF_CONSOLE_CMD(ConNewGRFProfile)
 
	const std::vector<GRFFile *> &files = GetAllGRFFiles();
 

	
 
	/* "list" sub-command */
 
	if (argc == 1 || strncasecmp(argv[1], "lis", 3) == 0) {
 
		IConsolePrint(CC_INFO, "Loaded GRF files:");
 
		int i = 1;
 
		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 */
 
	if (strncasecmp(argv[1], "sel", 3) == 0 && argc >= 3) {
 
		for (size_t argnum = 2; argnum < argc; ++argnum) {
 
			int grfnum = atoi(argv[argnum]);
 
			if (grfnum < 1 || grfnum > (int)files.size()) { // safe cast, files.size() should not be larger than a few hundred in the most extreme cases
 
				IConsolePrint(CC_WARNING, "GRF number {} out of range, not added.", grfnum);
 
				continue;
 
@@ -2072,33 +2070,33 @@ DEF_CONSOLE_CMD(ConNewGRFProfile)
 
		for (NewGRFProfiler &pr : _newgrf_profilers) {
 
			if (!pr.active) {
 
				pr.Start();
 
				started++;
 

	
 
				if (!grfids.empty()) grfids += ", ";
 
				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 {
 
			IConsolePrint(CC_ERROR, "Did not start profiling for any GRFs, all selected GRFs are already profiling.");
 
		}
 
		return true;
 
	}
 

	
 
	/* "stop" sub-command */
 
@@ -2156,144 +2154,144 @@ DEF_CONSOLE_CMD(ConFramerateWindow)
 

	
 
	if (_network_dedicated) {
 
		IConsolePrint(CC_ERROR, "Can not open frame rate window on a dedicated server");
 
		return false;
 
	}
 

	
 
	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' : '-',
 
				HasBit(rti->flags, ROTF_HIDDEN)            ? 'h' : '-',
 
				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' : '-',
 
				HasBit(rti->flags, RTF_ALLOW_90DEG)       ? 'a' : '-',
 
				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' : '-',
 
				(spec->classes & CC_EXPRESS)      != 0 ? 'x' : '-',
 
				(spec->classes & CC_ARMOURED)     != 0 ? 'a' : '-',
 
				(spec->classes & CC_BULK)         != 0 ? 'b' : '-',
 
				(spec->classes & CC_PIECE_GOODS)  != 0 ? 'g' : '-',
 
				(spec->classes & CC_LIQUID)       != 0 ? 'l' : '-',
 
				(spec->classes & CC_REFRIGERATED) != 0 ? 'r' : '-',
 
				(spec->classes & CC_HAZARDOUS)    != 0 ? 'h' : '-',
 
				(spec->classes & CC_COVERED)      != 0 ? 'c' : '-',
 
				(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)
 
{
 
	if (argc != 2) {
 
		IConsoleHelp("Dump debugging information.");
 
		IConsoleHelp("Usage: dump_info roadtypes|railtypes|cargotypes");
 
		IConsoleHelp("  Show information about road/tram types, rail types or cargo types.");
 
		return true;
 
	}
src/console_func.h
Show inline comments
 
@@ -37,20 +37,18 @@ void IConsolePrint(TextColour colour_cod
 
 * @tparam T The type of formatting parameter.
 
 * @tparam A The type of the first argument.
 
 * @tparam Args The types of the other arguments.
 
 */
 
template <typename T, typename A, typename ... Args>
 
static inline void IConsolePrint(TextColour colour_code, const T &format, A first_arg, Args&&... other_args)
 
{
 
	/* The separate first_arg argument is added to aid overloading.
 
	 * Otherwise the calls that do no need formatting will still use this function. */
 
	IConsolePrint(colour_code, fmt::format(format, first_arg, other_args...));
 
}
 

	
 
void CDECL IConsolePrintF(TextColour colour_code, const char *format, ...) WARN_FORMAT(2, 3);
 

	
 
/* Parser */
 
void IConsoleCmdExec(const char *cmdstr, const uint recurse_count = 0);
 

	
 
bool IsValidConsoleColour(TextColour c);
 

	
 
#endif /* CONSOLE_FUNC_H */
src/console_gui.cpp
Show inline comments
 
@@ -278,25 +278,25 @@ struct IConsoleWindow : Window
 
			case WKC_SHIFT | WKC_UP:
 
				this->Scroll(1);
 
				break;
 

	
 
			case WKC_BACKQUOTE:
 
				IConsoleSwitch();
 
				break;
 

	
 
			case WKC_RETURN: case WKC_NUM_ENTER: {
 
				/* We always want the ] at the left side; we always force these strings to be left
 
				 * aligned anyway. So enforce this in all cases by adding a left-to-right marker,
 
				 * otherwise it will be drawn at the wrong side with right-to-left texts. */
 
				IConsolePrintF(CC_COMMAND, LRM "] %s", _iconsole_cmdline.buf);
 
				IConsolePrint(CC_COMMAND, LRM "] {}", _iconsole_cmdline.buf);
 
				const char *cmd = IConsoleHistoryAdd(_iconsole_cmdline.buf);
 
				IConsoleClearCommand();
 

	
 
				if (cmd != nullptr) IConsoleCmdExec(cmd);
 
				break;
 
			}
 

	
 
			case WKC_CTRL | WKC_RETURN:
 
				_iconsole_mode = (_iconsole_mode == ICONSOLE_FULL) ? ICONSOLE_OPENED : ICONSOLE_FULL;
 
				IConsoleResize(this);
 
				MarkWholeScreenDirty();
 
				break;
 
@@ -390,28 +390,28 @@ struct IConsoleWindow : Window
 
};
 

	
 
int IConsoleWindow::scroll = 0;
 

	
 
void IConsoleGUIInit()
 
{
 
	IConsoleResetHistoryPos();
 
	_iconsole_mode = ICONSOLE_CLOSED;
 

	
 
	IConsoleLine::Reset();
 
	memset(_iconsole_history, 0, sizeof(_iconsole_history));
 

	
 
	IConsolePrintF(CC_WARNING, "OpenTTD Game Console Revision 7 - %s", _openttd_revision);
 
	IConsolePrint(CC_WHITE,  "------------------------------------");
 
	IConsolePrint(CC_WHITE,  "use \"help\" for more information");
 
	IConsolePrint(CC_WHITE,  "");
 
	IConsolePrint(TC_LIGHT_BLUE, "OpenTTD Game Console Revision 7 - {}", _openttd_revision);
 
	IConsolePrint(CC_WHITE, "------------------------------------");
 
	IConsolePrint(CC_WHITE, "use \"help\" for more information");
 
	IConsolePrint(CC_WHITE, "");
 
	IConsoleClearCommand();
 
}
 

	
 
void IConsoleClearBuffer()
 
{
 
	IConsoleLine::Reset();
 
}
 

	
 
void IConsoleGUIFree()
 
{
 
	IConsoleClearBuffer();
 
}
src/framerate_gui.cpp
Show inline comments
 
@@ -1014,25 +1014,25 @@ void ShowFrametimeGraphWindow(Performanc
 
{
 
	if (elem < PFE_FIRST || elem >= PFE_MAX) return; // maybe warn?
 
	AllocateWindowDescFront<FrametimeGraphWindow>(&_frametime_graph_window_desc, elem, true);
 
}
 

	
 
/** Print performance statistics to game console */
 
void ConPrintFramerate()
 
{
 
	const int count1 = NUM_FRAMERATE_POINTS / 8;
 
	const int count2 = NUM_FRAMERATE_POINTS / 4;
 
	const int count3 = NUM_FRAMERATE_POINTS / 1;
 

	
 
	IConsolePrintF(TC_SILVER, "Based on num. data points: %d %d %d", count1, count2, count3);
 
	IConsolePrint(TC_SILVER, "Based on num. data points: {} {} {}", count1, count2, count3);
 

	
 
	static const char *MEASUREMENT_NAMES[PFE_MAX] = {
 
		"Game loop",
 
		"  GL station ticks",
 
		"  GL train ticks",
 
		"  GL road vehicle ticks",
 
		"  GL ship ticks",
 
		"  GL aircraft ticks",
 
		"  GL landscape ticks",
 
		"  GL link graph delays",
 
		"Drawing",
 
		"  Viewport drawing",
 
@@ -1041,41 +1041,41 @@ void ConPrintFramerate()
 
		"AI/GS scripts total",
 
		"Game script",
 
	};
 
	char ai_name_buf[128];
 

	
 
	static const PerformanceElement rate_elements[] = { PFE_GAMELOOP, PFE_DRAWING, PFE_VIDEO };
 

	
 
	bool printed_anything = false;
 

	
 
	for (const PerformanceElement *e = rate_elements; e < rate_elements + lengthof(rate_elements); e++) {
 
		auto &pf = _pf_data[*e];
 
		if (pf.num_valid == 0) continue;
 
		IConsolePrintF(TC_GREEN, "%s rate: %.2ffps  (expected: %.2ffps)",
 
		IConsolePrint(TC_GREEN, "{} rate: {:.2f}fps  (expected: {:.2f}fps)",
 
			MEASUREMENT_NAMES[*e],
 
			pf.GetRate(),
 
			pf.expected_rate);
 
		printed_anything = true;
 
	}
 

	
 
	for (PerformanceElement e = PFE_FIRST; e < PFE_MAX; e++) {
 
		auto &pf = _pf_data[e];
 
		if (pf.num_valid == 0) continue;
 
		const char *name;
 
		if (e < PFE_AI0) {
 
			name = MEASUREMENT_NAMES[e];
 
		} else {
 
			seprintf(ai_name_buf, lastof(ai_name_buf), "AI %d %s", e - PFE_AI0 + 1, GetAIName(e - PFE_AI0)),
 
			name = ai_name_buf;
 
		}
 
		IConsolePrintF(TC_LIGHT_BLUE, "%s times: %.2fms  %.2fms  %.2fms",
 
		IConsolePrint(TC_LIGHT_BLUE, "{} times: {:.2f}ms  {:.2f}ms  {:.2f}ms",
 
			name,
 
			pf.GetAverageDurationMilliseconds(count1),
 
			pf.GetAverageDurationMilliseconds(count2),
 
			pf.GetAverageDurationMilliseconds(count3));
 
		printed_anything = true;
 
	}
 

	
 
	if (!printed_anything) {
 
		IConsolePrint(CC_ERROR, "No performance measurements have been taken yet.");
 
	}
 
}
src/music/midifile.cpp
Show inline comments
 
@@ -1100,43 +1100,43 @@ std::string MidiFile::GetSMFFile(const M
 

	
 
	if (midifile.WriteSMF(output_filename.c_str())) {
 
		return output_filename;
 
	} else {
 
		return std::string();
 
	}
 
}
 

	
 

	
 
static bool CmdDumpSMF(byte argc, char *argv[])
 
{
 
	if (argc == 0) {
 
		IConsolePrint(CC_WARNING, "Write the current song to a Standard MIDI File. Usage: 'dumpsmf <filename>'");
 
		IConsolePrint(CC_HELP, "Write the current song to a Standard MIDI File. Usage: 'dumpsmf <filename>'.");
 
		return true;
 
	}
 
	if (argc != 2) {
 
		IConsolePrint(CC_WARNING, "You must specify a filename to write MIDI data to.");
 
		return false;
 
	}
 

	
 
	if (_midifile_instance == nullptr) {
 
		IConsolePrint(CC_ERROR, "There is no MIDI file loaded currently, make sure music is playing, and you're using a driver that works with raw MIDI.");
 
		return false;
 
	}
 

	
 
	char fnbuf[MAX_PATH] = { 0 };
 
	if (seprintf(fnbuf, lastof(fnbuf), "%s%s", FiosGetScreenshotDir(), argv[1]) >= (int)lengthof(fnbuf)) {
 
		IConsolePrint(CC_ERROR, "Filename too long.");
 
		return false;
 
	}
 
	IConsolePrintF(CC_INFO, "Dumping MIDI to: %s", fnbuf);
 
	IConsolePrint(CC_INFO, "Dumping MIDI to '{}'.", fnbuf);
 

	
 
	if (_midifile_instance->WriteSMF(fnbuf)) {
 
		IConsolePrint(CC_INFO, "File written successfully.");
 
		return true;
 
	} else {
 
		IConsolePrint(CC_ERROR, "An error occurred writing MIDI file.");
 
		return false;
 
	}
 
}
 

	
 
static void RegisterConsoleMidiCommands()
 
{
src/network/network_client.cpp
Show inline comments
 
@@ -1151,25 +1151,25 @@ NetworkRecvStatus ClientNetworkGameSocke
 
	return NETWORK_RECV_STATUS_SERVER_ERROR;
 
}
 

	
 
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_RCON(Packet *p)
 
{
 
	if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 

	
 
	TextColour colour_code = (TextColour)p->Recv_uint16();
 
	if (!IsValidConsoleColour(colour_code)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 

	
 
	std::string rcon_out = p->Recv_string(NETWORK_RCONCOMMAND_LENGTH);
 

	
 
	IConsolePrint(colour_code, rcon_out.c_str());
 
	IConsolePrint(colour_code, rcon_out);
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MOVE(Packet *p)
 
{
 
	if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 

	
 
	/* Nothing more in this packet... */
 
	ClientID client_id   = (ClientID)p->Recv_uint32();
 
	CompanyID company_id = (CompanyID)p->Recv_uint8();
 

	
src/newgrf_profiling.cpp
Show inline comments
 
@@ -86,30 +86,30 @@ void NewGRFProfiler::RecursiveResolve()
 
void NewGRFProfiler::Start()
 
{
 
	this->Abort();
 
	this->active = true;
 
	this->start_tick = _tick_counter;
 
}
 

	
 
uint32 NewGRFProfiler::Finish()
 
{
 
	if (!this->active) return 0;
 

	
 
	if (this->calls.empty()) {
 
		IConsolePrintF(CC_DEBUG, "Finished profile of NewGRF [%08X], no events collected, not writing a file", BSWAP32(this->grffile->grfid));
 
		IConsolePrint(CC_DEBUG, "Finished profile of NewGRF [{:08X}], no events collected, not writing a file.", BSWAP32(this->grffile->grfid));
 
		return 0;
 
	}
 

	
 
	std::string filename = this->GetOutputFilename();
 
	IConsolePrintF(CC_DEBUG, "Finished profile of NewGRF [%08X], writing %u events to %s", BSWAP32(this->grffile->grfid), (uint)this->calls.size(), filename.c_str());
 
	IConsolePrint(CC_DEBUG, "Finished profile of NewGRF [{:08X}], writing {} events to '{}'.", BSWAP32(this->grffile->grfid), this->calls.size(), filename);
 

	
 
	FILE *f = FioFOpenFile(filename, "wt", Subdirectory::NO_DIRECTORY);
 
	FileCloser fcloser(f);
 

	
 
	uint32 total_microseconds = 0;
 

	
 
	fputs("Tick,Sprite,Feature,Item,CallbackID,Microseconds,Depth,Result\n", f);
 
	for (const Call &c : this->calls) {
 
		fprintf(f, "%u,%u,0x%X,%u,0x%X,%u,%u,%u\n", c.tick, c.root_sprite, c.feat, c.item, (uint)c.cb, c.time, c.subs, c.result);
 
		total_microseconds += c.time;
 
	}
 

	
 
@@ -142,19 +142,19 @@ std::string NewGRFProfiler::GetOutputFil
 
uint32 NewGRFProfiler::FinishAll()
 
{
 
	int max_ticks = 0;
 
	uint32 total_microseconds = 0;
 
	for (NewGRFProfiler &pr : _newgrf_profilers) {
 
		if (pr.active) {
 
			total_microseconds += pr.Finish();
 
			max_ticks = std::max(max_ticks, _tick_counter - pr.start_tick);
 
		}
 
	}
 

	
 
	if (total_microseconds > 0 && max_ticks > 0) {
 
		IConsolePrintF(CC_DEBUG, "Total NewGRF callback processing: %u microseconds over %d ticks", total_microseconds, max_ticks);
 
		IConsolePrint(CC_DEBUG, "Total NewGRF callback processing: {} microseconds over {} ticks.", total_microseconds, max_ticks);
 
	}
 

	
 
	_newgrf_profile_end_date = MAX_DAY;
 

	
 
	return total_microseconds;
 
}
src/settings.cpp
Show inline comments
 
@@ -1920,37 +1920,37 @@ void StringSettingDesc::ChangeValue(cons
 
	this->Write(object, newval);
 
	if (this->post_callback != nullptr) this->post_callback(newval);
 

	
 
	if (_save_config) SaveToConfig();
 
}
 

	
 
/* Those 2 functions need to be here, else we have to make some stuff non-static
 
 * and besides, it is also better to keep stuff like this at the same place */
 
void IConsoleSetSetting(const char *name, const char *value, bool force_newgame)
 
{
 
	const SettingDesc *sd = GetSettingFromName(name);
 
	if (sd == nullptr) {
 
		IConsolePrintF(CC_WARNING, "'%s' is an unknown setting.", name);
 
		IConsolePrint(CC_ERROR, "'{}' is an unknown setting.", name);
 
		return;
 
	}
 

	
 
	bool success = true;
 
	if (sd->IsStringSetting()) {
 
		success = SetSettingValue(sd->AsStringSetting(), value, force_newgame);
 
	} else if (sd->IsIntSetting()) {
 
		uint32 val;
 
		extern bool GetArgumentInteger(uint32 *value, const char *arg);
 
		success = GetArgumentInteger(&val, value);
 
		if (!success) {
 
			IConsolePrintF(CC_ERROR, "'%s' is not an integer.", value);
 
			IConsolePrint(CC_ERROR, "'{}' is not an integer.", value);
 
			return;
 
		}
 

	
 
		success = SetSettingValue(sd->AsIntSetting(), val, force_newgame);
 
	}
 

	
 
	if (!success) {
 
		if (_network_server) {
 
			IConsolePrint(CC_ERROR, "This command/variable is not available during network games.");
 
		} else {
 
			IConsolePrint(CC_ERROR, "This command/variable is only available to a network server.");
 
		}
 
@@ -1964,59 +1964,59 @@ void IConsoleSetSetting(const char *name
 
	SetSettingValue(sd->AsIntSetting(), value);
 
}
 

	
 
/**
 
 * Output value of a specific setting to the console
 
 * @param name  Name of the setting to output its value
 
 * @param force_newgame force the newgame settings
 
 */
 
void IConsoleGetSetting(const char *name, bool force_newgame)
 
{
 
	const SettingDesc *sd = GetSettingFromName(name);
 
	if (sd == nullptr) {
 
		IConsolePrintF(CC_WARNING, "'%s' is an unknown setting.", name);
 
		IConsolePrint(CC_ERROR, "'{}' is an unknown setting.", name);
 
		return;
 
	}
 

	
 
	const void *object = (_game_mode == GM_MENU || force_newgame) ? &_settings_newgame : &_settings_game;
 

	
 
	if (sd->IsStringSetting()) {
 
		IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", sd->name.c_str(), sd->AsStringSetting()->Read(object).c_str());
 
		IConsolePrint(CC_INFO, "Current value for '{}' is '{}'.", sd->name, sd->AsStringSetting()->Read(object));
 
	} else if (sd->IsIntSetting()) {
 
		char value[20];
 
		sd->FormatValue(value, lastof(value), object);
 
		const IntSettingDesc *int_setting = sd->AsIntSetting();
 
		IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %u)",
 
		IConsolePrint(CC_INFO, "Current value for '{}' is '{}' (min: {}{}, max: {}).",
 
			sd->name.c_str(), value, (sd->flags & SF_GUI_0_IS_SPECIAL) ? "(0) " : "", int_setting->min, int_setting->max);
 
	}
 
}
 

	
 
/**
 
 * List all settings and their value to the console
 
 *
 
 * @param prefilter  If not \c nullptr, only list settings with names that begin with \a prefilter prefix
 
 */
 
void IConsoleListSettings(const char *prefilter)
 
{
 
	IConsolePrintF(CC_WARNING, "All settings with their current value:");
 
	IConsolePrint(CC_HELP, "All settings with their current value:");
 

	
 
	for (auto &sd : _settings) {
 
		if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue;
 
		if (prefilter != nullptr && sd->name.find(prefilter) == std::string::npos) continue;
 
		char value[80];
 
		sd->FormatValue(value, lastof(value), &GetGameSettings());
 
		IConsolePrintF(CC_DEFAULT, "%s = %s", sd->name.c_str(), value);
 
		IConsolePrint(CC_DEFAULT, "{} = {}", sd->name, value);
 
	}
 

	
 
	IConsolePrintF(CC_WARNING, "Use 'setting' command to change a value");
 
	IConsolePrint(CC_HELP, "Use 'setting' command to change a value.");
 
}
 

	
 
/**
 
 * Get the SaveLoad description for the SettingTable.
 
 * @param settings SettingDesc struct containing all information.
 
 * @param is_loading True iff the SaveLoad table is for loading.
 
 * @return Vector with SaveLoad entries for the SettingTable.
 
 */
 
static std::vector<SaveLoad> GetSettingsDesc(const SettingTable &settings, bool is_loading)
 
{
 
	std::vector<SaveLoad> saveloads;
 
	for (auto &sd : settings) {
0 comments (0 inline, 0 general)