console_cmds.cpp

Go to the documentation of this file.
00001 /* $Id: console_cmds.cpp 23741 2012-01-03 21:47:01Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "console_internal.h"
00014 #include "debug.h"
00015 #include "engine_func.h"
00016 #include "landscape.h"
00017 #include "saveload/saveload.h"
00018 #include "network/network.h"
00019 #include "network/network_func.h"
00020 #include "network/network_base.h"
00021 #include "network/network_admin.h"
00022 #include "network/network_client.h"
00023 #include "command_func.h"
00024 #include "settings_func.h"
00025 #include "fios.h"
00026 #include "fileio_func.h"
00027 #include "screenshot.h"
00028 #include "genworld.h"
00029 #include "strings_func.h"
00030 #include "viewport_func.h"
00031 #include "window_func.h"
00032 #include "date_func.h"
00033 #include "company_func.h"
00034 #include "gamelog.h"
00035 #include "ai/ai.hpp"
00036 #include "ai/ai_config.hpp"
00037 #include "newgrf.h"
00038 #include "console_func.h"
00039 #include "engine_base.h"
00040 #include "game/game.hpp"
00041 
00042 #ifdef ENABLE_NETWORK
00043   #include "table/strings.h"
00044 #endif /* ENABLE_NETWORK */
00045 
00046 /* scriptfile handling */
00047 static bool _script_running; 
00048 
00049 /* console command defines */
00050 #define DEF_CONSOLE_CMD(function) static bool function(byte argc, char *argv[])
00051 #define DEF_CONSOLE_HOOK(function) static ConsoleHookResult function(bool echo)
00052 
00053 
00054 /****************
00055  * command hooks
00056  ****************/
00057 
00058 #ifdef ENABLE_NETWORK
00059 
00064 static inline bool NetworkAvailable(bool echo)
00065 {
00066   if (!_network_available) {
00067     if (echo) IConsoleError("You cannot use this command because there is no network available.");
00068     return false;
00069   }
00070   return true;
00071 }
00072 
00077 DEF_CONSOLE_HOOK(ConHookServerOnly)
00078 {
00079   if (!NetworkAvailable(echo)) return CHR_DISALLOW;
00080 
00081   if (!_network_server) {
00082     if (echo) IConsoleError("This command is only available to a network server.");
00083     return CHR_DISALLOW;
00084   }
00085   return CHR_ALLOW;
00086 }
00087 
00092 DEF_CONSOLE_HOOK(ConHookClientOnly)
00093 {
00094   if (!NetworkAvailable(echo)) return CHR_DISALLOW;
00095 
00096   if (_network_server) {
00097     if (echo) IConsoleError("This command is not available to a network server.");
00098     return CHR_DISALLOW;
00099   }
00100   return CHR_ALLOW;
00101 }
00102 
00107 DEF_CONSOLE_HOOK(ConHookNeedNetwork)
00108 {
00109   if (!NetworkAvailable(echo)) return CHR_DISALLOW;
00110 
00111   if (!_networking || (!_network_server && !MyClient::IsConnected())) {
00112     if (echo) IConsoleError("Not connected. This command is only available in multiplayer.");
00113     return CHR_DISALLOW;
00114   }
00115   return CHR_ALLOW;
00116 }
00117 
00122 DEF_CONSOLE_HOOK(ConHookNoNetwork)
00123 {
00124   if (_networking) {
00125     if (echo) IConsoleError("This command is forbidden in multiplayer.");
00126     return CHR_DISALLOW;
00127   }
00128   return CHR_ALLOW;
00129 }
00130 
00131 #else
00132 # define ConHookNoNetwork NULL
00133 #endif /* ENABLE_NETWORK */
00134 
00135 DEF_CONSOLE_HOOK(ConHookNewGRFDeveloperTool)
00136 {
00137   if (_settings_client.gui.newgrf_developer_tools) {
00138     if (_game_mode == GM_MENU) {
00139       if (echo) IConsoleError("This command is only available in game and editor.");
00140       return CHR_DISALLOW;
00141     }
00142 #ifdef ENABLE_NETWORK
00143     return ConHookNoNetwork(echo);
00144 #else
00145     return CHR_ALLOW;
00146 #endif
00147   }
00148   return CHR_HIDE;
00149 }
00150 
00155 static void IConsoleHelp(const char *str)
00156 {
00157   IConsolePrintF(CC_WARNING, "- %s", str);
00158 }
00159 
00164 DEF_CONSOLE_CMD(ConResetEngines)
00165 {
00166   if (argc == 0) {
00167     IConsoleHelp("Reset status data of all engines. This might solve some issues with 'lost' engines. Usage: 'resetengines'");
00168     return true;
00169   }
00170 
00171   StartupEngines();
00172   return true;
00173 }
00174 
00180 DEF_CONSOLE_CMD(ConResetEnginePool)
00181 {
00182   if (argc == 0) {
00183     IConsoleHelp("Reset NewGRF allocations of engine slots. This will remove invalid engine definitions, and might make default engines available again.");
00184     return true;
00185   }
00186 
00187   if (_game_mode == GM_MENU) {
00188     IConsoleError("This command is only available in game and editor.");
00189     return true;
00190   }
00191 
00192   if (!EngineOverrideManager::ResetToCurrentNewGRFConfig()) {
00193     IConsoleError("This can only be done when there are no vehicles in the game.");
00194     return true;
00195   }
00196 
00197   return true;
00198 }
00199 
00200 #ifdef _DEBUG
00201 
00206 DEF_CONSOLE_CMD(ConResetTile)
00207 {
00208   if (argc == 0) {
00209     IConsoleHelp("Reset a tile to bare land. Usage: 'resettile <tile>'");
00210     IConsoleHelp("Tile can be either decimal (34161) or hexadecimal (0x4a5B)");
00211     return true;
00212   }
00213 
00214   if (argc == 2) {
00215     uint32 result;
00216     if (GetArgumentInteger(&result, argv[1])) {
00217       DoClearSquare((TileIndex)result);
00218       return true;
00219     }
00220   }
00221 
00222   return false;
00223 }
00224 #endif /* _DEBUG */
00225 
00235 DEF_CONSOLE_CMD(ConScrollToTile)
00236 {
00237   switch (argc) {
00238     case 0:
00239       IConsoleHelp("Center the screen on a given tile.");
00240       IConsoleHelp("Usage: 'scrollto <tile>' or 'scrollto <x> <y>'");
00241       IConsoleHelp("Numbers can be either decimal (34161) or hexadecimal (0x4a5B).");
00242       return true;
00243 
00244     case 2: {
00245       uint32 result;
00246       if (GetArgumentInteger(&result, argv[1])) {
00247         if (result >= MapSize()) {
00248           IConsolePrint(CC_ERROR, "Tile does not exist");
00249           return true;
00250         }
00251         ScrollMainWindowToTile((TileIndex)result);
00252         return true;
00253       }
00254       break;
00255     }
00256 
00257     case 3: {
00258       uint32 x, y;
00259       if (GetArgumentInteger(&x, argv[1]) && GetArgumentInteger(&y, argv[2])) {
00260         if (x >= MapSizeX() || y >= MapSizeY()) {
00261           IConsolePrint(CC_ERROR, "Tile does not exist");
00262           return true;
00263         }
00264         ScrollMainWindowToTile(TileXY(x, y));
00265         return true;
00266       }
00267       break;
00268     }
00269   }
00270 
00271   return false;
00272 }
00273 
00279 DEF_CONSOLE_CMD(ConSave)
00280 {
00281   if (argc == 0) {
00282     IConsoleHelp("Save the current game. Usage: 'save <filename>'");
00283     return true;
00284   }
00285 
00286   if (argc == 2) {
00287     char *filename = str_fmt("%s.sav", argv[1]);
00288     IConsolePrint(CC_DEFAULT, "Saving map...");
00289 
00290     if (SaveOrLoad(filename, SL_SAVE, SAVE_DIR) != SL_OK) {
00291       IConsolePrint(CC_ERROR, "Saving map failed");
00292     } else {
00293       IConsolePrintF(CC_DEFAULT, "Map successfully saved to %s", filename);
00294     }
00295     free(filename);
00296     return true;
00297   }
00298 
00299   return false;
00300 }
00301 
00306 DEF_CONSOLE_CMD(ConSaveConfig)
00307 {
00308   if (argc == 0) {
00309     IConsoleHelp("Saves the configuration for new games to the configuration file, typically 'openttd.cfg'.");
00310     IConsoleHelp("It does not save the configuration of the current game to the configuration file.");
00311     return true;
00312   }
00313 
00314   SaveToConfig();
00315   IConsolePrint(CC_DEFAULT, "Saved config.");
00316   return true;
00317 }
00318 
00325 static const FiosItem *GetFiosItem(const char *file)
00326 {
00327   _saveload_mode = SLD_LOAD_GAME;
00328   BuildFileList();
00329 
00330   for (const FiosItem *item = _fios_items.Begin(); item != _fios_items.End(); item++) {
00331     if (strcmp(file, item->name) == 0) return item;
00332     if (strcmp(file, item->title) == 0) return item;
00333   }
00334 
00335   /* If no name matches, try to parse it as number */
00336   char *endptr;
00337   int i = strtol(file, &endptr, 10);
00338   if (file == endptr || *endptr != '\0') i = -1;
00339 
00340   if (IsInsideMM(i, 0, _fios_items.Length())) return _fios_items.Get(i);
00341 
00342   /* As a last effort assume it is an OpenTTD savegame and
00343    * that the ".sav" part was not given. */
00344   char long_file[MAX_PATH];
00345   seprintf(long_file, lastof(long_file), "%s.sav", file);
00346   for (const FiosItem *item = _fios_items.Begin(); item != _fios_items.End(); item++) {
00347     if (strcmp(long_file, item->name) == 0) return item;
00348     if (strcmp(long_file, item->title) == 0) return item;
00349   }
00350 
00351   return NULL;
00352 }
00353 
00354 
00355 DEF_CONSOLE_CMD(ConLoad)
00356 {
00357   if (argc == 0) {
00358     IConsoleHelp("Load a game by name or index. Usage: 'load <file | number>'");
00359     return true;
00360   }
00361 
00362   if (argc != 2) return false;
00363 
00364   const char *file = argv[1];
00365   const FiosItem *item = GetFiosItem(file);
00366   if (item != NULL) {
00367     switch (item->type) {
00368       case FIOS_TYPE_FILE: case FIOS_TYPE_OLDFILE: {
00369         _switch_mode = SM_LOAD_GAME;
00370         SetFiosType(item->type);
00371 
00372         strecpy(_file_to_saveload.name, FiosBrowseTo(item), lastof(_file_to_saveload.name));
00373         strecpy(_file_to_saveload.title, item->title, lastof(_file_to_saveload.title));
00374         break;
00375       }
00376       default: IConsolePrintF(CC_ERROR, "%s: Not a savegame.", file);
00377     }
00378   } else {
00379     IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
00380   }
00381 
00382   FiosFreeSavegameList();
00383   return true;
00384 }
00385 
00386 
00387 DEF_CONSOLE_CMD(ConRemove)
00388 {
00389   if (argc == 0) {
00390     IConsoleHelp("Remove a savegame by name or index. Usage: 'rm <file | number>'");
00391     return true;
00392   }
00393 
00394   if (argc != 2) return false;
00395 
00396   const char *file = argv[1];
00397   const FiosItem *item = GetFiosItem(file);
00398   if (item != NULL) {
00399     if (!FiosDelete(item->name)) {
00400       IConsolePrintF(CC_ERROR, "%s: Failed to delete file", file);
00401     }
00402   } else {
00403     IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
00404   }
00405 
00406   FiosFreeSavegameList();
00407   return true;
00408 }
00409 
00410 
00411 /* List all the files in the current dir via console */
00412 DEF_CONSOLE_CMD(ConListFiles)
00413 {
00414   if (argc == 0) {
00415     IConsoleHelp("List all loadable savegames and directories in the current dir via console. Usage: 'ls | dir'");
00416     return true;
00417   }
00418 
00419   BuildFileList();
00420 
00421   for (uint i = 0; i < _fios_items.Length(); i++) {
00422     IConsolePrintF(CC_DEFAULT, "%d) %s", i, _fios_items[i].title);
00423   }
00424 
00425   FiosFreeSavegameList();
00426   return true;
00427 }
00428 
00429 /* Change the dir via console */
00430 DEF_CONSOLE_CMD(ConChangeDirectory)
00431 {
00432   if (argc == 0) {
00433     IConsoleHelp("Change the dir via console. Usage: 'cd <directory | number>'");
00434     return true;
00435   }
00436 
00437   if (argc != 2) return false;
00438 
00439   const char *file = argv[1];
00440   const FiosItem *item = GetFiosItem(file);
00441   if (item != NULL) {
00442     switch (item->type) {
00443       case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT:
00444         FiosBrowseTo(item);
00445         break;
00446       default: IConsolePrintF(CC_ERROR, "%s: Not a directory.", file);
00447     }
00448   } else {
00449     IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file);
00450   }
00451 
00452   FiosFreeSavegameList();
00453   return true;
00454 }
00455 
00456 DEF_CONSOLE_CMD(ConPrintWorkingDirectory)
00457 {
00458   const char *path;
00459 
00460   if (argc == 0) {
00461     IConsoleHelp("Print out the current working directory. Usage: 'pwd'");
00462     return true;
00463   }
00464 
00465   /* XXX - Workaround for broken file handling */
00466   FiosGetSavegameList(SLD_LOAD_GAME);
00467   FiosFreeSavegameList();
00468 
00469   FiosGetDescText(&path, NULL);
00470   IConsolePrint(CC_DEFAULT, path);
00471   return true;
00472 }
00473 
00474 DEF_CONSOLE_CMD(ConClearBuffer)
00475 {
00476   if (argc == 0) {
00477     IConsoleHelp("Clear the console buffer. Usage: 'clear'");
00478     return true;
00479   }
00480 
00481   IConsoleClearBuffer();
00482   SetWindowDirty(WC_CONSOLE, 0);
00483   return true;
00484 }
00485 
00486 
00487 /**********************************
00488  * Network Core Console Commands
00489  **********************************/
00490 #ifdef ENABLE_NETWORK
00491 
00492 static bool ConKickOrBan(const char *argv, bool ban)
00493 {
00494   uint n;
00495 
00496   if (strchr(argv, '.') == NULL && strchr(argv, ':') == NULL) { // banning with ID
00497     ClientID client_id = (ClientID)atoi(argv);
00498 
00499     /* Don't kill the server, or the client doing the rcon. The latter can't be kicked because
00500      * kicking frees closes and subsequently free the connection related instances, which we
00501      * would be reading from and writing to after returning. So we would read or write data
00502      * from freed memory up till the segfault triggers. */
00503     if (client_id == CLIENT_ID_SERVER || client_id == _redirect_console_to_client) {
00504       IConsolePrintF(CC_ERROR, "ERROR: Silly boy, you can not %s yourself!", ban ? "ban" : "kick");
00505       return true;
00506     }
00507 
00508     NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
00509     if (ci == NULL) {
00510       IConsoleError("Invalid client");
00511       return true;
00512     }
00513 
00514     if (!ban) {
00515       /* Kick only this client, not all clients with that IP */
00516       NetworkServerKickClient(client_id);
00517       return true;
00518     }
00519 
00520     /* When banning, kick+ban all clients with that IP */
00521     n = NetworkServerKickOrBanIP(client_id, ban);
00522   } else {
00523     n = NetworkServerKickOrBanIP(argv, ban);
00524   }
00525 
00526   if (n == 0) {
00527     IConsolePrint(CC_DEFAULT, ban ? "Client not online, address added to banlist" : "Client not found");
00528   } else {
00529     IConsolePrintF(CC_DEFAULT, "%sed %u client(s)", ban ? "Bann" : "Kick", n);
00530   }
00531 
00532   return true;
00533 }
00534 
00535 DEF_CONSOLE_CMD(ConKick)
00536 {
00537   if (argc == 0) {
00538     IConsoleHelp("Kick a client from a network game. Usage: 'kick <ip | client-id>'");
00539     IConsoleHelp("For client-id's, see the command 'clients'");
00540     return true;
00541   }
00542 
00543   if (argc != 2) return false;
00544 
00545   return ConKickOrBan(argv[1], false);
00546 }
00547 
00548 DEF_CONSOLE_CMD(ConBan)
00549 {
00550   if (argc == 0) {
00551     IConsoleHelp("Ban a client from a network game. Usage: 'ban <ip | client-id>'");
00552     IConsoleHelp("For client-id's, see the command 'clients'");
00553     IConsoleHelp("If the client is no longer online, you can still ban his/her IP");
00554     return true;
00555   }
00556 
00557   if (argc != 2) return false;
00558 
00559   return ConKickOrBan(argv[1], true);
00560 }
00561 
00562 DEF_CONSOLE_CMD(ConUnBan)
00563 {
00564 
00565   if (argc == 0) {
00566     IConsoleHelp("Unban a client from a network game. Usage: 'unban <ip | client-id>'");
00567     IConsoleHelp("For a list of banned IP's, see the command 'banlist'");
00568     return true;
00569   }
00570 
00571   if (argc != 2) return false;
00572 
00573   uint index = (strchr(argv[1], '.') == NULL) ? atoi(argv[1]) : 0;
00574   index--;
00575   uint i = 0;
00576 
00577   for (char **iter = _network_ban_list.Begin(); iter != _network_ban_list.End(); iter++, i++) {
00578     if (strcmp(_network_ban_list[i], argv[1]) == 0 || index == i) {
00579       free(_network_ban_list[i]);
00580       _network_ban_list.Erase(iter);
00581       IConsolePrint(CC_DEFAULT, "IP unbanned.");
00582       return true;
00583     }
00584   }
00585 
00586   IConsolePrint(CC_DEFAULT, "IP not in ban-list.");
00587   return true;
00588 }
00589 
00590 DEF_CONSOLE_CMD(ConBanList)
00591 {
00592   if (argc == 0) {
00593     IConsoleHelp("List the IP's of banned clients: Usage 'banlist'");
00594     return true;
00595   }
00596 
00597   IConsolePrint(CC_DEFAULT, "Banlist: ");
00598 
00599   uint i = 1;
00600   for (char **iter = _network_ban_list.Begin(); iter != _network_ban_list.End(); iter++, i++) {
00601     IConsolePrintF(CC_DEFAULT, "  %d) %s", i, *iter);
00602   }
00603 
00604   return true;
00605 }
00606 
00607 DEF_CONSOLE_CMD(ConPauseGame)
00608 {
00609   if (argc == 0) {
00610     IConsoleHelp("Pause a network game. Usage: 'pause'");
00611     return true;
00612   }
00613 
00614   if ((_pause_mode & PM_PAUSED_NORMAL) == PM_UNPAUSED) {
00615     DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE);
00616     if (!_networking) IConsolePrint(CC_DEFAULT, "Game paused.");
00617   } else {
00618     IConsolePrint(CC_DEFAULT, "Game is already paused.");
00619   }
00620 
00621   return true;
00622 }
00623 
00624 DEF_CONSOLE_CMD(ConUnpauseGame)
00625 {
00626   if (argc == 0) {
00627     IConsoleHelp("Unpause a network game. Usage: 'unpause'");
00628     return true;
00629   }
00630 
00631   if ((_pause_mode & PM_PAUSED_NORMAL) != PM_UNPAUSED) {
00632     DoCommandP(0, PM_PAUSED_NORMAL, 0, CMD_PAUSE);
00633     if (!_networking) IConsolePrint(CC_DEFAULT, "Game unpaused.");
00634   } else if ((_pause_mode & PM_PAUSED_ERROR) != PM_UNPAUSED) {
00635     IConsolePrint(CC_DEFAULT, "Game is in error state and cannot be unpaused via console.");
00636   } else if (_pause_mode != PM_UNPAUSED) {
00637     IConsolePrint(CC_DEFAULT, "Game cannot be unpaused manually; disable pause_on_join/min_active_clients.");
00638   } else {
00639     IConsolePrint(CC_DEFAULT, "Game is already unpaused.");
00640   }
00641 
00642   return true;
00643 }
00644 
00645 DEF_CONSOLE_CMD(ConRcon)
00646 {
00647   if (argc == 0) {
00648     IConsoleHelp("Remote control the server from another client. Usage: 'rcon <password> <command>'");
00649     IConsoleHelp("Remember to enclose the command in quotes, otherwise only the first parameter is sent");
00650     return true;
00651   }
00652 
00653   if (argc < 3) return false;
00654 
00655   if (_network_server) {
00656     IConsoleCmdExec(argv[2]);
00657   } else {
00658     NetworkClientSendRcon(argv[1], argv[2]);
00659   }
00660   return true;
00661 }
00662 
00663 DEF_CONSOLE_CMD(ConStatus)
00664 {
00665   if (argc == 0) {
00666     IConsoleHelp("List the status of all clients connected to the server. Usage 'status'");
00667     return true;
00668   }
00669 
00670   NetworkServerShowStatusToConsole();
00671   return true;
00672 }
00673 
00674 DEF_CONSOLE_CMD(ConServerInfo)
00675 {
00676   if (argc == 0) {
00677     IConsoleHelp("List current and maximum client/company limits. Usage 'server_info'");
00678     IConsoleHelp("You can change these values by modifying settings 'network.max_clients', 'network.max_companies' and 'network.max_spectators'");
00679     return true;
00680   }
00681 
00682   IConsolePrintF(CC_DEFAULT, "Current/maximum clients:    %2d/%2d", _network_game_info.clients_on, _settings_client.network.max_clients);
00683   IConsolePrintF(CC_DEFAULT, "Current/maximum companies:  %2d/%2d", (int)Company::GetNumItems(), _settings_client.network.max_companies);
00684   IConsolePrintF(CC_DEFAULT, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), _settings_client.network.max_spectators);
00685 
00686   return true;
00687 }
00688 
00689 DEF_CONSOLE_CMD(ConClientNickChange)
00690 {
00691   if (argc != 3) {
00692     IConsoleHelp("Change the nickname of a connected client. Usage: 'client_name <client-id> <new-name>'");
00693     IConsoleHelp("For client-id's, see the command 'clients'");
00694     return true;
00695   }
00696 
00697   ClientID client_id = (ClientID)atoi(argv[1]);
00698 
00699   if (client_id == CLIENT_ID_SERVER) {
00700     IConsoleError("Please use the command 'name' to change your own name!");
00701     return true;
00702   }
00703 
00704   if (NetworkClientInfo::GetByClientID(client_id) == NULL) {
00705     IConsoleError("Invalid client");
00706     return true;
00707   }
00708 
00709   if (!NetworkServerChangeClientName(client_id, argv[2])) {
00710     IConsoleError("Cannot give a client a duplicate name");
00711   }
00712 
00713   return true;
00714 }
00715 
00716 DEF_CONSOLE_CMD(ConJoinCompany)
00717 {
00718   if (argc < 2) {
00719     IConsoleHelp("Request joining another company. Usage: join <company-id> [<password>]");
00720     IConsoleHelp("For valid company-id see company list, use 255 for spectator");
00721     return true;
00722   }
00723 
00724   CompanyID company_id = (CompanyID)(atoi(argv[1]) <= MAX_COMPANIES ? atoi(argv[1]) - 1 : atoi(argv[1]));
00725 
00726   /* Check we have a valid company id! */
00727   if (!Company::IsValidID(company_id) && company_id != COMPANY_SPECTATOR) {
00728     IConsolePrintF(CC_ERROR, "Company does not exist. Company-id must be between 1 and %d.", MAX_COMPANIES);
00729     return true;
00730   }
00731 
00732   if (NetworkClientInfo::GetByClientID(_network_own_client_id)->client_playas == company_id) {
00733     IConsoleError("You are already there!");
00734     return true;
00735   }
00736 
00737   if (company_id == COMPANY_SPECTATOR && NetworkMaxSpectatorsReached()) {
00738     IConsoleError("Cannot join spectators, maximum number of spectators reached.");
00739     return true;
00740   }
00741 
00742   if (company_id != COMPANY_SPECTATOR && !Company::IsHumanID(company_id)) {
00743     IConsoleError("Cannot join AI company.");
00744     return true;
00745   }
00746 
00747   /* Check if the company requires a password */
00748   if (NetworkCompanyIsPassworded(company_id) && argc < 3) {
00749     IConsolePrintF(CC_ERROR, "Company %d requires a password to join.", company_id + 1);
00750     return true;
00751   }
00752 
00753   /* non-dedicated server may just do the move! */
00754   if (_network_server) {
00755     NetworkServerDoMove(CLIENT_ID_SERVER, company_id);
00756   } else {
00757     NetworkClientRequestMove(company_id, NetworkCompanyIsPassworded(company_id) ? argv[2] : "");
00758   }
00759 
00760   return true;
00761 }
00762 
00763 DEF_CONSOLE_CMD(ConMoveClient)
00764 {
00765   if (argc < 3) {
00766     IConsoleHelp("Move a client to another company. Usage: move <client-id> <company-id>");
00767     IConsoleHelp("For valid client-id see 'clients', for valid company-id see 'companies', use 255 for moving to spectators");
00768     return true;
00769   }
00770 
00771   const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID((ClientID)atoi(argv[1]));
00772   CompanyID company_id = (CompanyID)(atoi(argv[2]) <= MAX_COMPANIES ? atoi(argv[2]) - 1 : atoi(argv[2]));
00773 
00774   /* check the client exists */
00775   if (ci == NULL) {
00776     IConsoleError("Invalid client-id, check the command 'clients' for valid client-id's.");
00777     return true;
00778   }
00779 
00780   if (!Company::IsValidID(company_id) && company_id != COMPANY_SPECTATOR) {
00781     IConsolePrintF(CC_ERROR, "Company does not exist. Company-id must be between 1 and %d.", MAX_COMPANIES);
00782     return true;
00783   }
00784 
00785   if (company_id != COMPANY_SPECTATOR && !Company::IsHumanID(company_id)) {
00786     IConsoleError("You cannot move clients to AI companies.");
00787     return true;
00788   }
00789 
00790   if (ci->client_id == CLIENT_ID_SERVER && _network_dedicated) {
00791     IConsoleError("Silly boy, you cannot move the server!");
00792     return true;
00793   }
00794 
00795   if (ci->client_playas == company_id) {
00796     IConsoleError("You cannot move someone to where he/she already is!");
00797     return true;
00798   }
00799 
00800   /* we are the server, so force the update */
00801   NetworkServerDoMove(ci->client_id, company_id);
00802 
00803   return true;
00804 }
00805 
00806 DEF_CONSOLE_CMD(ConResetCompany)
00807 {
00808   if (argc == 0) {
00809     IConsoleHelp("Remove an idle company from the game. Usage: 'reset_company <company-id>'");
00810     IConsoleHelp("For company-id's, see the list of companies from the dropdown menu. Company 1 is 1, etc.");
00811     return true;
00812   }
00813 
00814   if (argc != 2) return false;
00815 
00816   CompanyID index = (CompanyID)(atoi(argv[1]) - 1);
00817 
00818   /* Check valid range */
00819   if (!Company::IsValidID(index)) {
00820     IConsolePrintF(CC_ERROR, "Company does not exist. Company-id must be between 1 and %d.", MAX_COMPANIES);
00821     return true;
00822   }
00823 
00824   if (!Company::IsHumanID(index)) {
00825     IConsoleError("Company is owned by an AI.");
00826     return true;
00827   }
00828 
00829   if (NetworkCompanyHasClients(index)) {
00830     IConsoleError("Cannot remove company: a client is connected to that company.");
00831     return false;
00832   }
00833   const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
00834   if (ci->client_playas == index) {
00835     IConsoleError("Cannot remove company: the server is connected to that company.");
00836     return true;
00837   }
00838 
00839   /* It is safe to remove this company */
00840   DoCommandP(0, 2 | index << 16, CRR_MANUAL, CMD_COMPANY_CTRL);
00841   IConsolePrint(CC_DEFAULT, "Company deleted.");
00842 
00843   return true;
00844 }
00845 
00846 DEF_CONSOLE_CMD(ConNetworkClients)
00847 {
00848   if (argc == 0) {
00849     IConsoleHelp("Get a list of connected clients including their ID, name, company-id, and IP. Usage: 'clients'");
00850     return true;
00851   }
00852 
00853   NetworkPrintClients();
00854 
00855   return true;
00856 }
00857 
00858 DEF_CONSOLE_CMD(ConNetworkReconnect)
00859 {
00860   if (argc == 0) {
00861     IConsoleHelp("Reconnect to server to which you were connected last time. Usage: 'reconnect [<company>]'");
00862     IConsoleHelp("Company 255 is spectator (default, if not specified), 0 means creating new company.");
00863     IConsoleHelp("All others are a certain company with Company 1 being #1");
00864     return true;
00865   }
00866 
00867   CompanyID playas = (argc >= 2) ? (CompanyID)atoi(argv[1]) : COMPANY_SPECTATOR;
00868   switch (playas) {
00869     case 0: playas = COMPANY_NEW_COMPANY; break;
00870     case COMPANY_SPECTATOR: /* nothing to do */ break;
00871     default:
00872       /* From a user pov 0 is a new company, internally it's different and all
00873        * companies are offset by one to ease up on users (eg companies 1-8 not 0-7) */
00874       playas--;
00875       if (playas < COMPANY_FIRST || playas >= MAX_COMPANIES) return false;
00876       break;
00877   }
00878 
00879   if (StrEmpty(_settings_client.network.last_host)) {
00880     IConsolePrint(CC_DEFAULT, "No server for reconnecting.");
00881     return true;
00882   }
00883 
00884   /* Don't resolve the address first, just print it directly as it comes from the config file. */
00885   IConsolePrintF(CC_DEFAULT, "Reconnecting to %s:%d...", _settings_client.network.last_host, _settings_client.network.last_port);
00886 
00887   NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), playas);
00888   return true;
00889 }
00890 
00891 DEF_CONSOLE_CMD(ConNetworkConnect)
00892 {
00893   if (argc == 0) {
00894     IConsoleHelp("Connect to a remote OTTD server and join the game. Usage: 'connect <ip>'");
00895     IConsoleHelp("IP can contain port and company: 'IP[:Port][#Company]', eg: 'server.ottd.org:443#2'");
00896     IConsoleHelp("Company #255 is spectator all others are a certain company with Company 1 being #1");
00897     return true;
00898   }
00899 
00900   if (argc < 2) return false;
00901   if (_networking) NetworkDisconnect(); // we are in network-mode, first close it!
00902 
00903   const char *port = NULL;
00904   const char *company = NULL;
00905   char *ip = argv[1];
00906   /* Default settings: default port and new company */
00907   uint16 rport = NETWORK_DEFAULT_PORT;
00908   CompanyID join_as = COMPANY_NEW_COMPANY;
00909 
00910   ParseConnectionString(&company, &port, ip);
00911 
00912   IConsolePrintF(CC_DEFAULT, "Connecting to %s...", ip);
00913   if (company != NULL) {
00914     join_as = (CompanyID)atoi(company);
00915     IConsolePrintF(CC_DEFAULT, "    company-no: %d", join_as);
00916 
00917     /* From a user pov 0 is a new company, internally it's different and all
00918      * companies are offset by one to ease up on users (eg companies 1-8 not 0-7) */
00919     if (join_as != COMPANY_SPECTATOR) {
00920       if (join_as > MAX_COMPANIES) return false;
00921       join_as--;
00922     }
00923   }
00924   if (port != NULL) {
00925     rport = atoi(port);
00926     IConsolePrintF(CC_DEFAULT, "    port: %s", port);
00927   }
00928 
00929   NetworkClientConnectGame(NetworkAddress(ip, rport), join_as);
00930 
00931   return true;
00932 }
00933 
00934 #endif /* ENABLE_NETWORK */
00935 
00936 /*********************************
00937  *  script file console commands
00938  *********************************/
00939 
00940 DEF_CONSOLE_CMD(ConExec)
00941 {
00942   if (argc == 0) {
00943     IConsoleHelp("Execute a local script file. Usage: 'exec <script> <?>'");
00944     return true;
00945   }
00946 
00947   if (argc < 2) return false;
00948 
00949   FILE *script_file = FioFOpenFile(argv[1], "r", BASE_DIR);
00950 
00951   if (script_file == NULL) {
00952     if (argc == 2 || atoi(argv[2]) != 0) IConsoleError("script file not found");
00953     return true;
00954   }
00955 
00956   _script_running = true;
00957 
00958   char cmdline[ICON_CMDLN_SIZE];
00959   while (_script_running && fgets(cmdline, sizeof(cmdline), script_file) != NULL) {
00960     /* Remove newline characters from the executing script */
00961     for (char *cmdptr = cmdline; *cmdptr != '\0'; cmdptr++) {
00962       if (*cmdptr == '\n' || *cmdptr == '\r') {
00963         *cmdptr = '\0';
00964         break;
00965       }
00966     }
00967     IConsoleCmdExec(cmdline);
00968   }
00969 
00970   if (ferror(script_file)) {
00971     IConsoleError("Encountered errror while trying to read from script file");
00972   }
00973 
00974   _script_running = false;
00975   FioFCloseFile(script_file);
00976   return true;
00977 }
00978 
00979 DEF_CONSOLE_CMD(ConReturn)
00980 {
00981   if (argc == 0) {
00982     IConsoleHelp("Stop executing a running script. Usage: 'return'");
00983     return true;
00984   }
00985 
00986   _script_running = false;
00987   return true;
00988 }
00989 
00990 /*****************************
00991  *  default console commands
00992  ******************************/
00993 extern bool CloseConsoleLogIfActive();
00994 
00995 DEF_CONSOLE_CMD(ConScript)
00996 {
00997   extern FILE *_iconsole_output_file;
00998 
00999   if (argc == 0) {
01000     IConsoleHelp("Start or stop logging console output to a file. Usage: 'script <filename>'");
01001     IConsoleHelp("If filename is omitted, a running log is stopped if it is active");
01002     return true;
01003   }
01004 
01005   if (!CloseConsoleLogIfActive()) {
01006     if (argc < 2) return false;
01007 
01008     IConsolePrintF(CC_DEFAULT, "file output started to: %s", argv[1]);
01009     _iconsole_output_file = fopen(argv[1], "ab");
01010     if (_iconsole_output_file == NULL) IConsoleError("could not open file");
01011   }
01012 
01013   return true;
01014 }
01015 
01016 
01017 DEF_CONSOLE_CMD(ConEcho)
01018 {
01019   if (argc == 0) {
01020     IConsoleHelp("Print back the first argument to the console. Usage: 'echo <arg>'");
01021     return true;
01022   }
01023 
01024   if (argc < 2) return false;
01025   IConsolePrint(CC_DEFAULT, argv[1]);
01026   return true;
01027 }
01028 
01029 DEF_CONSOLE_CMD(ConEchoC)
01030 {
01031   if (argc == 0) {
01032     IConsoleHelp("Print back the first argument to the console in a given colour. Usage: 'echoc <colour> <arg2>'");
01033     return true;
01034   }
01035 
01036   if (argc < 3) return false;
01037   IConsolePrint((TextColour)Clamp(atoi(argv[1]), TC_BEGIN, TC_END - 1), argv[2]);
01038   return true;
01039 }
01040 
01041 DEF_CONSOLE_CMD(ConNewGame)
01042 {
01043   if (argc == 0) {
01044     IConsoleHelp("Start a new game. Usage: 'newgame [seed]'");
01045     IConsoleHelp("The server can force a new game using 'newgame'; any client joined will rejoin after the server is done generating the new game.");
01046     return true;
01047   }
01048 
01049   StartNewGameWithoutGUI((argc == 2) ? strtoul(argv[1], NULL, 10) : GENERATE_NEW_SEED);
01050   return true;
01051 }
01052 
01053 DEF_CONSOLE_CMD(ConRestart)
01054 {
01055   if (argc == 0) {
01056     IConsoleHelp("Restart game. Usage: 'restart'");
01057     IConsoleHelp("Restarts a game. It tries to reproduce the exact same map as the game started with.");
01058     IConsoleHelp("However:");
01059     IConsoleHelp(" * restarting games started in another version might create another map due to difference in map generation");
01060     IConsoleHelp(" * restarting games based on scenarios, loaded games or heightmaps will start a new game based on the settings stored in the scenario/savegame");
01061     return true;
01062   }
01063 
01064   /* Don't copy the _newgame pointers to the real pointers, so call SwitchToMode directly */
01065   _settings_game.game_creation.map_x = MapLogX();
01066   _settings_game.game_creation.map_y = FindFirstBit(MapSizeY());
01067   _switch_mode = SM_RESTARTGAME;
01068   return true;
01069 }
01070 
01076 static void PrintLineByLine(char *buf)
01077 {
01078   char *p = buf;
01079   /* Print output line by line */
01080   for (char *p2 = buf; *p2 != '\0'; p2++) {
01081     if (*p2 == '\n') {
01082       *p2 = '\0';
01083       IConsolePrintF(CC_DEFAULT, "%s", p);
01084       p = p2 + 1;
01085     }
01086   }
01087 }
01088 
01089 DEF_CONSOLE_CMD(ConListAILibs)
01090 {
01091   char buf[4096];
01092   AI::GetConsoleLibraryList(buf, lastof(buf));
01093 
01094   PrintLineByLine(buf);
01095 
01096   return true;
01097 }
01098 
01099 DEF_CONSOLE_CMD(ConListAI)
01100 {
01101   char buf[4096];
01102   AI::GetConsoleList(buf, lastof(buf));
01103 
01104   PrintLineByLine(buf);
01105 
01106   return true;
01107 }
01108 
01109 DEF_CONSOLE_CMD(ConListGameLibs)
01110 {
01111   char buf[4096];
01112   Game::GetConsoleLibraryList(buf, lastof(buf));
01113 
01114   PrintLineByLine(buf);
01115 
01116   return true;
01117 }
01118 
01119 DEF_CONSOLE_CMD(ConListGame)
01120 {
01121   char buf[4096];
01122   Game::GetConsoleList(buf, lastof(buf));
01123 
01124   PrintLineByLine(buf);
01125 
01126   return true;
01127 }
01128 
01129 DEF_CONSOLE_CMD(ConStartAI)
01130 {
01131   if (argc == 0 || argc > 3) {
01132     IConsoleHelp("Start a new AI. Usage: 'start_ai [<AI>] [<settings>]'");
01133     IConsoleHelp("Start a new AI. If <AI> is given, it starts that specific AI (if found).");
01134     IConsoleHelp("If <settings> is given, it is parsed and the AI settings are set to that.");
01135     return true;
01136   }
01137 
01138   if (_game_mode != GM_NORMAL) {
01139     IConsoleWarning("AIs can only be managed in a game.");
01140     return true;
01141   }
01142 
01143   if (Company::GetNumItems() == CompanyPool::MAX_SIZE) {
01144     IConsoleWarning("Can't start a new AI (no more free slots).");
01145     return true;
01146   }
01147   if (_networking && !_network_server) {
01148     IConsoleWarning("Only the server can start a new AI.");
01149     return true;
01150   }
01151   if (_networking && !_settings_game.ai.ai_in_multiplayer) {
01152     IConsoleWarning("AIs are not allowed in multiplayer by configuration.");
01153     IConsoleWarning("Switch AI -> AI in multiplayer to True.");
01154     return true;
01155   }
01156   if (!AI::CanStartNew()) {
01157     IConsoleWarning("Can't start a new AI.");
01158     return true;
01159   }
01160 
01161   int n = 0;
01162   Company *c;
01163   /* Find the next free slot */
01164   FOR_ALL_COMPANIES(c) {
01165     if (c->index != n) break;
01166     n++;
01167   }
01168 
01169   AIConfig *config = AIConfig::GetConfig((CompanyID)n);
01170   if (argc >= 2) {
01171     config->Change(argv[1], -1, true);
01172     if (!config->HasScript()) {
01173       IConsoleWarning("Failed to load the specified AI");
01174       return true;
01175     }
01176     if (argc == 3) {
01177       config->StringToSettings(argv[2]);
01178     }
01179   }
01180 
01181   /* Start a new AI company */
01182   DoCommandP(0, 1 | INVALID_COMPANY << 16, 0, CMD_COMPANY_CTRL);
01183 
01184   return true;
01185 }
01186 
01187 DEF_CONSOLE_CMD(ConReloadAI)
01188 {
01189   if (argc != 2) {
01190     IConsoleHelp("Reload an AI. Usage: 'reload_ai <company-id>'");
01191     IConsoleHelp("Reload the AI with the given company id. For company-id's, see the list of companies from the dropdown menu. Company 1 is 1, etc.");
01192     return true;
01193   }
01194 
01195   if (_game_mode != GM_NORMAL) {
01196     IConsoleWarning("AIs can only be managed in a game.");
01197     return true;
01198   }
01199 
01200   if (_networking && !_network_server) {
01201     IConsoleWarning("Only the server can reload an AI.");
01202     return true;
01203   }
01204 
01205   CompanyID company_id = (CompanyID)(atoi(argv[1]) - 1);
01206   if (!Company::IsValidID(company_id)) {
01207     IConsolePrintF(CC_DEFAULT, "Unknown company. Company range is between 1 and %d.", MAX_COMPANIES);
01208     return true;
01209   }
01210 
01211   if (Company::IsHumanID(company_id)) {
01212     IConsoleWarning("Company is not controlled by an AI.");
01213     return true;
01214   }
01215 
01216   /* First kill the company of the AI, then start a new one. This should start the current AI again */
01217   DoCommandP(0, 2 | company_id << 16, CRR_MANUAL, CMD_COMPANY_CTRL);
01218   DoCommandP(0, 1 | company_id << 16, 0, CMD_COMPANY_CTRL);
01219   IConsolePrint(CC_DEFAULT, "AI reloaded.");
01220 
01221   return true;
01222 }
01223 
01224 DEF_CONSOLE_CMD(ConStopAI)
01225 {
01226   if (argc != 2) {
01227     IConsoleHelp("Stop an AI. Usage: 'stop_ai <company-id>'");
01228     IConsoleHelp("Stop the AI with the given company id. For company-id's, see the list of companies from the dropdown menu. Company 1 is 1, etc.");
01229     return true;
01230   }
01231 
01232   if (_game_mode != GM_NORMAL) {
01233     IConsoleWarning("AIs can only be managed in a game.");
01234     return true;
01235   }
01236 
01237   if (_networking && !_network_server) {
01238     IConsoleWarning("Only the server can stop an AI.");
01239     return true;
01240   }
01241 
01242   CompanyID company_id = (CompanyID)(atoi(argv[1]) - 1);
01243   if (!Company::IsValidID(company_id)) {
01244     IConsolePrintF(CC_DEFAULT, "Unknown company. Company range is between 1 and %d.", MAX_COMPANIES);
01245     return true;
01246   }
01247 
01248   if (Company::IsHumanID(company_id) || company_id == _local_company) {
01249     IConsoleWarning("Company is not controlled by an AI.");
01250     return true;
01251   }
01252 
01253   /* Now kill the company of the AI. */
01254   DoCommandP(0, 2 | company_id << 16, CRR_MANUAL, CMD_COMPANY_CTRL);
01255   IConsolePrint(CC_DEFAULT, "AI stopped, company deleted.");
01256 
01257   return true;
01258 }
01259 
01260 DEF_CONSOLE_CMD(ConRescanAI)
01261 {
01262   if (argc == 0) {
01263     IConsoleHelp("Rescan the AI dir for scripts. Usage: 'rescan_ai'");
01264     return true;
01265   }
01266 
01267   if (_networking && !_network_server) {
01268     IConsoleWarning("Only the server can rescan the AI dir for scripts.");
01269     return true;
01270   }
01271 
01272   AI::Rescan();
01273 
01274   return true;
01275 }
01276 
01277 DEF_CONSOLE_CMD(ConRescanGame)
01278 {
01279   if (argc == 0) {
01280     IConsoleHelp("Rescan the Game Script dir for scripts. Usage: 'rescan_game'");
01281     return true;
01282   }
01283 
01284   if (_networking && !_network_server) {
01285     IConsoleWarning("Only the server can rescan the Game Script dir for scripts.");
01286     return true;
01287   }
01288 
01289   Game::Rescan();
01290 
01291   return true;
01292 }
01293 
01294 DEF_CONSOLE_CMD(ConRescanNewGRF)
01295 {
01296   if (argc == 0) {
01297     IConsoleHelp("Rescan the data dir for NewGRFs. Usage: 'rescan_newgrf'");
01298     return true;
01299   }
01300 
01301   ScanNewGRFFiles(NULL);
01302 
01303   return true;
01304 }
01305 
01306 DEF_CONSOLE_CMD(ConGetSeed)
01307 {
01308   if (argc == 0) {
01309     IConsoleHelp("Returns the seed used to create this game. Usage: 'getseed'");
01310     IConsoleHelp("The seed can be used to reproduce the exact same map as the game started with.");
01311     return true;
01312   }
01313 
01314   IConsolePrintF(CC_DEFAULT, "Generation Seed: %u", _settings_game.game_creation.generation_seed);
01315   return true;
01316 }
01317 
01318 DEF_CONSOLE_CMD(ConGetDate)
01319 {
01320   if (argc == 0) {
01321     IConsoleHelp("Returns the current date (day-month-year) of the game. Usage: 'getdate'");
01322     return true;
01323   }
01324 
01325   YearMonthDay ymd;
01326   ConvertDateToYMD(_date, &ymd);
01327   IConsolePrintF(CC_DEFAULT, "Date: %d-%d-%d", ymd.day, ymd.month + 1, ymd.year);
01328   return true;
01329 }
01330 
01331 
01332 DEF_CONSOLE_CMD(ConAlias)
01333 {
01334   IConsoleAlias *alias;
01335 
01336   if (argc == 0) {
01337     IConsoleHelp("Add a new alias, or redefine the behaviour of an existing alias . Usage: 'alias <name> <command>'");
01338     return true;
01339   }
01340 
01341   if (argc < 3) return false;
01342 
01343   alias = IConsoleAliasGet(argv[1]);
01344   if (alias == NULL) {
01345     IConsoleAliasRegister(argv[1], argv[2]);
01346   } else {
01347     free(alias->cmdline);
01348     alias->cmdline = strdup(argv[2]);
01349   }
01350   return true;
01351 }
01352 
01353 DEF_CONSOLE_CMD(ConScreenShot)
01354 {
01355   if (argc == 0) {
01356     IConsoleHelp("Create a screenshot of the game. Usage: 'screenshot [big | giant | no_con] [file name]'");
01357     IConsoleHelp("'big' makes a zoomed-in screenshot of the visible area, 'giant' makes a screenshot of the "
01358         "whole map, 'no_con' hides the console to create the screenshot. 'big' or 'giant' "
01359         "screenshots are always drawn without console");
01360     return true;
01361   }
01362 
01363   if (argc > 3) return false;
01364 
01365   ScreenshotType type = SC_VIEWPORT;
01366   const char *name = NULL;
01367 
01368   if (argc > 1) {
01369     if (strcmp(argv[1], "big") == 0) {
01370       /* screenshot big [filename] */
01371       type = SC_ZOOMEDIN;
01372       if (argc > 2) name = argv[2];
01373     } else if (strcmp(argv[1], "giant") == 0) {
01374       /* screenshot giant [filename] */
01375       type = SC_WORLD;
01376       if (argc > 2) name = argv[2];
01377     } else if (strcmp(argv[1], "no_con") == 0) {
01378       /* screenshot no_con [filename] */
01379       IConsoleClose();
01380       if (argc > 2) name = argv[2];
01381     } else if (argc == 2) {
01382       /* screenshot filename */
01383       name = argv[1];
01384     } else {
01385       /* screenshot argv[1] argv[2] - invalid */
01386       return false;
01387     }
01388   }
01389 
01390   MakeScreenshot(type, name);
01391   return true;
01392 }
01393 
01394 DEF_CONSOLE_CMD(ConInfoCmd)
01395 {
01396   if (argc == 0) {
01397     IConsoleHelp("Print out debugging information about a command. Usage: 'info_cmd <cmd>'");
01398     return true;
01399   }
01400 
01401   if (argc < 2) return false;
01402 
01403   const IConsoleCmd *cmd = IConsoleCmdGet(argv[1]);
01404   if (cmd == NULL) {
01405     IConsoleError("the given command was not found");
01406     return true;
01407   }
01408 
01409   IConsolePrintF(CC_DEFAULT, "command name: %s", cmd->name);
01410   IConsolePrintF(CC_DEFAULT, "command proc: %p", cmd->proc);
01411 
01412   if (cmd->hook != NULL) IConsoleWarning("command is hooked");
01413 
01414   return true;
01415 }
01416 
01417 DEF_CONSOLE_CMD(ConDebugLevel)
01418 {
01419   if (argc == 0) {
01420     IConsoleHelp("Get/set the default debugging level for the game. Usage: 'debug_level [<level>]'");
01421     IConsoleHelp("Level can be any combination of names, levels. Eg 'net=5 ms=4'. Remember to enclose it in \"'s");
01422     return true;
01423   }
01424 
01425   if (argc > 2) return false;
01426 
01427   if (argc == 1) {
01428     IConsolePrintF(CC_DEFAULT, "Current debug-level: '%s'", GetDebugString());
01429   } else {
01430     SetDebugString(argv[1]);
01431   }
01432 
01433   return true;
01434 }
01435 
01436 DEF_CONSOLE_CMD(ConExit)
01437 {
01438   if (argc == 0) {
01439     IConsoleHelp("Exit the game. Usage: 'exit'");
01440     return true;
01441   }
01442 
01443   if (_game_mode == GM_NORMAL && _settings_client.gui.autosave_on_exit) DoExitSave();
01444 
01445   _exit_game = true;
01446   return true;
01447 }
01448 
01449 DEF_CONSOLE_CMD(ConPart)
01450 {
01451   if (argc == 0) {
01452     IConsoleHelp("Leave the currently joined/running game (only ingame). Usage: 'part'");
01453     return true;
01454   }
01455 
01456   if (_game_mode != GM_NORMAL) return false;
01457 
01458   _switch_mode = SM_MENU;
01459   return true;
01460 }
01461 
01462 DEF_CONSOLE_CMD(ConHelp)
01463 {
01464   if (argc == 2) {
01465     const IConsoleCmd *cmd;
01466     const IConsoleAlias *alias;
01467 
01468     RemoveUnderscores(argv[1]);
01469     cmd = IConsoleCmdGet(argv[1]);
01470     if (cmd != NULL) {
01471       cmd->proc(0, NULL);
01472       return true;
01473     }
01474 
01475     alias = IConsoleAliasGet(argv[1]);
01476     if (alias != NULL) {
01477       cmd = IConsoleCmdGet(alias->cmdline);
01478       if (cmd != NULL) {
01479         cmd->proc(0, NULL);
01480         return true;
01481       }
01482       IConsolePrintF(CC_ERROR, "ERROR: alias is of special type, please see its execution-line: '%s'", alias->cmdline);
01483       return true;
01484     }
01485 
01486     IConsoleError("command not found");
01487     return true;
01488   }
01489 
01490   IConsolePrint(CC_WARNING, " ---- OpenTTD Console Help ---- ");
01491   IConsolePrint(CC_DEFAULT, " - commands: [command to list all commands: list_cmds]");
01492   IConsolePrint(CC_DEFAULT, " call commands with '<command> <arg2> <arg3>...'");
01493   IConsolePrint(CC_DEFAULT, " - to assign strings, or use them as arguments, enclose it within quotes");
01494   IConsolePrint(CC_DEFAULT, " like this: '<command> \"string argument with spaces\"'");
01495   IConsolePrint(CC_DEFAULT, " - use 'help <command>' to get specific information");
01496   IConsolePrint(CC_DEFAULT, " - scroll console output with shift + (up | down | pageup | pagedown)");
01497   IConsolePrint(CC_DEFAULT, " - scroll console input history with the up or down arrows");
01498   IConsolePrint(CC_DEFAULT, "");
01499   return true;
01500 }
01501 
01502 DEF_CONSOLE_CMD(ConListCommands)
01503 {
01504   if (argc == 0) {
01505     IConsoleHelp("List all registered commands. Usage: 'list_cmds [<pre-filter>]'");
01506     return true;
01507   }
01508 
01509   for (const IConsoleCmd *cmd = _iconsole_cmds; cmd != NULL; cmd = cmd->next) {
01510     if (argv[1] == NULL || strstr(cmd->name, argv[1]) != NULL) {
01511       if (cmd->hook == NULL || cmd->hook(false) != CHR_HIDE) IConsolePrintF(CC_DEFAULT, "%s", cmd->name);
01512     }
01513   }
01514 
01515   return true;
01516 }
01517 
01518 DEF_CONSOLE_CMD(ConListAliases)
01519 {
01520   if (argc == 0) {
01521     IConsoleHelp("List all registered aliases. Usage: 'list_aliases [<pre-filter>]'");
01522     return true;
01523   }
01524 
01525   for (const IConsoleAlias *alias = _iconsole_aliases; alias != NULL; alias = alias->next) {
01526     if (argv[1] == NULL || strstr(alias->name, argv[1]) != NULL) {
01527       IConsolePrintF(CC_DEFAULT, "%s => %s", alias->name, alias->cmdline);
01528     }
01529   }
01530 
01531   return true;
01532 }
01533 
01534 #ifdef ENABLE_NETWORK
01535 
01536 DEF_CONSOLE_CMD(ConSay)
01537 {
01538   if (argc == 0) {
01539     IConsoleHelp("Chat to your fellow players in a multiplayer game. Usage: 'say \"<msg>\"'");
01540     return true;
01541   }
01542 
01543   if (argc != 2) return false;
01544 
01545   if (!_network_server) {
01546     NetworkClientSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 /* param does not matter */, argv[1]);
01547   } else {
01548     bool from_admin = (_redirect_console_to_admin < INVALID_ADMIN_ID);
01549     NetworkServerSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], CLIENT_ID_SERVER, from_admin);
01550   }
01551 
01552   return true;
01553 }
01554 
01555 DEF_CONSOLE_CMD(ConCompanies)
01556 {
01557   if (argc == 0) {
01558     IConsoleHelp("List the in-game details of all clients connected to the server. Usage 'companies'");
01559     return true;
01560   }
01561   NetworkCompanyStats company_stats[MAX_COMPANIES];
01562   NetworkPopulateCompanyStats(company_stats);
01563 
01564   Company *c;
01565   FOR_ALL_COMPANIES(c) {
01566     /* Grab the company name */
01567     char company_name[NETWORK_COMPANY_NAME_LENGTH];
01568     SetDParam(0, c->index);
01569     GetString(company_name, STR_COMPANY_NAME, lastof(company_name));
01570 
01571     char buffer[512];
01572     const NetworkCompanyStats *stats = &company_stats[c->index];
01573 
01574     GetString(buffer, STR_COLOUR_DARK_BLUE + _company_colours[c->index], lastof(buffer));
01575     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) %sprotected",
01576       c->index + 1, buffer, company_name, c->inaugurated_year, (int64)c->money, (int64)c->current_loan, (int64)CalculateCompanyValue(c),
01577       /* trains      */ stats->num_vehicle[0],
01578       /* lorry + bus */ stats->num_vehicle[1] + stats->num_vehicle[2],
01579       /* planes      */ stats->num_vehicle[3],
01580       /* ships       */ stats->num_vehicle[4],
01581       /* protected   */ StrEmpty(_network_company_states[c->index].password) ? "un" : "");
01582   }
01583 
01584   return true;
01585 }
01586 
01587 DEF_CONSOLE_CMD(ConSayCompany)
01588 {
01589   if (argc == 0) {
01590     IConsoleHelp("Chat to a certain company in a multiplayer game. Usage: 'say_company <company-no> \"<msg>\"'");
01591     IConsoleHelp("CompanyNo is the company that plays as company <companyno>, 1 through max_companies");
01592     return true;
01593   }
01594 
01595   if (argc != 3) return false;
01596 
01597   CompanyID company_id = (CompanyID)(atoi(argv[1]) - 1);
01598   if (!Company::IsValidID(company_id)) {
01599     IConsolePrintF(CC_DEFAULT, "Unknown company. Company range is between 1 and %d.", MAX_COMPANIES);
01600     return true;
01601   }
01602 
01603   if (!_network_server) {
01604     NetworkClientSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, company_id, argv[2]);
01605   } else {
01606     bool from_admin = (_redirect_console_to_admin < INVALID_ADMIN_ID);
01607     NetworkServerSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, company_id, argv[2], CLIENT_ID_SERVER, from_admin);
01608   }
01609 
01610   return true;
01611 }
01612 
01613 DEF_CONSOLE_CMD(ConSayClient)
01614 {
01615   if (argc == 0) {
01616     IConsoleHelp("Chat to a certain client in a multiplayer game. Usage: 'say_client <client-no> \"<msg>\"'");
01617     IConsoleHelp("For client-id's, see the command 'clients'");
01618     return true;
01619   }
01620 
01621   if (argc != 3) return false;
01622 
01623   if (!_network_server) {
01624     NetworkClientSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
01625   } else {
01626     bool from_admin = (_redirect_console_to_admin < INVALID_ADMIN_ID);
01627     NetworkServerSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], CLIENT_ID_SERVER, from_admin);
01628   }
01629 
01630   return true;
01631 }
01632 
01633 DEF_CONSOLE_CMD(ConCompanyPassword)
01634 {
01635   if (argc == 0) {
01636     const char *helpmsg;
01637 
01638     if (_network_dedicated) {
01639       helpmsg = "Change the password of a company. Usage: 'company_pw <company-no> \"<password>\"";
01640     } else if (_network_server) {
01641       helpmsg = "Change the password of your or any other company. Usage: 'company_pw [<company-no>] \"<password>\"'";
01642     } else {
01643       helpmsg = "Change the password of your company. Usage: 'company_pw \"<password>\"'";
01644     }
01645 
01646     IConsoleHelp(helpmsg);
01647     IConsoleHelp("Use \"*\" to disable the password.");
01648     return true;
01649   }
01650 
01651   CompanyID company_id;
01652   const char *password;
01653   const char *errormsg;
01654 
01655   if (argc == 2) {
01656     company_id = _local_company;
01657     password = argv[1];
01658     errormsg = "You have to own a company to make use of this command.";
01659   } else if (argc == 3 && _network_server) {
01660     company_id = (CompanyID)(atoi(argv[1]) - 1);
01661     password = argv[2];
01662     errormsg = "You have to specify the ID of a valid human controlled company.";
01663   } else {
01664     return false;
01665   }
01666 
01667   if (!Company::IsValidHumanID(company_id)) {
01668     IConsoleError(errormsg);
01669     return false;
01670   }
01671 
01672   password = NetworkChangeCompanyPassword(company_id, password);
01673 
01674   if (StrEmpty(password)) {
01675     IConsolePrintF(CC_WARNING, "Company password cleared");
01676   } else {
01677     IConsolePrintF(CC_WARNING, "Company password changed to: %s", password);
01678   }
01679 
01680   return true;
01681 }
01682 
01683 /* Content downloading only is available with ZLIB */
01684 #if defined(WITH_ZLIB)
01685 #include "network/network_content.h"
01686 
01688 static ContentType StringToContentType(const char *str)
01689 {
01690   static const char * const inv_lookup[] = { "", "base", "newgrf", "ai", "ailib", "scenario", "heightmap" };
01691   for (uint i = 1 /* there is no type 0 */; i < lengthof(inv_lookup); i++) {
01692     if (strcasecmp(str, inv_lookup[i]) == 0) return (ContentType)i;
01693   }
01694   return CONTENT_TYPE_END;
01695 }
01696 
01698 struct ConsoleContentCallback : public ContentCallback {
01699   void OnConnect(bool success)
01700   {
01701     IConsolePrintF(CC_DEFAULT, "Content server connection %s", success ? "established" : "failed");
01702   }
01703 
01704   void OnDisconnect()
01705   {
01706     IConsolePrintF(CC_DEFAULT, "Content server connection closed");
01707   }
01708 
01709   void OnDownloadComplete(ContentID cid)
01710   {
01711     IConsolePrintF(CC_DEFAULT, "Completed download of %d", cid);
01712   }
01713 };
01714 
01715 DEF_CONSOLE_CMD(ConContent)
01716 {
01717   static ContentCallback *cb = NULL;
01718   if (cb == NULL) {
01719     cb = new ConsoleContentCallback();
01720     _network_content_client.AddCallback(cb);
01721   }
01722 
01723   if (argc <= 1) {
01724     IConsoleHelp("Query, select and download content. Usage: 'content update|upgrade|select [all|id]|unselect [all|id]|state|download'");
01725     IConsoleHelp("  update: get a new list of downloadable content; must be run first");
01726     IConsoleHelp("  upgrade: select all items that are upgrades");
01727     IConsoleHelp("  select: select a specific item given by its id or 'all' to select all");
01728     IConsoleHelp("  unselect: unselect a specific item given by its id or 'all' to unselect all");
01729     IConsoleHelp("  state: show the download/select state of all downloadable content");
01730     IConsoleHelp("  download: download all content you've selected");
01731     return true;
01732   }
01733 
01734   if (strcasecmp(argv[1], "update") == 0) {
01735     _network_content_client.RequestContentList((argc > 2) ? StringToContentType(argv[2]) : CONTENT_TYPE_END);
01736     return true;
01737   }
01738 
01739   if (strcasecmp(argv[1], "upgrade") == 0) {
01740     _network_content_client.SelectUpgrade();
01741     return true;
01742   }
01743 
01744   if (strcasecmp(argv[1], "select") == 0) {
01745     if (argc <= 2) {
01746       IConsoleError("You must enter the id.");
01747       return false;
01748     }
01749     if (strcasecmp(argv[2], "all") == 0) {
01750       _network_content_client.SelectAll();
01751     } else {
01752       _network_content_client.Select((ContentID)atoi(argv[2]));
01753     }
01754     return true;
01755   }
01756 
01757   if (strcasecmp(argv[1], "unselect") == 0) {
01758     if (argc <= 2) {
01759       IConsoleError("You must enter the id.");
01760       return false;
01761     }
01762     if (strcasecmp(argv[2], "all") == 0) {
01763       _network_content_client.UnselectAll();
01764     } else {
01765       _network_content_client.Unselect((ContentID)atoi(argv[2]));
01766     }
01767     return true;
01768   }
01769 
01770   if (strcasecmp(argv[1], "state") == 0) {
01771     IConsolePrintF(CC_WHITE, "id, type, state, name");
01772     for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) {
01773       static const char * const types[] = { "Base graphics", "NewGRF", "AI", "AI library", "Scenario", "Heightmap", "Base sound", "Base music", "Game script", "GS library" };
01774       assert_compile(lengthof(types) == CONTENT_TYPE_END - CONTENT_TYPE_BEGIN);
01775       static const char * const states[] = { "Not selected", "Selected", "Dep Selected", "Installed", "Unknown" };
01776       static const TextColour state_to_colour[] = { CC_COMMAND, CC_INFO, CC_INFO, CC_WHITE, CC_ERROR };
01777 
01778       const ContentInfo *ci = *iter;
01779       IConsolePrintF(state_to_colour[ci->state], "%d, %s, %s, %s", ci->id, types[ci->type - 1], states[ci->state], ci->name);
01780     }
01781     return true;
01782   }
01783 
01784   if (strcasecmp(argv[1], "download") == 0) {
01785     uint files;
01786     uint bytes;
01787     _network_content_client.DownloadSelectedContent(files, bytes);
01788     IConsolePrintF(CC_DEFAULT, "Downloading %d file(s) (%d bytes)", files, bytes);
01789     return true;
01790   }
01791 
01792   return false;
01793 }
01794 #endif /* defined(WITH_ZLIB) */
01795 #endif /* ENABLE_NETWORK */
01796 
01797 DEF_CONSOLE_CMD(ConSetting)
01798 {
01799   if (argc == 0) {
01800     IConsoleHelp("Change setting for all clients. Usage: 'setting <name> [<value>]'");
01801     IConsoleHelp("Omitting <value> will print out the current value of the setting.");
01802     return true;
01803   }
01804 
01805   if (argc == 1 || argc > 3) return false;
01806 
01807   if (argc == 2) {
01808     IConsoleGetSetting(argv[1]);
01809   } else {
01810     IConsoleSetSetting(argv[1], argv[2]);
01811   }
01812 
01813   return true;
01814 }
01815 
01816 DEF_CONSOLE_CMD(ConSettingNewgame)
01817 {
01818   if (argc == 0) {
01819     IConsoleHelp("Change setting for the next game. Usage: 'setting_newgame <name> [<value>]'");
01820     IConsoleHelp("Omitting <value> will print out the current value of the setting.");
01821     return true;
01822   }
01823 
01824   if (argc == 1 || argc > 3) return false;
01825 
01826   if (argc == 2) {
01827     IConsoleGetSetting(argv[1], true);
01828   } else {
01829     IConsoleSetSetting(argv[1], argv[2], true);
01830   }
01831 
01832   return true;
01833 }
01834 
01835 DEF_CONSOLE_CMD(ConListSettings)
01836 {
01837   if (argc == 0) {
01838     IConsoleHelp("List settings. Usage: 'list_settings [<pre-filter>]'");
01839     return true;
01840   }
01841 
01842   if (argc > 2) return false;
01843 
01844   IConsoleListSettings((argc == 2) ? argv[1] : NULL);
01845   return true;
01846 }
01847 
01848 DEF_CONSOLE_CMD(ConGamelogPrint)
01849 {
01850   GamelogPrintConsole();
01851   return true;
01852 }
01853 
01854 DEF_CONSOLE_CMD(ConNewGRFReload)
01855 {
01856   if (argc == 0) {
01857     IConsoleHelp("Reloads all active NewGRFs from disk. Equivalent to reapplying NewGRFs via the settings, but without asking for confirmation. This might crash OpenTTD!");
01858     return true;
01859   }
01860 
01861   ReloadNewGRFData();
01862   return true;
01863 }
01864 
01865 #ifdef _DEBUG
01866 /******************
01867  *  debug commands
01868  ******************/
01869 
01870 static void IConsoleDebugLibRegister()
01871 {
01872   IConsoleCmdRegister("resettile",        ConResetTile);
01873   IConsoleAliasRegister("dbg_echo",       "echo %A; echo %B");
01874   IConsoleAliasRegister("dbg_echo2",      "echo %!");
01875 }
01876 #endif
01877 
01878 /*******************************
01879  * console command registration
01880  *******************************/
01881 
01882 void IConsoleStdLibRegister()
01883 {
01884   IConsoleCmdRegister("debug_level",  ConDebugLevel);
01885   IConsoleCmdRegister("echo",         ConEcho);
01886   IConsoleCmdRegister("echoc",        ConEchoC);
01887   IConsoleCmdRegister("exec",         ConExec);
01888   IConsoleCmdRegister("exit",         ConExit);
01889   IConsoleCmdRegister("part",         ConPart);
01890   IConsoleCmdRegister("help",         ConHelp);
01891   IConsoleCmdRegister("info_cmd",     ConInfoCmd);
01892   IConsoleCmdRegister("list_cmds",    ConListCommands);
01893   IConsoleCmdRegister("list_aliases", ConListAliases);
01894   IConsoleCmdRegister("newgame",      ConNewGame);
01895   IConsoleCmdRegister("restart",      ConRestart);
01896   IConsoleCmdRegister("getseed",      ConGetSeed);
01897   IConsoleCmdRegister("getdate",      ConGetDate);
01898   IConsoleCmdRegister("quit",         ConExit);
01899   IConsoleCmdRegister("resetengines", ConResetEngines, ConHookNoNetwork);
01900   IConsoleCmdRegister("reset_enginepool", ConResetEnginePool, ConHookNoNetwork);
01901   IConsoleCmdRegister("return",       ConReturn);
01902   IConsoleCmdRegister("screenshot",   ConScreenShot);
01903   IConsoleCmdRegister("script",       ConScript);
01904   IConsoleCmdRegister("scrollto",     ConScrollToTile);
01905   IConsoleCmdRegister("alias",        ConAlias);
01906   IConsoleCmdRegister("load",         ConLoad);
01907   IConsoleCmdRegister("rm",           ConRemove);
01908   IConsoleCmdRegister("save",         ConSave);
01909   IConsoleCmdRegister("saveconfig",   ConSaveConfig);
01910   IConsoleCmdRegister("ls",           ConListFiles);
01911   IConsoleCmdRegister("cd",           ConChangeDirectory);
01912   IConsoleCmdRegister("pwd",          ConPrintWorkingDirectory);
01913   IConsoleCmdRegister("clear",        ConClearBuffer);
01914   IConsoleCmdRegister("setting",      ConSetting);
01915   IConsoleCmdRegister("setting_newgame", ConSettingNewgame);
01916   IConsoleCmdRegister("list_settings",ConListSettings);
01917   IConsoleCmdRegister("gamelog",      ConGamelogPrint);
01918   IConsoleCmdRegister("rescan_newgrf", ConRescanNewGRF);
01919 
01920   IConsoleAliasRegister("dir",          "ls");
01921   IConsoleAliasRegister("del",          "rm %+");
01922   IConsoleAliasRegister("newmap",       "newgame");
01923   IConsoleAliasRegister("patch",        "setting %+");
01924   IConsoleAliasRegister("set",          "setting %+");
01925   IConsoleAliasRegister("set_newgame",  "setting_newgame %+");
01926   IConsoleAliasRegister("list_patches", "list_settings %+");
01927   IConsoleAliasRegister("developer",    "setting developer %+");
01928 
01929   IConsoleCmdRegister("list_ai_libs", ConListAILibs);
01930   IConsoleCmdRegister("list_ai",      ConListAI);
01931   IConsoleCmdRegister("reload_ai",    ConReloadAI);
01932   IConsoleCmdRegister("rescan_ai",    ConRescanAI);
01933   IConsoleCmdRegister("start_ai",     ConStartAI);
01934   IConsoleCmdRegister("stop_ai",      ConStopAI);
01935 
01936   IConsoleCmdRegister("list_game",    ConListGame);
01937   IConsoleCmdRegister("list_game_libs", ConListGameLibs);
01938   IConsoleCmdRegister("rescan_game",    ConRescanGame);
01939 
01940   /* networking functions */
01941 #ifdef ENABLE_NETWORK
01942 /* Content downloading is only available with ZLIB */
01943 #if defined(WITH_ZLIB)
01944   IConsoleCmdRegister("content",         ConContent);
01945 #endif /* defined(WITH_ZLIB) */
01946 
01947   /*** Networking commands ***/
01948   IConsoleCmdRegister("say",             ConSay, ConHookNeedNetwork);
01949   IConsoleCmdRegister("companies",       ConCompanies, ConHookServerOnly);
01950   IConsoleAliasRegister("players",       "companies");
01951   IConsoleCmdRegister("say_company",     ConSayCompany, ConHookNeedNetwork);
01952   IConsoleAliasRegister("say_player",    "say_company %+");
01953   IConsoleCmdRegister("say_client",      ConSayClient, ConHookNeedNetwork);
01954 
01955   IConsoleCmdRegister("connect",         ConNetworkConnect, ConHookClientOnly);
01956   IConsoleCmdRegister("clients",         ConNetworkClients, ConHookNeedNetwork);
01957   IConsoleCmdRegister("status",          ConStatus, ConHookServerOnly);
01958   IConsoleCmdRegister("server_info",     ConServerInfo, ConHookServerOnly);
01959   IConsoleAliasRegister("info",          "server_info");
01960   IConsoleCmdRegister("reconnect",       ConNetworkReconnect, ConHookClientOnly);
01961   IConsoleCmdRegister("rcon",            ConRcon, ConHookNeedNetwork);
01962 
01963   IConsoleCmdRegister("join",            ConJoinCompany, ConHookNeedNetwork);
01964   IConsoleAliasRegister("spectate",      "join 255");
01965   IConsoleCmdRegister("move",            ConMoveClient, ConHookServerOnly);
01966   IConsoleCmdRegister("reset_company",   ConResetCompany, ConHookServerOnly);
01967   IConsoleAliasRegister("clean_company", "reset_company %A");
01968   IConsoleCmdRegister("client_name",     ConClientNickChange, ConHookServerOnly);
01969   IConsoleCmdRegister("kick",            ConKick, ConHookServerOnly);
01970   IConsoleCmdRegister("ban",             ConBan, ConHookServerOnly);
01971   IConsoleCmdRegister("unban",           ConUnBan, ConHookServerOnly);
01972   IConsoleCmdRegister("banlist",         ConBanList, ConHookServerOnly);
01973 
01974   IConsoleCmdRegister("pause",           ConPauseGame, ConHookServerOnly);
01975   IConsoleCmdRegister("unpause",         ConUnpauseGame, ConHookServerOnly);
01976 
01977   IConsoleCmdRegister("company_pw",      ConCompanyPassword, ConHookNeedNetwork);
01978   IConsoleAliasRegister("company_password",      "company_pw %+");
01979 
01980   IConsoleAliasRegister("net_frame_freq",        "setting frame_freq %+");
01981   IConsoleAliasRegister("net_sync_freq",         "setting sync_freq %+");
01982   IConsoleAliasRegister("server_pw",             "setting server_password %+");
01983   IConsoleAliasRegister("server_password",       "setting server_password %+");
01984   IConsoleAliasRegister("rcon_pw",               "setting rcon_password %+");
01985   IConsoleAliasRegister("rcon_password",         "setting rcon_password %+");
01986   IConsoleAliasRegister("name",                  "setting client_name %+");
01987   IConsoleAliasRegister("server_name",           "setting server_name %+");
01988   IConsoleAliasRegister("server_port",           "setting server_port %+");
01989   IConsoleAliasRegister("server_advertise",      "setting server_advertise %+");
01990   IConsoleAliasRegister("max_clients",           "setting max_clients %+");
01991   IConsoleAliasRegister("max_companies",         "setting max_companies %+");
01992   IConsoleAliasRegister("max_spectators",        "setting max_spectators %+");
01993   IConsoleAliasRegister("max_join_time",         "setting max_join_time %+");
01994   IConsoleAliasRegister("pause_on_join",         "setting pause_on_join %+");
01995   IConsoleAliasRegister("autoclean_companies",   "setting autoclean_companies %+");
01996   IConsoleAliasRegister("autoclean_protected",   "setting autoclean_protected %+");
01997   IConsoleAliasRegister("autoclean_unprotected", "setting autoclean_unprotected %+");
01998   IConsoleAliasRegister("restart_game_year",     "setting restart_game_year %+");
01999   IConsoleAliasRegister("min_players",           "setting min_active_clients %+");
02000   IConsoleAliasRegister("reload_cfg",            "setting reload_cfg %+");
02001 #endif /* ENABLE_NETWORK */
02002 
02003   /* debugging stuff */
02004 #ifdef _DEBUG
02005   IConsoleDebugLibRegister();
02006 #endif
02007 
02008   /* NewGRF development stuff */
02009   IConsoleCmdRegister("reload_newgrfs",  ConNewGRFReload, ConHookNewGRFDeveloperTool);
02010 }