Merge branch 'origin/master' commit 'a499e9acdd385b57dd43caf88af3a6f7f53716ba'

This commit is contained in:
pelya
2020-03-20 00:10:46 +02:00
1448 changed files with 32573 additions and 27146 deletions

View File

@@ -1,5 +1,3 @@
/* $Id$ */
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
@@ -35,10 +33,12 @@
#include "ai/ai.hpp"
#include "ai/ai_config.hpp"
#include "newgrf.h"
#include "newgrf_profiling.h"
#include "console_func.h"
#include "engine_base.h"
#include "game/game.hpp"
#include "table/strings.h"
#include <time.h>
#include "safeguards.h"
@@ -86,8 +86,6 @@ static ConsoleFileList _console_file_list; ///< File storage cache for the conso
* command hooks
****************/
#ifdef ENABLE_NETWORK
/**
* Check network availability and inform in console about failure of detection.
* @return Network availability.
@@ -159,10 +157,6 @@ DEF_CONSOLE_HOOK(ConHookNoNetwork)
return CHR_ALLOW;
}
#else
# define ConHookNoNetwork NULL
#endif /* ENABLE_NETWORK */
DEF_CONSOLE_HOOK(ConHookNewGRFDeveloperTool)
{
if (_settings_client.gui.newgrf_developer_tools) {
@@ -170,11 +164,7 @@ DEF_CONSOLE_HOOK(ConHookNewGRFDeveloperTool)
if (echo) IConsoleError("This command is only available in game and editor.");
return CHR_DISALLOW;
}
#ifdef ENABLE_NETWORK
return ConHookNoNetwork(echo);
#else
return CHR_ALLOW;
#endif
}
return CHR_HIDE;
}
@@ -258,7 +248,7 @@ DEF_CONSOLE_CMD(ConResetTile)
* Scroll to a tile on the map.
* param x tile number or tile x coordinate.
* param y optional y coordinate.
* @note When only one argument is given it is intepreted as the tile number.
* @note When only one argument is given it is interpreted as the tile number.
* When two arguments are given, they are interpreted as the tile's x
* and y coordinates.
* @return True when either console help was shown or a proper amount of parameters given.
@@ -359,7 +349,7 @@ DEF_CONSOLE_CMD(ConLoad)
const char *file = argv[1];
_console_file_list.ValidateFileList();
const FiosItem *item = _console_file_list.FindItem(file);
if (item != NULL) {
if (item != nullptr) {
if (GetAbstractFileType(item->type) == FT_SAVEGAME) {
_switch_mode = SM_LOAD_GAME;
_file_to_saveload.SetMode(item->type);
@@ -388,7 +378,7 @@ DEF_CONSOLE_CMD(ConRemove)
const char *file = argv[1];
_console_file_list.ValidateFileList();
const FiosItem *item = _console_file_list.FindItem(file);
if (item != NULL) {
if (item != nullptr) {
if (!FiosDelete(item->name)) {
IConsolePrintF(CC_ERROR, "%s: Failed to delete file", file);
}
@@ -444,7 +434,7 @@ DEF_CONSOLE_CMD(ConChangeDirectory)
const char *file = argv[1];
_console_file_list.ValidateFileList(true);
const FiosItem *item = _console_file_list.FindItem(file);
if (item != NULL) {
if (item != nullptr) {
switch (item->type) {
case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT:
FiosBrowseTo(item);
@@ -472,7 +462,7 @@ DEF_CONSOLE_CMD(ConPrintWorkingDirectory)
_console_file_list.ValidateFileList(true);
_console_file_list.InvalidateFileList();
FiosGetDescText(&path, NULL);
FiosGetDescText(&path, nullptr);
IConsolePrint(CC_DEFAULT, path);
return true;
}
@@ -493,13 +483,12 @@ DEF_CONSOLE_CMD(ConClearBuffer)
/**********************************
* Network Core Console Commands
**********************************/
#ifdef ENABLE_NETWORK
static bool ConKickOrBan(const char *argv, bool ban)
static bool ConKickOrBan(const char *argv, bool ban, const char *reason)
{
uint n;
if (strchr(argv, '.') == NULL && strchr(argv, ':') == NULL) { // banning with ID
if (strchr(argv, '.') == nullptr && strchr(argv, ':') == nullptr) { // banning with ID
ClientID client_id = (ClientID)atoi(argv);
/* Don't kill the server, or the client doing the rcon. The latter can't be kicked because
@@ -512,21 +501,21 @@ static bool ConKickOrBan(const char *argv, bool ban)
}
NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
if (ci == NULL) {
if (ci == nullptr) {
IConsoleError("Invalid client");
return true;
}
if (!ban) {
/* Kick only this client, not all clients with that IP */
NetworkServerKickClient(client_id);
NetworkServerKickClient(client_id, reason);
return true;
}
/* When banning, kick+ban all clients with that IP */
n = NetworkServerKickOrBanIP(client_id, ban);
n = NetworkServerKickOrBanIP(client_id, ban, reason);
} else {
n = NetworkServerKickOrBanIP(argv, ban);
n = NetworkServerKickOrBanIP(argv, ban, reason);
}
if (n == 0) {
@@ -541,28 +530,48 @@ static bool ConKickOrBan(const char *argv, bool ban)
DEF_CONSOLE_CMD(ConKick)
{
if (argc == 0) {
IConsoleHelp("Kick a client from a network game. Usage: 'kick <ip | client-id>'");
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;
}
if (argc != 2) return false;
if (argc != 2 && argc != 3) return false;
return ConKickOrBan(argv[1], false);
/* No reason supplied for kicking */
if (argc == 2) return ConKickOrBan(argv[1], false, nullptr);
/* Reason for kicking supplied */
size_t kick_message_length = strlen(argv[2]);
if (kick_message_length >= 255) {
IConsolePrintF(CC_ERROR, "ERROR: Maximum kick message length is 254 characters. You entered %d characters.", kick_message_length);
return false;
} else {
return ConKickOrBan(argv[1], false, argv[2]);
}
}
DEF_CONSOLE_CMD(ConBan)
{
if (argc == 0) {
IConsoleHelp("Ban a client from a network game. Usage: 'ban <ip | client-id>'");
IConsoleHelp("Ban a client from a network game. Usage: 'ban <ip | client-id> [<ban-reason>]'");
IConsoleHelp("For client-id's, see the command 'clients'");
IConsoleHelp("If the client is no longer online, you can still ban his/her IP");
return true;
}
if (argc != 2) return false;
if (argc != 2 && argc != 3) return false;
return ConKickOrBan(argv[1], true);
/* No reason supplied for kicking */
if (argc == 2) return ConKickOrBan(argv[1], true, nullptr);
/* Reason for kicking supplied */
size_t kick_message_length = strlen(argv[2]);
if (kick_message_length >= 255) {
IConsolePrintF(CC_ERROR, "ERROR: Maximum kick message length is 254 characters. You entered %d characters.", kick_message_length);
return false;
} else {
return ConKickOrBan(argv[1], true, argv[2]);
}
}
DEF_CONSOLE_CMD(ConUnBan)
@@ -577,21 +586,20 @@ DEF_CONSOLE_CMD(ConUnBan)
/* Try by IP. */
uint index;
for (index = 0; index < _network_ban_list.Length(); index++) {
if (strcmp(_network_ban_list[index], argv[1]) == 0) break;
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.Length()) {
if (index >= _network_ban_list.size()) {
index = atoi(argv[1]) - 1U; // let it wrap
}
if (index < _network_ban_list.Length()) {
if (index < _network_ban_list.size()) {
char msg[64];
seprintf(msg, lastof(msg), "Unbanned %s", _network_ban_list[index]);
seprintf(msg, lastof(msg), "Unbanned %s", _network_ban_list[index].c_str());
IConsolePrint(CC_DEFAULT, msg);
free(_network_ban_list[index]);
_network_ban_list.Erase(_network_ban_list.Get(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'");
@@ -610,8 +618,8 @@ DEF_CONSOLE_CMD(ConBanList)
IConsolePrint(CC_DEFAULT, "Banlist: ");
uint i = 1;
for (char **iter = _network_ban_list.Begin(); iter != _network_ban_list.End(); iter++, i++) {
IConsolePrintF(CC_DEFAULT, " %d) %s", i, *iter);
for (const auto &entry : _network_ban_list) {
IConsolePrintF(CC_DEFAULT, " %d) %s", i, entry.c_str());
}
return true;
@@ -714,7 +722,7 @@ DEF_CONSOLE_CMD(ConClientNickChange)
return true;
}
if (NetworkClientInfo::GetByClientID(client_id) == NULL) {
if (NetworkClientInfo::GetByClientID(client_id) == nullptr) {
IConsoleError("Invalid client");
return true;
}
@@ -785,7 +793,7 @@ DEF_CONSOLE_CMD(ConMoveClient)
CompanyID company_id = (CompanyID)(atoi(argv[2]) <= MAX_COMPANIES ? atoi(argv[2]) - 1 : atoi(argv[2]));
/* check the client exists */
if (ci == NULL) {
if (ci == nullptr) {
IConsoleError("Invalid client-id, check the command 'clients' for valid client-id's.");
return true;
}
@@ -850,7 +858,7 @@ DEF_CONSOLE_CMD(ConResetCompany)
}
/* It is safe to remove this company */
DoCommandP(0, CCA_DELETE | index << 16, CRR_MANUAL, CMD_COMPANY_CTRL);
DoCommandP(0, CCA_DELETE | index << 16 | CRR_MANUAL << 24, 0, CMD_COMPANY_CTRL);
IConsolePrint(CC_DEFAULT, "Company deleted.");
return true;
@@ -884,8 +892,7 @@ DEF_CONSOLE_CMD(ConNetworkReconnect)
default:
/* 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) */
playas--;
if (playas < COMPANY_FIRST || playas >= MAX_COMPANIES) return false;
if (playas < COMPANY_FIRST + 1 || playas > MAX_COMPANIES + 1) return false;
break;
}
@@ -913,8 +920,8 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
if (argc < 2) return false;
if (_networking) NetworkDisconnect(); // we are in network-mode, first close it!
const char *port = NULL;
const char *company = NULL;
const char *port = nullptr;
const char *company = nullptr;
char *ip = argv[1];
/* Default settings: default port and new company */
uint16 rport = NETWORK_DEFAULT_PORT;
@@ -923,7 +930,7 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
ParseConnectionString(&company, &port, ip);
IConsolePrintF(CC_DEFAULT, "Connecting to %s...", ip);
if (company != NULL) {
if (company != nullptr) {
join_as = (CompanyID)atoi(company);
IConsolePrintF(CC_DEFAULT, " company-no: %d", join_as);
@@ -934,7 +941,7 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
join_as--;
}
}
if (port != NULL) {
if (port != nullptr) {
rport = atoi(port);
IConsolePrintF(CC_DEFAULT, " port: %s", port);
}
@@ -944,8 +951,6 @@ DEF_CONSOLE_CMD(ConNetworkConnect)
return true;
}
#endif /* ENABLE_NETWORK */
/*********************************
* script file console commands
*********************************/
@@ -961,7 +966,7 @@ DEF_CONSOLE_CMD(ConExec)
FILE *script_file = FioFOpenFile(argv[1], "r", BASE_DIR);
if (script_file == NULL) {
if (script_file == nullptr) {
if (argc == 2 || atoi(argv[2]) != 0) IConsoleError("script file not found");
return true;
}
@@ -969,7 +974,7 @@ DEF_CONSOLE_CMD(ConExec)
_script_running = true;
char cmdline[ICON_CMDLN_SIZE];
while (_script_running && fgets(cmdline, sizeof(cmdline), script_file) != NULL) {
while (_script_running && fgets(cmdline, sizeof(cmdline), script_file) != nullptr) {
/* Remove newline characters from the executing script */
for (char *cmdptr = cmdline; *cmdptr != '\0'; cmdptr++) {
if (*cmdptr == '\n' || *cmdptr == '\r') {
@@ -1020,7 +1025,7 @@ DEF_CONSOLE_CMD(ConScript)
IConsolePrintF(CC_DEFAULT, "file output started to: %s", argv[1]);
_iconsole_output_file = fopen(argv[1], "ab");
if (_iconsole_output_file == NULL) IConsoleError("could not open file");
if (_iconsole_output_file == nullptr) IConsoleError("could not open file");
}
return true;
@@ -1059,7 +1064,7 @@ DEF_CONSOLE_CMD(ConNewGame)
return true;
}
StartNewGameWithoutGUI((argc == 2) ? strtoul(argv[1], NULL, 10) : GENERATE_NEW_SEED);
StartNewGameWithoutGUI((argc == 2) ? strtoul(argv[1], nullptr, 10) : GENERATE_NEW_SEED);
return true;
}
@@ -1172,9 +1177,8 @@ DEF_CONSOLE_CMD(ConStartAI)
}
int n = 0;
Company *c;
/* Find the next free slot */
FOR_ALL_COMPANIES(c) {
for (const Company *c : Company::Iterate()) {
if (c->index != n) break;
n++;
}
@@ -1227,7 +1231,7 @@ DEF_CONSOLE_CMD(ConReloadAI)
}
/* 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, CMD_COMPANY_CTRL);
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);
IConsolePrint(CC_DEFAULT, "AI reloaded.");
@@ -1264,7 +1268,7 @@ DEF_CONSOLE_CMD(ConStopAI)
}
/* Now kill the company of the AI. */
DoCommandP(0, CCA_DELETE | company_id << 16, CRR_MANUAL, CMD_COMPANY_CTRL);
DoCommandP(0, CCA_DELETE | company_id << 16 | CRR_MANUAL << 24, 0, CMD_COMPANY_CTRL);
IConsolePrint(CC_DEFAULT, "AI stopped, company deleted.");
return true;
@@ -1311,7 +1315,7 @@ DEF_CONSOLE_CMD(ConRescanNewGRF)
return true;
}
ScanNewGRFFiles(NULL);
ScanNewGRFFiles(nullptr);
return true;
}
@@ -1331,13 +1335,27 @@ DEF_CONSOLE_CMD(ConGetSeed)
DEF_CONSOLE_CMD(ConGetDate)
{
if (argc == 0) {
IConsoleHelp("Returns the current date (day-month-year) of the game. Usage: 'getdate'");
IConsoleHelp("Returns the current date (year-month-day) of the game. Usage: 'getdate'");
return true;
}
YearMonthDay ymd;
ConvertDateToYMD(_date, &ymd);
IConsolePrintF(CC_DEFAULT, "Date: %d-%d-%d", ymd.day, ymd.month + 1, ymd.year);
IConsolePrintF(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;
}
time_t t;
time(&t);
auto timeinfo = localtime(&t);
IConsolePrintF(CC_DEFAULT, "System Date: %04d-%02d-%02d %02d:%02d:%02d", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
return true;
}
@@ -1354,7 +1372,7 @@ DEF_CONSOLE_CMD(ConAlias)
if (argc < 3) return false;
alias = IConsoleAliasGet(argv[1]);
if (alias == NULL) {
if (alias == nullptr) {
IConsoleAliasRegister(argv[1], argv[2]);
} else {
free(alias->cmdline);
@@ -1366,17 +1384,18 @@ DEF_CONSOLE_CMD(ConAlias)
DEF_CONSOLE_CMD(ConScreenShot)
{
if (argc == 0) {
IConsoleHelp("Create a screenshot of the game. Usage: 'screenshot [big | giant | no_con] [file name]'");
IConsoleHelp("Create a screenshot of the game. Usage: 'screenshot [big | giant | no_con | minimap] [file name]'");
IConsoleHelp("'big' makes a zoomed-in screenshot of the visible area, 'giant' makes a screenshot of the "
"whole map, 'no_con' hides the console to create the screenshot. 'big' or 'giant' "
"screenshots are always drawn without console");
"screenshots are always drawn without console. "
"'minimap' makes a top-viewed minimap screenshot of whole world which represents one tile by one pixel.");
return true;
}
if (argc > 3) return false;
ScreenshotType type = SC_VIEWPORT;
const char *name = NULL;
const char *name = nullptr;
if (argc > 1) {
if (strcmp(argv[1], "big") == 0) {
@@ -1387,6 +1406,10 @@ DEF_CONSOLE_CMD(ConScreenShot)
/* screenshot giant [filename] */
type = SC_WORLD;
if (argc > 2) name = argv[2];
} else if (strcmp(argv[1], "minimap") == 0) {
/* screenshot minimap [filename] */
type = SC_MINIMAP;
if (argc > 2) name = argv[2];
} else if (strcmp(argv[1], "no_con") == 0) {
/* screenshot no_con [filename] */
IConsoleClose();
@@ -1414,7 +1437,7 @@ DEF_CONSOLE_CMD(ConInfoCmd)
if (argc < 2) return false;
const IConsoleCmd *cmd = IConsoleCmdGet(argv[1]);
if (cmd == NULL) {
if (cmd == nullptr) {
IConsoleError("the given command was not found");
return true;
}
@@ -1422,7 +1445,7 @@ DEF_CONSOLE_CMD(ConInfoCmd)
IConsolePrintF(CC_DEFAULT, "command name: %s", cmd->name);
IConsolePrintF(CC_DEFAULT, "command proc: %p", cmd->proc);
if (cmd->hook != NULL) IConsoleWarning("command is hooked");
if (cmd->hook != nullptr) IConsoleWarning("command is hooked");
return true;
}
@@ -1480,16 +1503,16 @@ DEF_CONSOLE_CMD(ConHelp)
RemoveUnderscores(argv[1]);
cmd = IConsoleCmdGet(argv[1]);
if (cmd != NULL) {
cmd->proc(0, NULL);
if (cmd != nullptr) {
cmd->proc(0, nullptr);
return true;
}
alias = IConsoleAliasGet(argv[1]);
if (alias != NULL) {
if (alias != nullptr) {
cmd = IConsoleCmdGet(alias->cmdline);
if (cmd != NULL) {
cmd->proc(0, NULL);
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);
@@ -1519,9 +1542,9 @@ DEF_CONSOLE_CMD(ConListCommands)
return true;
}
for (const IConsoleCmd *cmd = _iconsole_cmds; cmd != NULL; cmd = cmd->next) {
if (argv[1] == NULL || strstr(cmd->name, argv[1]) != NULL) {
if (cmd->hook == NULL || cmd->hook(false) != CHR_HIDE) IConsolePrintF(CC_DEFAULT, "%s", cmd->name);
for (const IConsoleCmd *cmd = _iconsole_cmds; cmd != nullptr; cmd = cmd->next) {
if (argv[1] == nullptr || strstr(cmd->name, argv[1]) != nullptr) {
if (cmd->hook == nullptr || cmd->hook(false) != CHR_HIDE) IConsolePrintF(CC_DEFAULT, "%s", cmd->name);
}
}
@@ -1535,8 +1558,8 @@ DEF_CONSOLE_CMD(ConListAliases)
return true;
}
for (const IConsoleAlias *alias = _iconsole_aliases; alias != NULL; alias = alias->next) {
if (argv[1] == NULL || strstr(alias->name, argv[1]) != NULL) {
for (const IConsoleAlias *alias = _iconsole_aliases; alias != nullptr; alias = alias->next) {
if (argv[1] == nullptr || strstr(alias->name, argv[1]) != nullptr) {
IConsolePrintF(CC_DEFAULT, "%s => %s", alias->name, alias->cmdline);
}
}
@@ -1551,8 +1574,7 @@ DEF_CONSOLE_CMD(ConCompanies)
return true;
}
Company *c;
FOR_ALL_COMPANIES(c) {
for (const Company *c : Company::Iterate()) {
/* Grab the company name */
char company_name[512];
SetDParam(0, c->index);
@@ -1561,12 +1583,9 @@ DEF_CONSOLE_CMD(ConCompanies)
const char *password_state = "";
if (c->is_ai) {
password_state = "AI";
}
#ifdef ENABLE_NETWORK
else if (_network_server) {
} else if (_network_server) {
password_state = StrEmpty(_network_company_states[c->index].password) ? "unprotected" : "protected";
}
#endif
char colour[512];
GetString(colour, STR_COLOUR_DARK_BLUE + _company_colours[c->index], lastof(colour));
@@ -1583,8 +1602,6 @@ DEF_CONSOLE_CMD(ConCompanies)
return true;
}
#ifdef ENABLE_NETWORK
DEF_CONSOLE_CMD(ConSay)
{
if (argc == 0) {
@@ -1750,8 +1767,8 @@ static void OutputContentState(const ContentInfo *const ci)
DEF_CONSOLE_CMD(ConContent)
{
static ContentCallback *cb = NULL;
if (cb == NULL) {
static ContentCallback *cb = nullptr;
if (cb == nullptr) {
cb = new ConsoleContentCallback();
_network_content_client.AddCallback(cb);
}
@@ -1809,7 +1826,7 @@ DEF_CONSOLE_CMD(ConContent)
if (strcasecmp(argv[1], "state") == 0) {
IConsolePrintF(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, argv[2]) == NULL) continue;
if (argc > 2 && strcasestr((*iter)->name, argv[2]) == nullptr) continue;
OutputContentState(*iter);
}
return true;
@@ -1826,7 +1843,6 @@ DEF_CONSOLE_CMD(ConContent)
return false;
}
#endif /* defined(WITH_ZLIB) */
#endif /* ENABLE_NETWORK */
DEF_CONSOLE_CMD(ConSetting)
{
@@ -1875,7 +1891,7 @@ DEF_CONSOLE_CMD(ConListSettings)
if (argc > 2) return false;
IConsoleListSettings((argc == 2) ? argv[1] : NULL);
IConsoleListSettings((argc == 2) ? argv[1] : nullptr);
return true;
}
@@ -1896,6 +1912,135 @@ DEF_CONSOLE_CMD(ConNewGRFReload)
return true;
}
DEF_CONSOLE_CMD(ConNewGRFProfile)
{
if (argc == 0) {
IConsoleHelp("Collect performance data about NewGRF sprite requests and callbacks. Sub-commands can be abbreviated.");
IConsoleHelp("Usage: newgrf_profile [list]");
IConsoleHelp(" List all NewGRFs that can be profiled, and their status.");
IConsoleHelp("Usage: newgrf_profile select <grf-num>...");
IConsoleHelp(" Select one or more GRFs for profiling.");
IConsoleHelp("Usage: newgrf_profile unselect <grf-num>...");
IConsoleHelp(" Unselect one or more GRFs from profiling. Use the keyword \"all\" instead of a GRF number to unselect all. Removing an active profiler aborts data collection.");
IConsoleHelp("Usage: newgrf_profile start [<num-days>]");
IConsoleHelp(" Begin profiling all selected GRFs. If a number of days is provided, profiling stops after that many in-game days.");
IConsoleHelp("Usage: newgrf_profile stop");
IConsoleHelp(" End profiling and write the collected data to CSV files.");
IConsoleHelp("Usage: newgrf_profile abort");
IConsoleHelp(" End profiling and discard all collected data.");
return true;
}
extern const std::vector<GRFFile *> &GetAllGRFFiles();
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);
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
IConsolePrintF(CC_WARNING, "GRF number %d out of range, not added.", grfnum);
continue;
}
GRFFile *grf = files[grfnum - 1];
if (std::any_of(_newgrf_profilers.begin(), _newgrf_profilers.end(), [&](NewGRFProfiler &pr) { return pr.grffile == grf; })) {
IConsolePrintF(CC_WARNING, "GRF number %d [%08X] is already selected for profiling.", grfnum, BSWAP32(grf->grfid));
continue;
}
_newgrf_profilers.emplace_back(grf);
}
return true;
}
/* "unselect" sub-command */
if (strncasecmp(argv[1], "uns", 3) == 0 && argc >= 3) {
for (size_t argnum = 2; argnum < argc; ++argnum) {
if (strcasecmp(argv[argnum], "all") == 0) {
_newgrf_profilers.clear();
break;
}
int grfnum = atoi(argv[argnum]);
if (grfnum < 1 || grfnum > (int)files.size()) {
IConsolePrintF(CC_WARNING, "GRF number %d out of range, not removing.", grfnum);
continue;
}
GRFFile *grf = files[grfnum - 1];
auto pos = std::find_if(_newgrf_profilers.begin(), _newgrf_profilers.end(), [&](NewGRFProfiler &pr) { return pr.grffile == grf; });
if (pos != _newgrf_profilers.end()) _newgrf_profilers.erase(pos);
}
return true;
}
/* "start" sub-command */
if (strncasecmp(argv[1], "sta", 3) == 0) {
std::string grfids;
size_t started = 0;
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());
if (argc >= 3) {
int days = 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);
} else {
_newgrf_profile_end_date = MAX_DAY;
}
} else if (_newgrf_profilers.empty()) {
IConsolePrintF(CC_WARNING, "No GRFs selected for profiling, did not start.");
} else {
IConsolePrintF(CC_WARNING, "Did not start profiling for any GRFs, all selected GRFs are already profiling.");
}
return true;
}
/* "stop" sub-command */
if (strncasecmp(argv[1], "sto", 3) == 0) {
NewGRFProfiler::FinishAll();
return true;
}
/* "abort" sub-command */
if (strncasecmp(argv[1], "abo", 3) == 0) {
for (NewGRFProfiler &pr : _newgrf_profilers) {
pr.Abort();
}
_newgrf_profile_end_date = MAX_DAY;
return true;
}
return false;
}
#ifdef _DEBUG
/******************
* debug commands
@@ -1960,6 +2105,7 @@ void IConsoleStdLibRegister()
IConsoleCmdRegister("restart", ConRestart);
IConsoleCmdRegister("getseed", ConGetSeed);
IConsoleCmdRegister("getdate", ConGetDate);
IConsoleCmdRegister("getsysdate", ConGetSysDate);
IConsoleCmdRegister("quit", ConExit);
IConsoleCmdRegister("resetengines", ConResetEngines, ConHookNoNetwork);
IConsoleCmdRegister("reset_enginepool", ConResetEnginePool, ConHookNoNetwork);
@@ -2008,7 +2154,7 @@ void IConsoleStdLibRegister()
IConsoleAliasRegister("players", "companies");
/* networking functions */
#ifdef ENABLE_NETWORK
/* Content downloading is only available with ZLIB */
#if defined(WITH_ZLIB)
IConsoleCmdRegister("content", ConContent);
@@ -2066,7 +2212,6 @@ void IConsoleStdLibRegister()
IConsoleAliasRegister("restart_game_year", "setting restart_game_year %+");
IConsoleAliasRegister("min_players", "setting min_active_clients %+");
IConsoleAliasRegister("reload_cfg", "setting reload_cfg %+");
#endif /* ENABLE_NETWORK */
/* debugging stuff */
#ifdef _DEBUG
@@ -2077,4 +2222,5 @@ void IConsoleStdLibRegister()
/* NewGRF development stuff */
IConsoleCmdRegister("reload_newgrfs", ConNewGRFReload, ConHookNewGRFDeveloperTool);
IConsoleCmdRegister("newgrf_profile", ConNewGRFProfile, ConHookNewGRFDeveloperTool);
}